Skip to content

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 推送;核心是"扣钱可靠、展示实时、异步落库、防刷防重",用最终一致性保证钱和礼物不错账。

基于 VitePress 重建