红包雨架构设计---2、流程设计-灵析社区

提笔写架构

业务流程

会员登录APP或者小程序;

调度器查询要进行的活动种子;

数据反馈活动种子信息;

活动预热,根据奖品数据,生成奖品池令牌桶;

活动时间到,前台弹出红包雨,会员参与抽奖;

前端获取活动信息;

缓存返回活动信息给前端;

进行用户登录、资格等基础校验;

基础校验通过则获取令牌;

缓存返回获取到的令牌;

校验令牌有效性,是否在活动时间;

令牌检验失败则令牌放回队列;

令牌有效则说明中奖,组装中奖信息;

提示用户中奖;

异步通知消息服务中奖信息;

执行持久化操作,入库中奖信息;

缓存体系

活动基本信息

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

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

活动策略信息

hset,以活动id为group,用户等级为key,策略值为valueredisUtil.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);

中奖逻辑判断

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

阅读量:2136

点赞量:0

收藏量:0