需求背景
我们app和对接单位拟举行一次抽奖活动提高日活,app内提供抽奖入口页面,进入抽奖页面点击赚取积分进入第三方页面,进行答题,赚取积分。抽奖规则:每个人每天最多抽奖3次,每次抽奖消耗积分3分,活动期间每个人最大中奖次数是固定的,每次的中奖概率也是不同的。以上所有的配置都支持动态配置即修改动配置立即生效,无须重启应用。
架构设计
结合此需求前提下,采用springboot+mybatisplus+nacos+分布式锁+redis队列来实现抽奖功能,并且由springcloud网关来实现抽奖接口数据加解密以及限流功能,防止有人恶意刷票导致系统崩溃
详细设计
由于奖品数量不大,且奖品不区分等级,因此系统初始化时将奖品缓存到redis队列中,并设置奖品池标识true/false(true代表还有奖品,false代表无奖品)。此处由于系统是集群部署,因此在初始化奖品池的过程添加了分布式锁,防止初始化多次奖品池数据。
抽奖接口防幂等性:抽奖之前先针对用户生成唯一token,将该token放入header中请求抽奖接口
另外注意的点就是防超卖,除了前面正常判断是否满足抽奖资格逻辑之外,扣库存操作借助消息队列线性消费,消费者在扣减库存时,采用行锁的方式扣减库存,update xx set count=count-1 where id = xxx and count>1,而不是先select 再update(容易引起并发问题) ,另外扣减库存操作假如失败,需要回填库存
另外针对抽奖接口,添加了限流逻辑,实现机制是基于RateLimter的令牌桶算法,每秒钟向桶中放x枚令牌,每个请求进来如果拿到令牌则继续执行,拿不到令牌则返回系统繁忙请稍后重试等提示
以上就是考虑的比较重要的几点吧,如有不对的地方请指出!