2021腾讯数字生态大会直播预约通道开启!技术内容大爆发,开发者必看! 了解详情
写点什么

百亿级微信红包的高并发资金交易系统设计方案

2017 年 2 月 16 日

2017 年 1 月 28 日,正月初一,微信公布了用户在除夕当天收发微信红包的数量——142 亿个,而其收发峰值也已达到 76 万每秒。百亿级别的红包,如何保障并发性能与资金安全?这给微信带来了超级挑战。面对挑战,微信红包在分析了业界“秒杀”系统解决方案的基础上,采用了 SET 化、请求排队串行化、双维度分库表等设计,形成了独特的高并发、资金安全系统解决方案。实践证明,该方案表现稳定,且实现了除夕夜系统零故障运行。

本文将为读者介绍百亿级别红包背后的系统高并发设计方案,包括微信红包的两大业务特点、微信红包系统的技术难点、解决高并发问题通常使用的方案,以及微信红包系统的高并发解决方案。

一、微信红包的两大业务特点

微信红包(尤其是发在微信群里的红包,即群红包)业务形态上很类似网上的普通商品“秒杀”活动。

用户在微信群里发一个红包,等同于是普通商品“秒杀”活动的商品上架;微信群里的所有用户抢红包的动作,等同于“秒杀”活动中的查询库存;用户抢到红包后拆红包的动作,则对应“秒杀”活动中用户的“秒杀”动作。

不过除了上面的相同点之外,微信红包在业务形态上与普通商品“秒杀”活动相比,还具备自身的特点:

首先,微信红包业务比普通商品“秒杀”有更海量的并发要求。

微信红包用户在微信群里发一个红包,等同于在网上发布一次商品“秒杀”活动。假设同一时间有 10 万个群里的用户同时在发红包,那就相当于同一时间有 10 万个“秒杀”活动发布出去。10 万个微信群里的用户同时抢红包,将产生海量的并发请求。

其次,微信红包业务要求更严格的安全级别。

微信红包业务本质上是资金交易。微信红包是微信支付的一个商户,提供资金流转服务。

用户发红包时,相当于在微信红包这个商户上使用微信支付购买一笔“钱”,并且收货地址是微信群。当用户支付成功后,红包“发货”到微信群里,群里的用户拆开红包后,微信红包提供了将“钱”转入折红包用户微信零钱的服务。

资金交易业务比普通商品“秒杀”活动有更高的安全级别要求。普通的商品“秒杀”商品由商户提供,库存是商户预设的,“秒杀”时可以允许存在“超卖”(即实际被抢的商品数量比计划的库存多)、“少卖”(即实际被抢的商户数量比计划的库存少)的情况。但是对于微信红包,用户发 100 元的红包绝对不可以被拆出 101 元;用户发 100 元只被领取 99 元时,剩下的 1 元在 24 小时过期后要精确地退还给发红包用户,不能多也不能少。

以上是微信红包业务模型上的两大特点。

二、 微信红包系统的技术难点

在介绍微信红包系统的技术难点之前,先介绍下简单的、典型的商品“秒杀”系统的架构设计,如下图所示。

该系统由接入层、逻辑服务层、存储层与缓存构成。Proxy 处理请求接入,Server 承载主要的业务逻辑,Cache 用于缓存库存数量、DB 则用于数据持久化。

一个“秒杀”活动,对应 DB 中的一条库存记录。当用户进行商品“秒杀”时,系统的主要逻辑在于 DB 中库存的操作上。一般来说,对 DB 的操作流程有以下三步:

a. 锁库存

b. 插入“秒杀”记录

c. 更新库存

其中,锁库存是为了避免并发请求时出现“超卖”情况。同时要求这三步操作需要在一个事务中完成(所谓的事务,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行)。

“秒杀”系统的设计难点就在这个事务操作上。商品库存在 DB 中记为一行,大量用户同时“秒杀”同一商品时,第一个到达 DB 的请求锁住了这行库存记录。在第一个事务完成提交之前这个锁一直被第一个请求占用,后面的所有请求需要排队等待。同时参与“秒杀”的用户越多,并发进 DB 的请求越多,请求排队越严重。因此,并发请求抢锁,是典型的商品“秒杀”系统的设计难点。

微信红包业务相比普通商品“秒杀”活动,具有海量并发、高安全级别要求的特点。在微信红包系统的设计上,除了并发请求抢锁之外,还有以下两个突出难点

首先,事务级操作量级大。上文介绍微信红包业务特点时提到,普遍情况下同时会有数以万计的微信群在发红包。这个业务特点映射到微信红包系统设计上,就是有数以万计的“并发请求抢锁”同时在进行。这使得 DB 的压力比普通单个商品“库存”被锁要大很多倍。

其次,事务性要求严格。微信红包系统本质上是一个资金交易系统,相比普通商品“秒杀”系统有更高的事务级别要求。

三、解决高并发问题通常使用的方案

普通商品“秒杀”活动系统,解决高并发问题的方案,大体有以下几种:

方案一,使用内存操作替代实时的 DB 事务操作。

如图 2 所示,将“实时扣库存”的行为上移到内存 Cache 中操作,内存 Cache 操作成功直接给 Server 返回成功,然后异步落 DB 持久化。

这个方案的优点是用内存操作替代磁盘操作,提高了并发性能。

但是缺点也很明显,在内存操作成功但 DB 持久化失败,或者内存 Cache 故障的情况下,DB 持久化会丢数据,不适合微信红包这种资金交易系统。

方案二,使用乐观锁替代悲观锁。

所谓悲观锁,是关系数据库管理系统里的一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作对某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。对应于上文分析中的“并发请求抢锁”行为。

所谓乐观锁,它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。

商品“秒杀”系统中,乐观锁的具体应用方法,是在 DB 的“库存”记录中维护一个版本号。在更新“库存”的操作进行前,先去 DB 获取当前版本号。在更新库存的事务提交时,检查该版本号是否已被其他事务修改。如果版本没被修改,则提交事务,且版本号加 1;如果版本号已经被其他事务修改,则回滚事务,并给上层报错。

这个方案解决了“并发请求抢锁”的问题,可以提高 DB 的并发处理能力。

但是如果应用于微信红包系统,则会存在下面三个问题

  1. 如果拆红包采用乐观锁,那么在并发抢到相同版本号的拆红包请求中,只有一个能拆红包成功,其他的请求将事务回滚并返回失败,给用户报错,用户体验完全不可接受。
  2. 如果采用乐观锁,将会导致第一时间同时拆红包的用户有一部分直接返回失败,反而那些“手慢”的用户,有可能因为并发减小后拆红包成功,这会带来用户体验上的负面影响。
  3. 如果采用乐观锁的方式,会带来大数量的无效更新请求、事务回滚,给 DB 造成不必要的额外压力。

基于以上原因,微信红包系统不能采用乐观锁的方式解决并发抢锁问题。

四、微信红包系统的高并发解决方案

综合上面的分析,微信红包系统针对相应的技术难点,采用了下面几个方案,解决高并发问题。

1. 系统垂直 SET 化,分而治之。

微信红包用户发一个红包时,微信红包系统生成一个 ID 作为这个红包的唯一标识。接下来这个红包的所有发红包、抢红包、拆红包、查询红包详情等操作,都根据这个 ID 关联。

红包系统根据这个红包 ID,按一定的规则(如按 ID 尾号取模等),垂直上下切分。切分后,一个垂直链条上的逻辑 Server 服务器、DB 统称为一个 SET。

各个 SET 之间相互独立,互相解耦。并且同一个红包 ID 的所有请求,包括发红包、抢红包、拆红包、查详情详情等,垂直 stick 到同一个 SET 内处理,高度内聚。通过这样的方式,系统将所有红包请求这个巨大的洪流分散为多股小流,互不影响,分而治之,如下图所示。

这个方案解决了同时存在海量事务级操作的问题,将海量化为小量。

2. 逻辑 Server 层将请求排队,解决 DB 并发问题。

红包系统是资金交易系统,DB 操作的事务性无法避免,所以会存在“并发抢锁”问题。但是如果到达 DB 的事务操作(也即拆红包行为)不是并发的,而是串行的,就不会存在“并发抢锁”的问题了。

按这个思路,为了使拆红包的事务操作串行地进入 DB,只需要将请求在 Server 层以 FIFO(先进先出)的方式排队,就可以达到这个效果。从而问题就集中到 Server 的 FIFO 队列设计上。

微信红包系统设计了分布式的、轻巧的、灵活的 FIFO 队列方案。其具体实现如下:

首先,将同一个红包 ID 的所有请求 stick 到同一台 Server。

上面 SET 化方案已经介绍,同个红包 ID 的所有请求,按红包 ID stick 到同个 SET 中。不过在同个 SET 中,会存在多台 Server 服务器同时连接同一台 DB(基于容灾、性能考虑,需要多台 Server 互备、均衡压力)。

为了使同一个红包 ID 的所有请求,stick 到同一台 Server 服务器上,在 SET 化的设计之外,微信红包系统添加了一层基于红包 ID hash 值的分流,如下图所示。

其次,设计单机请求排队方案。

将 stick 到同一台 Server 上的所有请求在被接收进程接收后,按红包 ID 进行排队。然后串行地进入 worker 进程(执行业务逻辑)进行处理,从而达到排队的效果,如下图所示。

最后,增加 memcached 控制并发。

为了防止 Server 中的请求队列过载导致队列被降级,从而所有请求拥进 DB,系统增加了与 Server 服务器同机部署的 memcached,用于控制拆同一个红包的请求并发数。

具体来说,利用 memcached 的 CAS 原子累增操作,控制同时进入 DB 执行拆红包事务的请求数,超过预先设定数值则直接拒绝服务。用于 DB 负载升高时的降级体验。

通过以上三个措施,系统有效地控制了 DB 的“并发抢锁”情况。

3. 双维度库表设计,保障系统性能稳定

红包系统的分库表规则,初期是根据红包 ID 的 hash 值分为多库多表。随着红包数据量逐渐增大,单表数据量也逐渐增加。而 DB 的性能与单表数据量有一定相关性。当单表数据量达到一定程度时,DB 性能会有大幅度下降,影响系统性能稳定性。采用冷热分离,将历史冷数据与当前热数据分开存储,可以解决这个问题。

处理微信红包数据的冷热分离时,系统在以红包 ID 维度分库表的基础上,增加了以循环天分表的维度,形成了双维度分库表的特色。

具体来说,就是分库表规则像 db_xx.t_y_dd 设计,其中,xx/y 是红包 ID 的 hash 值后三位,dd 的取值范围在 01~31,代表一个月天数最多 31 天。

通过这种双维度分库表方式,解决了 DB 单表数据量膨胀导致性能下降的问题,保障了系统性能的稳定性。同时,在热冷分离的问题上,又使得数据搬迁变得简单而优雅。

综上所述,微信红包系统在解决高并发问题上的设计,主要采用了 SET 化分治、请求排队、双维度分库表等方案,使得单组 DB 的并发性能提升了 8 倍左右,取得了很好的效果。

五、总结

微信红包系统是一个高并发的资金交易系统,最大的技术挑战是保障并发性能与资金安全。这种全新的技术挑战,传统的“秒杀”系统设计方案已不能完全解决。在分析了业界“秒杀”系统解决方案的基础上,微信红包采用了 SET 化、请求排队串行化、双维度分库表等设计,形成了独特的高并发、资金安全系统解决方案,并在平时节假日、2015 和 2016 春节实践中充分证明了可行性,取得了显著的效果。在刚刚过去的 2017 鸡年除夕夜,微信红包收发峰值达到 76 万每秒,收发微信红包 142 亿个,微信红包系统的表现稳定,实现了除夕夜系统零故障。

作者简介

方乐明,现任微信支付应用产品系统负责人,主要从事微信红包、微信转账、微信群收款等支付应用产品的系统设计、可用性提升、高性能解决方案设计等,曾负责 2015、2016 和 2017 年春节微信红包系统的性能优化与稳定性提升,取得良好的效果。

感谢韩婷对本文的策划和审校。

2017 年 2 月 16 日 19:1025103

评论 12 条评论

发布
用户头像
同一个key,落在具体一个主机上,这个主机就是单点,分库分表 也ha机制也是一个单机处理,这个怎么解决单点处理一个很大红包问题呢?
2021 年 05 月 09 日 16:48
回复
红包的数量限制了, 就限制了请求进来的流量。 所以这个很大也没多大啊 , 单机就可以处理了,而且还弄了个队列
2021 年 08 月 25 日 18:21
回复
用户头像
请求消息是直接放队列了么?要是消息丢了怎么办
2021 年 03 月 28 日 18:50
回复
用户头像
第二步按红包id排队,是每个红包生成一个队列么,还是预设几个队列,按红包id分配到其中一个队列中呢?按照全文的理解,这里访问db是根据红包id串行访问的,是不是有点类似于预设N个队列,对应N个线程,每个线程消费对应的队列数据。一个队列会保存多个红包id的数据,只是保证同一个红包id的请求有序。
2021 年 02 月 20 日 17:27
回复
用户头像
有几个问题不理解想问一下,通过hash到set后,set中有几个Server,那这样一个红包ID还需要到具体的一个server,(1)这个是怎么指定到具体的server。(2)如果在抢红包中途这台机器挂了或者重启了怎么处理? (3)当请求到一台机器后,这时候请求会到队列里面排队进行消费,是这台机器的所有请求都到一个队列里面,还是一个红包id一个队列,,如果一个红包一个队列在本地是如何实现的?如果是所有请求一个队列会不会影响性能
2020 年 10 月 31 日 20:37
回复
用户头像
用Hash值来分服务器,然后同一个ID会分到同一个流,这里的容灾备份怎么做呢? 主备服务器么?
2019 年 07 月 29 日 06:53
回复
发现某台 server 宕机,接入层将请求转移到同组另一台 server 处理即可
2020 年 04 月 07 日 15:16
回复
如果一个红包抢了一半,这个时候换了一台机器也能保证拆红包事务的顺序性?
2020 年 10 月 31 日 20:43
回复
用户头像
为什么乐观锁可以减少并发获取锁呢,update纪录不是一样要获取锁么
2019 年 03 月 07 日 08:38
回复
用户头像
点赞,说的很详细:
- 通过分流+队列+流控解决高并发场景下库存锁竞争的情况;
- 通过事务操作串行化保证资金安全,避免出现红包超发、漏发、重复发的情况;
- 通过红包ID+循环天双维度分库表规则提升系统性能;
2019 年 01 月 28 日 16:34
回复
没搞懂这个地方的队列是怎么实现按照不同的id一个队列的,可以理解为如果是java就一个红包生成一个单线程的线程池,如果该红包抢完了就关闭这个线程池?
2020 年 10 月 31 日 20:41
回复
一个红包一个线程池不现实,个人能想到的是
1:扔到mq(例如rocketmq),使用mq的顺序性消息特性(通过哈西取模的方式把同一个红包的请求落在一个queue),然后消费者消费的时候单线程消费即可保证顺序性,这样可以保证机器重启红包消息丢失问题(但要考虑幂等性),这样性能也会差一些,可以考虑增大queue的个数同时多部署几台实例解决
2:在方案1的基础上改成消费者线程池消费,要改一下消费逻辑,根据红包id路由到同一个线程,消费(保证同一个红包拆解顺序性),性能更好,因为不同红包的拆分互相不影响,代码也复杂些
2021 年 01 月 09 日 19:37
回复
没有更多了
发现更多内容

GK架构营模4作业

Ping

刷爆Leetcode!字节算法大佬进阶专属算法笔记:GitHub标星97k+

Java 架构 面试 程序人生 LeetCode

智云盾捕获多个僵尸网络利用最新ConfluenceRCE漏洞的活动

百度开发者中心

安全 漏洞

第5章-《Linux一学就会》- Linux基本操作和服务器硬件选购指南

学神来啦

Linux linux运维 linux学习 Linux教程

PerfDog携手Imagination,助力开发者获取GPU关键数据

WeTest

如何管理职场新人?

石云升

团队管理 管理 引航计划 内容合集 9月日更

应用开发中的存储架构进化史——从起步到起飞

云流

Java 编程 架构 面试 后端

一文带你掌握工作流引擎flowable所有业务概念

小黄鸡1992

后端 引航计划

Linux用户/用户组编辑

在即

9月日更 9 月日更

区块链食品溯源系统开发,区块链溯源的价值

135深圳3055源中瑞8032

云原生时代,如何构建数字化转型架构?

博文视点Broadview

让数据库无惧灾难,华为云GaussDB同城双集群高可用方案正式发布

华为云开发者社区

数据库 高可用 集群 华为云GaussDB 同城双集群

如何使用ESD二极管,设计运算放大器电压保护?

不脱发的程序猿

电路设计 ESD二极管 运算放大器 电压保护 嵌入式硬件

🏆【SpringBoot技术专题】「FtpServer文件服务」教你如何基于Springboot开发一个”可移植“的轻量级文件服务项目系统!

浩宇天尚

Apache springboot ftp服务 9月日更 FtpServer

三款Linux文件传输工具简单介绍-行云管家

行云管家

Linux 文件传输 IT运维

阿里内部最新“SpringCloudAlibaba学习笔记”(全彩第三版)限时开源

云流

Java 架构 面试 微服务 Alibaba

遇见乌镇 | VoneCredit洞见供应链金融新未来

旺链科技

世界互联网大会 供应链金融

AI专家一席谈:复用算法、模型、案例,AI Gallery带你快速上手应用开发

华为云开发者社区

算法 模型 案例 AI Gallery 应用开发

等保测评一次多少钱,收费标准是怎样的?

行云管家

网络安全 等保 等保测评 等保2.0

音视频编解码 --X264码率控制初探

Fenngton

音视频 ffmpeg 编码 码率控制 引航计划

解密秒杀系统架构,不是所有的系统都能做秒杀!

华为云开发者社区

架构 秒杀 电商系统

【架构实战营作业】模块四——学生管理系统存储

聆息

案例分享 | dubbo 2.7.12 bug导致线上故障

捉虫大师

dubbo 问题排查

HarmonyOS荣膺2021世界互联网大会领先科技成果奖

Geek_283163

华为 鸿蒙

论文阅读丨神经清洁: 神经网络中的后门攻击识别与缓解

华为云开发者社区

神经网络 深度学习 论文阅读

【大咖直播】Elastic 企业搜索实战工作坊(第一期)

腾讯云大数据

elasticsearch

金九银十面试如何得到面试官青睐?2021最新大厂Java面试真题合集(附权威答案)

Java 架构 面试 程序人生 编程语言

金秋国庆|官微掌门人火热征集!期待你的掌舵!

InfoQ写作平台官方

活动专区 国庆中秋

浅谈语音质量保障:如何测试 RTC 中的音频质量?

阿里云视频云

阿里云 测试 WebRTC 语音 音频

百胜中国使用Rainbond实现云原生落地的实践

Rex

Docker 行业资讯 案例分享 运维人生 kubenetes

质量基础设施一站式公共服务平台建设,NQI线上一站式平台开发

135深圳3055源中瑞8032

英特尔On技术创新峰会

英特尔On技术创新峰会

百亿级微信红包的高并发资金交易系统设计方案-InfoQ