红包雨与入账峰值

返回 高并发

春晚红包、App 红包雨、企业发福袋:短时 千万~亿级点击,每人金额小,但入账记录不能丢、不能重复领。介于「排行榜最终一致」与「抢票强一致库存」之间——钱/account 余额需准确,可接受百毫秒级延迟展示


场景特征

特征说明
写放大一次活动 N 次「抢」请求
热点活动单个 redpack:act:xxx 超级热 key
金额守恒总金额 = 已发出 + 剩余,不能超发
重复领取同一用户只能成功一次
峰值短分钟级结束

解决方案总览

活动配置预加载(总金额、份数、规则)
      ▼
抢红包:快速校验 + Redis 原子抢槽位
      ▼
成功 → 写领取记录(幂等)→ 异步入账(MQ)
      ▼
余额展示可延迟;账务以 DB 为准

1. 预分配与分片(削热 key)

避免单 Redis key 存「剩余金额」被万人抢:

方案说明
红包拆桶活动拆成 1024 个子红包队列,用户 hash(uid)%1024 路由
预先随机金额子包内金额列表预生成,抢即 LPOP
CAS 扣份数remain_count 分桶 DECR
-- 桶内剩余份数 DECR
local c = tonumber(redis.call('GET', KEYS[1]) or '0')
if c <= 0 then return 0 end
redis.call('DECR', KEYS[1])
return 1

2. 幂等与防重复

UNIQUE KEY uk_act_user (activity_id, user_id)
SET grab:act:2024:uid:10001 1 NX EX 86400   # 抢到标记

流程:先占位成功 → 再异步写账务;占位失败直接「已领取/手慢无」。


3. 入账异步(数据层外缓冲)

步骤路径
抢成功同步写 grab_log(或 Redis 队列)
加余额MQ 消费者批量更新 wallet
对账活动结束 T+0 核对总金额

用户余额 UI:先展示「到账中」,消费成功后刷新(最终一致)。


4. 限流与降级

  • 全局限流:活动 QPS 上限
  • 单用户:1 秒 1 次
  • 降级:抢光后静态返回,不再打 Redis

5. 与步数榜 / 抢票对照

红包雨步数榜抢票
一致性金额准确、可异步展示可近似座位强一致
热 key分桶必备可按用户拉取车次库存
失败语义已抢完榜更新慢无票

检查清单

  • 总金额是否可能超发?
  • 重复点击是否重复入账?
  • 单活动是否单 key?
  • MQ 堆积时账务是否可对账修复?

相关