[Golang 修仙之路] 场景题:红包系统设计

本文章仅供个人学习使用。

架构层面

红包系统流量特点:整体并发流量巨大,对于单体红包流量不是很大。

什么意思?

  • 秒杀系统:几百万人可能都盯着某个热点门票 or 商品,单一商品的瞬时并发量高。
  • 红包系统:微信一个群就500人,单一红包瞬时流量不算高。但是同一时刻,有上百万的微信群在抢红包,整体流量很大。

1. 水平扩展

正因为如此,红包系统水平扩展比较容易,因为可以让一台机器处理一定范围的红包,不同红包之间的状态不会互相影响。

2. SET化

我们还可以在这个基础上更进一步,做「硬件资源隔离」或者叫「SET化」,为什么要这么干,原因有2个:

  • 一、如果多个红包服务共享Redis、MySQL,虽然通过分片分摊了流量,但是Redis、MySQL要维护大量的TCP连接,数据库连接数可能被打满。
  • 二、多个红包服务同时命中一个MySQL分片,事务冲突加剧。

所谓的SET化,或者说硬件资源隔离,就是给每个服务都配备独立的完整的硬件资源(数据库、中间件等),让每个服务可以独立部署。通过部署多套服务,来缓解上述2个问题。

数据库表设计

SQL 复制代码
-- 红包订单表
CREATE TABLE red_pack_order (
    id BIGINT PRIMARY KEY, 
    owner_id BIGINT NOT NULL, 
    target_id BIGINT NOT NULL, 
    red_pack_type INT NOT NULL, 
    total_money BIGINT NOT NULL, 
    total_red_pack_num INT NOT NULL, 
    red_pack_order_status INT NOT NULL, 
    created TIMESTAMP NOT NULL, 
    modified TIMESTAMP NOT NULL 
);

-- 红包表
CREATE TABLE red_pack (
    id BIGINT PRIMARY KEY, 
    red_pack_order_id BIGINT, 
    owner_id BIGINT NOT NULL, 
    target_id BIGINT NOT NULL, 
    red_pack_type INT NOT NULL, 
    total_money BIGINT NOT NULL, 
    total_red_pack_num INT NOT NULL, 
    red_pack_status INT NOT NULL, 
    created TIMESTAMP NOT NULL, 
    modified TIMESTAMP NOT NULL 
);

-- 红包流水表
CREATE TABLE red_pack_record (
    id BIGINT NOT NULL PRIMARY KEY, 
    red_pack_id BIGINT NOT NULL, 
    money BIGINT NOT NULL, 
    owner_id BIGINT NOT NULL, 
    red_pack_record_status INT NOT NULL, 
    created TIMESTAMP NOT NULL, 
    modified TIMESTAMP NOT NULL 
);

业务层面

1. 发红包流程

  1. 用户填写红包信息,包括:总金额、拼手气还是固定金额、红包个数、标题、封面。
  2. 创建订单(向「红包订单表」中插入一条记录)。
  3. 启动定时任务:过期未付款取消订单。
  4. 调用支付接口。
  5. 接收到支付接口回调后,创建红包(向「红包表」中插入一条数据)同时,为了把扣减库存的操作上移到缓存,我需要同步Redis。
    • red_packet:{id}:remain_amount
    • red_packet:{id}:remain_count
  6. 调用消息系统推送消息的接口,把红包发送到目标(人 or 群)。
  7. 启动定时任务:红包过期对账、退款。

红包状态流转:已创建 -- 已支付 -- 已生效 -- 已抢完 -- 已过期

2. 抢红包流程

  1. 校验用户资格(用户是否在群里,用户是否已经抢过红包)
  2. 校验红包状态
  3. 通过Lua脚本实现 扣减库存 扣减的余额,在Redis中执行原子性的扣减。
  4. 记录红包流水(向红包流水表中写入一条记录)
  5. 通过消息队列 异步转账。

红包分配算法

两个大的方向:实时计算 和 预先生成

1. 二倍均值法

用户可以抢到的金额在 0.01元 和 2倍的均值之间。 如果剩余红包数为1,则用户直接带走全部余额。

参考

  1. mp.weixin.qq.com/s/mhLulCLdl...
  2. mp.weixin.qq.com/s/KRQSuddXk...
  3. mp.weixin.qq.com/s/bviv2DdIq...
相关推荐
子兮曰15 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰15 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝15 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码16 小时前
别再前后端各写一套表单校验了
java·后端
晨米酱16 小时前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
大勇前进16 小时前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu16 小时前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile16 小时前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白8016 小时前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙17 小时前
PHP 接口返回统一响应封装,让前后端对接更省心
后端