[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...
相关推荐
CN_山居5 小时前
Ubuntu使用Google Authenticator(MFA)
后端
程序猿二饭5 小时前
SpringBoot 实现支持多个微信小程序的登录
后端
AlpsMonaco5 小时前
kubernetes(k8s)集群迁移更新
后端
华仔啊5 小时前
刚学 Java 就被内存溢出劝退?这 10 个集合内存管理技巧救了我!
java·后端
武子康5 小时前
大数据-90 Spark RDD容错机制:Checkpoint原理、场景与最佳实践 容错机制详解
大数据·后端·spark
花花无缺6 小时前
python自动化-pytest-标记
后端·python
小扳6 小时前
SpringBootWeb 篇-深入了解 ThreadLocal 存在内存泄漏问题
java·开发语言·spring boot·面试
Villiam_AY6 小时前
使用 chromedp 高效爬取 Bing 搜索结果
后端·爬虫·golang
CryptoPP6 小时前
跨境金融数据对接实践:印度NSE/BSE股票行情API集成指南
开发语言·后端·金融