群发红包系统
业务流程
发红包
- 输入金额以及人数
- 创建红包订单(订单ID,金额,份数)
- 调用支付系统
- 红包订单支付之后红包就发出去了
- 钱先拆好(行锁分散,加大并发)
抢红包
- 抢红包业务群,检测当前是否有剩余钱
- 没有剩余直接返回,有剩余就将请求转发到Redis里面的list(先来先服务),同时将请求发到mq启动一个延时任务(对账作用),之后有一个worker调度中心监听Redis,也就是消费队列里面的消息。
- 抢红包业务群会阻塞轮询worker调度中心是否抢到红包,之后返回给用户,这个过程用户看来是同步的,只是在后端用Redis的list实现了简单排下队异步。
拆红包
- 抢到红包之后,计算红包的金额,计算更新剩余的红包的余额。
- 分支1:返回给用户
- 分支2:将拆红包的流水写到数据库里面(MQ异步记账)
- 红包结算(异常结算池)
- 红包入账
业务特点
- 个数少,人数少:小系统
- 个数多,人数少:美团。饿了么红包
- 个数多,人数大:微信群红包
- 个数少,人数多:春晚红包
设计思路
- 数据量大:分库分表
- 避免所有请求都到达DB:Redis
- 并发请求量大:Redis高可用 + 分布式ID + 消息队列
- 抢红包的FIFO保证:mq还是Redis
- 使用mq就是过于重量级,这种消息小而且是比较多的请求,最好不使用,kafka在topic多的时候容易性能下降、
- 使用Redis的list就可以性能比较高。
- 响应快
- 转账和热点数据
- 金融系统的安全问题:账务对账
实体设计
红包表
- 红包ID
- 发的用户ID
- 红包的金额
- 红包的人头数
- 支付的状态
- 已抢人数
- 版本号
拆红包流水表
- 拆红包流水号
- 红包ID
- 拆红包的用户ID
- 得到的金额
- 时间
实现一:微型系统(100个红包,1000个人抢)
-
一个分布式锁:同时抢,使用分布式锁排队,要求抢红包3s内返回,1个DB操作20ms(MySQL的行级锁),所以100个红包就是2000ms也就是2s抢完,满足3s之内。
-
分表:数据量多的时候
-
控制重复抢红包
实现二:小型系统(1000个红包,10000个人抢)
- 预先拆分红包到数据库:钱先按照个数拆分好,就有多个行锁
- 多个分布式锁:钱先按照个数拆分好,就有多个行锁,这个时候就使用对应个数的分布式锁,之后使用hash将锁分散到不同的锁上面
- 注意获取到锁之后判断一下有没有抢完,抢完就直接返回了,不要继续往下执行了
- Redis队列:钱按照个数拆分的时候流水结果放到队列里面,分布式锁抢到之后就从队列里面取出来一个更新数据库。
- 分表
实现三:千万级(千万个红包)
- 异步化:增加任务调度中心,异步处理(Redis的list替换mq,更加高效,数据小且多)
- 请求到达红包服务,抢红包请求隔离阻塞在红包服务,任务异步推送到Redis的list里面,任务调度中心拿到任务之后,使用之前的分布式锁去处理
- 可以控制系统的吞吐量
posted on 2025-10-14 23:40 chuchengzhi 阅读(3) 评论(0) 收藏 举报