大营销
第三节:策略概率装配处理
装配流程
-
装配抽奖策略,根据抽奖策略ID(strategy_id)进行装配
-
子流程如下:
-
根据抽奖策略ID(strategy_id)去数据库查询该策略配置下的奖品列表(strategyAwardEntityList),先从redis中读,如果redis中没有,再去数据库中拿,拿完转完一下实体类,存redis中,并返回这个奖品列表
-
拿到奖品列表后,进行第一次装配(此时没有根据权重规则过滤奖品),在redis中存的是该策略ID(strategy_id)下所有的奖品列表。
-
装配子流程:需要一个key(strategy_id),一个奖品列表实体类
-
拿最小概率值(方便后续计算)
-
拿概率值总和(所有的概率加一起,后面计算用)
-
获得概率范围,就是用概率总和除以这个最小概率值,向正无穷取整,算出来个大小范围,比如100.0/0.1 就是1000。就是相当于把小数点给去掉,得出来一个范围(0-1000)
-
生成策略概率查找表,生成一个list,大小就是上面的范围大小,然后根据相应的规则向里面填充奖品ID,比如奖品1占10%,就填充100个(以1000为例),把这个list填满。
-
然后乱序处理,交换各个元素的位置,保证它们的随机性,不然抽奖概率会有影响
-
生成一个map,奖品查找表,其实就是把这个list放到map里,key值是 list的大小从小到大,value值是奖品id
-
最后把这个map存放到redis中,这一步有一个putall操作,如果你的redis报了一个(org.springframework.dao.InvalidDataAccessApiUsageException: ERR Protocol error: invalid multibulk length.)这种异常(windows 环境下 一个老版本的 redis 报的,mac 环境下redis版本 7.2.3 没有报,一切正常)可以试试把概率改小,map小一点,我这个改成了小数点后一位就正常了,可能是redis配置或者版本的问题。
-
-
-
装配权重策略,根据这个id去数据库里查,优先查redis,没有再去数据库查,查完存redis并返回 (StrategyEntity)这个实体类
- 从ruleModels中遍历看是否有"rule_weight"这个规则,有就是需要权重过滤,没有,为null直接结束
-
再次验证规则是否有异常,走到这一步是一定有 rule_weight的,如果根据id和ruleWeight查询不到,抛出异常,流程异常结束
-
根据权重规则,重新装配奖品
- 首先拿到 rule_weight 下所有的规则,4000分的规则,5000分的规则等等
- 就是这一串(4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109)
- 把规则分割一下,key:(4000:102,103,104,105),value:([102],[103],[104],[105]),value是该规则下所有的奖品id,返回一个map<key,value>
- 遍历这个map,每个key下都有list奖品列表,从第一步装配的(strategyAwardEntityList)克隆一个新的list,从中移除 list奖品 中没有的
- 把这个克隆的新的list重新装配进redis中,参考装配子流程
-
装配结束(此时redis中key如下)
127.0.0.1:6379> keys *
"big_market_strategy_award_key_100001"
"big_market_strategy_rate_table_key_100001_5000:102,103,104,105,106,107"
"big_market_strategy_rate_table_key_100001_4000:102,103,104,105"
"big_market_strategy_rate_range_key_100001_5000:102,103,104,105,106,107"
"big_market_strategy_rate_table_key_100001_6000:102,103,104,105,106,107,108,109"
抽奖流程
24-04-22.21:07:53.724 [main ] INFO StrategyArmoryDispatch - rateRange:6
24-04-22.21:07:53.728 [main ] INFO StrategyArmoryDispatch - key:100001_4000:102,103,104,105, result:105
24-04-22.21:07:53.728 [main ] INFO StrategyTest - 测试结果:105 - 4000 策略配置
24-04-22.21:07:53.729 [main ] INFO StrategyArmoryDispatch - rateRange:14
24-04-22.21:07:53.729 [main ] INFO StrategyArmoryDispatch - key:100001_5000:102,103,104,105,106,107, result:106
24-04-22.21:07:53.729 [main ] INFO StrategyTest - 测试结果:106 - 5000 策略配置
24-04-22.21:07:53.729 [main ] INFO StrategyArmoryDispatch - rateRange:4901
24-04-22.21:07:53.730 [main ] INFO StrategyArmoryDispatch - key:100001_6000:102,103,104,105,106,107,108,109, result:107
24-04-22.21:07:53.730 [main ] INFO StrategyTest - 测试结果:107 - 6000 策略配置
抽奖流程需要知道,抽奖的策略ID(strategyId),还有抽奖的规则(ruleWeightValue)
- 拼接出来redis的key,就是id+规则
- 从redis中拿(自动拼接big_market_strategy_rate_range_key_)这个 map 中存储的是生成的随机数,以及该策略 id 下 map 的大小(rateRange),根据 key从 redis中拿到一个概率范围rateRange
- 随机获取 0-rateRange 之间的值,根据key(自动拼接big_market_strategy_rate_table_key_ ) 和生成的随机数从 map 中拿到奖品 id并返回