奖品抽取逻辑的实现汇总+主观点评

目前公司各个项目中,有一些奖品抽取的实现逻辑,不尽想同。下面的进行列举,并进行主观点评:
1、idGreedy


image.png

image.png

抽取的思路为,

1)按不同的模式(普通、大奖、低概率(21年10月已废弃)),获取对应的一套所有物品的抽取概率配置(物品概率,配置为整数,作为分子。所有物品的整数之和作为分母)

2)获取[0, 整数之和)的随机数,落到的区间对应的物品,为抽取到的物品

优点:真实地按概率进行抽取,每局有能力完全独立进行抽取(因为有些防亏损逻辑,导致不能独立)

不足与风险:

纯使用概率不能满足业务,常常会补充各种辅助逻辑,使得最终的的逻辑难以理解:1)不同模式都有各自的开启条件,2)不同模式下,有各自判断达到亏损上限,进行废弃抽取结果,排除部分亏损物品,重新抽取的逻辑

大奖物品与非大奖物品并列,且都需要配置每种模式的概率(21年8月的事故,主要原因就是为大奖物品配置低概率模式概率,低概率模式本不应该抽到大奖物品,也不会对大奖物品进行防亏损处理)

2、idLucyGift


image.png

抽取的思路为

1)分配不同的抽取策略:概率抽取(与idGreedy类似)、步长抽取

2)按奖品的配置次序,判断当前次数是否整除“步长”,整除时作为抽取

优点:严格控制奖品出现次数,与抽取次数的比例。

不足与风险:

奖品出现的间隔固定,容易被用户发现这种规律;

达到不同奖品步长的公倍数时,只能发出一个高优先的奖品(步长不是最终的频次,受其它高优先奖品的步长影响)

不同策略的配置参数,混用json对象,字段一部分有效,另一部分无效。

3、欢乐扭蛋机,轮次奖池 打乱+不放回抽取

image.png

image.png

抽取的思路为

1)将礼物id,添加到一个数据切片(每个id的重复次数为其 在轮次奖池中的数量)

2)打乱轮次奖池(util.ShuffleString(gifts))(对个别特殊奖品出现的次序,有一定的干预)

3)提前将50轮的已打乱轮次发放列表,存入redis

4)抽取时,使用lua脚本,指定发放列表找出命中的奖品

优点:

在每个轮次内,每种奖品有固定的数量,同时进行了打乱;

部分抽取逻辑交由redis执行,避免的分布布锁的使用,并发能力也有了保障。

不足与风险:

lua脚本书写抽取逻辑,开发、调试难度过大;

发放列表提前生成,无法做到进行中,进行即时变更配置。

4、国际化抽奖礼物,轮次奖池 打乱+不放回抽取


image.png

同样实现 轮次奖池 打乱+不放回抽取 ,避免使用lua脚本,配置变更时在新开启的轮次中生效(这个功能独立,可删掉)

抽取的思路为

1)使用redis incr操作,可领取到一个抽取的序号

2)使用伪随机算法,为抽取序号映射出一个奖池中奖品序号

3)使用redis将进行中的轮次配置,维护为一个队列。针对指定轮次,最早写入队列的配置,就是最终要使用的。(并发时,多个容器可能有不同的配置 同时进行写入)

优点:

避免使用lua脚本;

最少使用redis的操作,进一步提高了并发能力;

配置变更时在新开启的轮次中生效;

不足与风险:

修改配置时,轮次的奖池大小要保持不变。变化时,伪随机算法会完全错乱。

你可能感兴趣的:(奖品抽取逻辑的实现汇总+主观点评)