发布于 

读《规则引擎:大厂营销系统资格设计全解》关于资格判断设计的思考

前几天读了《规则引擎:大厂营销系统资格设计全解》,里面对于静态资格、动态资格的设计,虽然叫法名称不同,但与我们目前在做的营销管理系统设计从业务以及逻辑流程上很相似,然而做得更优雅更抽象。

具体而言

静态资格的判断

在进行静态资格判断时,我们系统目前是将每一个活动的静态资格做成一个drools脚本,对于一个触发用户,需要使用他的标签数据去执行每一个活动的规则脚本来判断是否满足静态资格条件,也就是我们所定义的客群入主条件。而在作者所在的公司做的营销系统,将所有活动的规则组合成一个具有分支的drools脚本,一个用户只需要执行一个脚本就能知道他满足哪些活动条件。

从业务角度来看,其实我们目前的做法不能说不好,更符合我们公司目前活动模式以及比较复杂的规则配置,并且,将所有活动的客群规则组合成一个规则脚本,其实是对规则做了限制,要求活动的规则是有顺序性,不如我们目前的做法灵活。但是,可以参考这种思路做一个资格服务,上游系统直接使用用户ID即可查出该用户有资格参与的所有活动,那就补充了我们系统中遗漏的一块,用户可以在参与活动前就查询自己是否有资格参与,而不是被动的等待系统触达。

动态资格的判断

文章中的动态资格,在我们的系统中被认为是一个权益的脱频设计。

相对而言,我们目前的脱频设计会更粗糙,仅仅针对某个活动下人维度+时间维度的脱频,没有针对活动维度以及权益自身的资格限制。也就是说,我可以配置一个人在活动A中,每周、每月、每年、整个活动周期中最多能获取的权益数目,但是不能配置整个活动A每周、每月、每年、整个活动周期内最多能发放的权益数目。
同时,没有做缓存,每次需要对用户发放权益时,都需要实时计算他已经发放了多少,再算出他还能发放多少(从权益角度而言我们的设计会更复杂,不仅需要考虑数量,还需要考虑限制金额)。虽然目前的数据量情况下影响不大,但是这是一个需要优化的点,需要将动态资格(按维度已经领取的,最多能领取的)数据缓存到redis。

此外,代码写得太丑,没有层级,没有抽象,仅仅满足业务需求。

所以,最近几天在思考如何对脱频(也就是动态资格)的实现再做设计和优化。目前想到的优化点:

  1. 权益的动态资格限制可以按维度、周期和总额来多次限制。维度分为活动、计划、人、以及权益自身;周期分为自然日、周、月、年、用久。那么我在配置一个权益的时候,比如腾讯视频会员,可以限制它每个活动一年最多发放1000个,总共加起来一年不能超过10000个,每个人每个月不能超过一个….等等;
  2. 可以将每个维度、周期当前已经发放的权益写进redis,这样不需要在发放的时候再通过流水实时计算已经发放了多少,直接从redis获取并更新数量。

由于业务的复杂性,针对上面的两点优化,还是有很多难点。比如:

  • 权益所属月份、或自然天、自然年,由于实际活动中,会有当前月发放的权益却要求它属于上一个月(或其他月)的场景,那么我们在判断动态资格的时候,还要先根据配置以及系统时间(或触发时间)来计算实际权益所属周期
  • 由于有人的维度,所以人维度key的数量 = 用户数 * 周期数,以天来算,100万用户,一年下来,每个用户都要保存365天每一天的数据,key的数量会很吓人。这里考虑几个点:
    1. 用redis做缓存的话,有效期设为多少?会不会有需求发放的权益是一年前的,结果要我去找一年前某一天这个用户发放了多少然后再做资格判断?这种情况怎么处理;
    2. 如果缓存数据需要落到数据库,那么选hbase还是mysql?数据量如何评估?分别有什么优缺点?
  • 假如业务在刚开始的时候,没有对某个维度某个周期的数量做限制,然后后期突然又要加上限制了,那么之前已经发放的数据是否还要计算在内呢。如果不计在内从代码实现上来说比较简单,数据量也会大大减少,但是业务不一定接受;如果要计算在内,那么,不管是否有配置,都需要把每个维度、每个周期的发放数量记录下来,这样就有大量的数据冗余,也许业务永远都用不上…

真是个复杂的问题,容我再好好想想。