admin 管理员组

文章数量: 1086055

红包雨架构设计

业务流程

  1. 管理后台创建红包活动,绑定奖品;
  2. 会员登录APP或者小程序;
  3. 调度器查询要进行的活动种子;
  4. 数据反馈活动种子信息;
  5. 活动预热,根据奖品数据,生成奖品池令牌桶;
  6. 活动时间到,前台弹出红包雨,会员参与抽奖;
  7. 前端获取活动信息;
  8. 缓存返回活动信息给前端;
  9. 进行用户登录、资格等基础校验;
  10. 基础校验通过则获取令牌;
  11. 缓存返回获取到的令牌;
  12. 校验令牌有效性,是否在活动时间;
  13. 令牌检验失败则令牌放回队列;
  14. 令牌有效则说明中奖,组装中奖信息;
  15. 提示用户中奖;
  16. 异步通知消息服务中奖信息;
  17. 执行持久化操作,入库中奖信息;

缓存体系

活动基本信息

k-v,以活动id为key,活动对象为value,永不超时

redisUtil.set(RedisKeys.INFO+game.getId(),game,‐1);

活动策略信息

hset,以活动id为group,用户等级为key,策略值为value

redisUtil.hset(RedisKeys.MAXGOAL + game.getId(),r.getUserlevel()+"",r.getGoalTimes()); redisUtil.hset(RedisKeys.MAXENTER + game.getId(),r.getUserlevel()+"",r.getEnterTimes());

抽奖令牌桶

双端队列(不清楚的自行百度),以活动id为key,在活动时间段内,随机生成时间戳做令牌,有多少个奖品就生成多少个令牌。令牌即奖品发放的时间点。从小到大排序后从右侧入队。

redisUtil.rightPushAll(RedisKeys.TOKENS + game.getId(),tokenList);

奖品映射信息

k-v , 以活动id_令牌为key,奖品信息为value,会员获取到令牌后,如果令牌有效,则用令牌token值,来这里获取奖品详细信息

redisUtil.set(RedisKeys.TOKEN + game.getId() +"_"+token,productMap.get(cgp.getProductid()),expire);

令牌设计技巧

假设活动时间间隔太短,奖品数量太多。那么极有可能产生的时间戳发生重复。
解决技巧:额外再附加一个随机因子。将 (时间戳 * 1000 + 3位随机数)作为令牌。抽奖时,将抽中的令牌/1000 ,还原真实的时间戳。

//活动持续时间(ms) 
long duration = end ‐ start; 
long rnd = start + new Random().nextInt((int)duration); 
//为什么乘1000,再额外加一个随机数呢? ‐ 防止时间段奖品多时重复 
long token = rnd * 1000 + new Random().nextInt(999);

中奖计数

k-v,以活动id_用户id作为key,中奖数为value,利用redis原子性,中奖后incr增加计数。
抽奖次数计数也是同样的道理

redisUtil.incr(RedisKeys.USERHIT+gameid+"_"+user.getId(),1);

中奖逻辑判断

抽奖时,从令牌桶左侧出队和当前时间比较,如果令牌时间戳小于等于当前时间,令牌有效,表示中奖。大于当前时间,则令牌无效,将令牌还回,从左侧压入队列。

本文标签: 红包雨架构设计