导读
前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计。当然啦,Redis基础知识还不过关的,先去加强下自身内功,然后在回来看这篇,Redis基础知识(点我直达)。为啥写这个微信抢红包项目呢,公司0202年08月22日,公司周年庆,抢了100多红包,O(∩_∩)O哈哈~
微信抢红包实现原理
业务流程分析
功能拆解
新建红包
在DB、Redis分别新增一条记录
抢红包(并发)
请求Redis,红包剩余个数,大于0才可以拆,等会0时,提示用户,红包已抢完
拆红包(并发)
用到技术
Redis中数据类型的String特性的原子递减(DECR key)和减少指定值(DECRBY key decrement)
业务
- 请求Redis,当剩余红包个数大于0,红包个数原子递减,随机获取红包
- 计算金额,当最后一个红包时,最后一个红包金额=总金额-总已抢红包金额
- 更新数据库
查看红包记录
查询DB即可
数据库表设计
红包流水表
CREATE TABLE `red_packet_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `red_packet_id` bigint(11) NOT NULL DEFAULT 0 COMMENT '红包id,采⽤ timestamp+5位随机数', `total_amount` int(11) NOT NULL DEFAULT 0 COMMENT '红包总⾦额,单位分', `total_packet` int(11) NOT NULL DEFAULT 0 COMMENT '红包总个数', `remaining_amount` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包⾦额,单位 分', `remaining_packet` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包个数', `uid` int(20) NOT NULL DEFAULT 0 COMMENT '新建红包⽤户的⽤户标识', `create_time` timestamp COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='红包信息 表,新建⼀个红包插⼊⼀条记录';
红包记录表
CREATE TABLE `red_packet_record` ( `id` int(11) NOT NULL AUTO_INCREMENT, `amount` int(11) NOT NULL DEFAULT '0' COMMENT '抢到红包的⾦额', `nick_name` varchar(32) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的⽤户 名', `img_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的头像', `uid` int(20) NOT NULL DEFAULT '0' COMMENT '抢到红包⽤户的⽤户标识', `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '红包id,采⽤ timestamp+5位随机数', `create_time` timestamp COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='抢红包记 录表,抢⼀个红包插⼊⼀条记录';
发红包API
发红包接口开发
- 新增一条红包记录
- 往mysql里面添加一条红包记录
- 往redis里面添加一条红包数量记录
- 往redis里面添加一条红包金额记录
注意,往db中就单纯存入一条记录,Service层和Mapper层,就简单的一条sql语句,主要是提供思路,下面会附案例源码,不要慌
抢红包API
- 抢红包功能属于原子减操作
- 当大小小于0时原子减失败
- 当红包个数为0时,后面进来的用户全部抢红包失败,并不会进入拆红包环节
- 抢红包功能设计
- 将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回
- 注意事项
- 抢到红包不一定能拆成功
抢红包算法拆解
通过上图算法得出,靠前面的人,手气最佳几率小,手气最佳,往往在后面
- 发100元,共10个红包,那么平均值是10元一个,那么发出来的红包金额在0.01~20元之间波动
- 当前面4个红包总共被领了30元时,剩下70元,总共6个红包,那么这6个红包的金额在0.01~23.3元之间波动
抢红包接口开发
测试
发红包
模拟高并发抢红包(Jmeter压测工具)
因为我发了10个红包,金额是20000,使用压测工具,模拟50个请求,只允许前10个请求能抢到红包,并且金额等于20000。
项目源码下载
链接: https://pan.baidu.com/s/1knmVMKBldVe46cmXqqfGpw 密码: a7o7
未完待续
微信上有个小伙伴刚好要做一个秒杀的系统,催我赶紧把博客更新出来。过2天继续往下更新,布隆过滤器。