[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...
相关推荐
用户214118326360212 分钟前
OpenSpec 实战:用规范驱动开发破解 AI 编程协作难题
后端
Olrookie1 小时前
若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
java·前端·笔记·后端·学习·vue·ruoyi
LucianaiB1 小时前
招聘可以AI面试,那么我制作了一个AI面试教练不过分吧
后端
无奈何杨2 小时前
CoolGuard更新,ip2region升级、名单增加过期时间
后端
摇滚侠2 小时前
Spring Boot 3零基础教程,WEB 开发 自定义静态资源目录 笔记31
spring boot·笔记·后端·spring
Anthony_49263 小时前
逻辑清晰地梳理Golang Context
后端·go
Github项目推荐3 小时前
你的错误处理一团糟-是时候修复它了-🛠️
前端·后端
进击的圆儿3 小时前
高并发内存池项目开发记录01
后端
左灯右行的爱情3 小时前
4-Spring SPI机制解读
java·后端·spring
沐怡旸3 小时前
【穿越Effective C++】条款02:尽量以const, enum, inline替换#define
c++·面试