[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...
相关推荐
做运维的阿瑞3 小时前
Python零基础入门:30分钟掌握核心语法与实战应用
开发语言·后端·python·算法·系统架构
猿究院-陆昱泽4 小时前
Redis 五大核心数据结构知识点梳理
redis·后端·中间件
yuriy.wang4 小时前
Spring IOC源码篇五 核心方法obtainFreshBeanFactory.doLoadBeanDefinitions
java·后端·spring
咖啡教室6 小时前
程序员应该掌握的网络命令telnet、ping和curl
运维·后端
你的人类朋友7 小时前
Let‘s Encrypt 免费获取 SSL、TLS 证书的原理
后端
老葱头蒸鸡7 小时前
(14)ASP.NET Core2.2 中的日志记录
后端·asp.net
李昊哲小课8 小时前
Spring Boot 基础教程
java·大数据·spring boot·后端
码事漫谈8 小时前
C++内存越界的幽灵:为什么代码运行正常,free时却崩溃了?
后端
Swift社区8 小时前
Spring Boot 3.x + Security + OpenFeign:如何避免内部服务调用被重复拦截?
java·spring boot·后端
90后的晨仔8 小时前
Mac 上配置多个 Gitee 账号的完整教程
前端·后端