P54 项目场景面试:直播间高并发打赏系统设计
面试题:直播间打赏(送礼、刷火箭)高并发场景怎么设计?比如主播实时展示"谁送了什么礼物"。
1. 业务特点
- 写多读多、瞬时峰值:用户疯狂刷礼物;
- 礼物列表/主播收益需要实时展示;
- 打赏涉及余额扣减、礼物落库、通知主播/榜单等多个动作。
2. 核心架构
text
客户端 → 网关(鉴权/限流)→ 打赏服务
├─ 余额校验+扣减(Redis Lua 原子)→ 发 MQ
├─ 礼物记录异步落库(订单/流水表)
└─ 实时榜单/消息 → Redis → WebSocket/SSE 推给主播和观众3. 关键设计点
① 余额扣减用 Lua 原子操作
lua
if tonumber(redis.call('GET', KEYS[1])) >= tonumber(ARGV[1]) then
return redis.call('DECRBY', KEYS[1], ARGV[1])
end
return -1防止并发扣超;扣减成功后发 MQ 异步落流水。
② 礼物记录异步化
- 打赏确认(余额扣成功 + 礼物送出去)用最终一致;
- 礼物流水表批量插入/异步落库,别让每次打赏都同步写库;
- 失败补偿:MQ 重试 + 对账。
③ 实时榜单
- 主播收益榜/礼物榜用 Redis ZSet(member=用户,score=礼物金额/数量):
bash
ZINCRBY rank:live:{roomId} 1314 10001- 榜单数据小可以广播;超大房间只推 Top N + 自己的排名。
④ 实时消息推送
- 主播大屏、观众公屏用 WebSocket/SSE;
- 推送内容先写 Redis(最近消息),再广播;
- 高并发下消息合并/采样(如每 100ms 聚合一次),避免刷屏把推送服务打爆。
⑤ 防刷与安全
- 打赏频次限流、单次/单日金额上限;
- 未成年人保护、风控(异常大额打赏拦截);
- 幂等:客户端重试不能重复扣款(打赏请求带幂等键)。
4. 加分点
- 强调读写分离路径:扣减/记录走可靠链路,展示走 Redis/推送链路,互不阻塞;
- 金额用分(整数)存储,避免浮点误差;
- 对账:礼物流水与主播收益日结,发现不一致补偿。
一句话总结
打赏系统 = Redis Lua 原子扣余额 + MQ 异步落流水 + ZSet 实时榜单 + WebSocket 推送;核心是"扣钱可靠、展示实时、异步落库、防刷防重",用最终一致性保证钱和礼物不错账。