[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...
相关推荐
章豪Mrrey nical4 小时前
前后端分离工作详解Detailed Explanation of Frontend-Backend Separation Work
后端·前端框架·状态模式
写写闲篇儿5 小时前
微软面试之白板做题
面试·职场和发展
派大鑫wink5 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
程序员爱钓鱼6 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
xUxIAOrUIII6 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home6 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
zfj3216 小时前
go为什么设计成源码依赖,而不是二进制依赖
开发语言·后端·golang
weixin_462446236 小时前
使用 Go 实现 SSE 流式推送 + 打字机效果(模拟 Coze Chat)
开发语言·后端·golang
JIngJaneIL6 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码7 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web