高并发资金交易系统设计方案—百亿双十一、微信红包背后的技术架构

21CTO社区导读 :

今天带来的是一个长篇文章。主要讲解高可用的互联网交易系统架构,包括双十一、支付宝&微博红包技术架构,以及微信红包的技术架构,希望能给各位提供价值。

概述

话说每逢双十一节或春节等节假日,对大家来讲是最欢乐的日子,可以在微信群中收发红包,此外今年微信还推出了面对面红包,让大家拜年时可直接收发,对于用户来讲很爽也很方便。但对于技术架构侧的考量,这使得微信红包的收发数据成几何倍数上升,处理的复杂度也增加了很多。

2017年微信红包发送量最大的时间段是除夕夜,达到了142亿个。如此大规模、高并发、高峰值的业务场景,怕是在美帝互联网的技术团队,包括EBay、Amazon等也无法想象,在这种巨大的流量与并发后面,需要什么样级别的技术架构支撑?当达百亿级别的资金交易规模时,我们该怎样来保证系统的并发性能和交易安全?

当今中国的电子商务平台,有两个场景称得上亿级以上的并发量:一个是阿里的双十一,一个是微信的红包,都是在一个单位时间达到亿万以以上的请求负载。

阿里交易系统与红包体系架构

我们先来回顾一下阿里『双十一』的业务场景。

中国移动互联网的完全普及,使得电商业务每年都几百倍甚至更高倍速的增长,包括农村用户也对电商逐渐认可。电商巨头们每年创造出的新节日,无论是『双十一』还是『双十二』,都最大化点染了用户的消费欲望,人们在这一天疯狂下单和参与秒杀活动,期望用最便宜的价格购买到心仪的商品,这导致一些平台后端商品超卖,服务器负载过高拒绝服务等问题频频出现。

网站以及各个客户端带来巨大的流量对后端技术架构的要求越来越苛刻。比如某个电商网站宕机,对用户和订单的损失是无法估量的,就算老板拿着把刀放在桌子也无法根本上解决问题,关键还是看技术团队的架构、能力,同时也包括软硬件等相关资源投入。

我们拿刚刚过去的2016年『双十一』来讲,阿里巴巴&淘宝网的当天交易额为1207亿元,而2015年的数字为912.17亿元,成交额足足增长了32.32%。1207亿的巨大交易量,背后是阿里巴巴的云平台提供的技术支撑。马云同志说,所有的创新都是被逼出来的,不管是被他逼,还是用户逼,阿里的技术平台就是这样被倒逼了出来。

在2016年的阿里技术栈中,和往年比技术平台也发生了很大变化,一部分变成了数据挖掘,有一部分演变了人工智能计算。除了传统的Web后端,还增加了直播平台流媒体应用。

视频直播系统与Web系统有相同也有不同之处,来看大部分视频直播平台的存在着一些技术瑕疵。如下图示:

以上的问题在后端需要实施不同的技术解决方案,需要进行日志采集实时监控,比如对终端类、后台类以及CDN的运行日志进行分析等。

阿里的直播端,视频传播使用了H.265编码压缩。H265编码在压缩比以及清晰度上要超过目前主流的H.264标准。阿里云使用了自己的ApsaraVideo平台完成了这些任务。这个APsaraVideo提供了以下子系统:

1、客户端推流sdk

2、云端OpenAPI

3、CDN分发

阿里通过上面一系列产品,将推流、转码、分发、播放等问题全部解决。

关于流量的负载均衡,阿里双十一采用了双专线的CDN,20T以上的带宽,这样可支撑1000万人同时在线下单和观看视频直播。

在视频的传播压缩,阿里率先使用H.265编码压缩。H265在压缩比以及清晰度上要超过目前主流采用的H.264标准。

数据存储

在手机淘宝中的用户关注信息存储在云服务器的Redis中,订单等持久化数据保存在RDS(阿里云的MySQL集群)中。

在阿里的电商平台,从双11节开始后,每笔交易队列都是通过消息中间件系统来做流转,包括消息发布订阅,状态,定时,监控报警等消息服务——这个消息系统是阿里自研的产品称为AliwareMQ(内核为RocketMQ),当然我们也可以使用ActiveMQ,RabbitMQ等开源软件。

商品支付成功后的订单完成后,发给各个物流公司的订单数据采用了PetaData的产品,支持OLTP和OLAP。不需要把一份数据进行多次复制,然后再进行数据分析,免去在线与离线数据仓库之间海量数据的传输和加载时间,实现在线分析决策。

支付宝与微博红包架构

支付宝红包通过性能较高的分布式文件系统保证用户数据的高可靠与高可用。分布式文件系统需要考虑多机集群之间的一致性与效率问题。

新浪微博红包在2017年除夕的发抢数量也达到了16亿个以上,参与的用户有不同的类型与地域,对架构、监控与性能优化具有一定的挑战。除了通过CDN,分布式图片系统等处理性能问题,另外还有系统底层的内核进行优化,安全修复以及软硬件扩容。

微信红包技术架构

2017年1月28日,正值农历正月初一,腾讯微信平台公布了在除夕当天用户收发微信红包的数量达到142亿个,收发峰值为76万/秒。

2015年的春节数据:除夕摇一摇总次数110亿次,峰值1400万次/秒,8.1亿次每分钟,微信红包收发达10.1亿次,除夕红包为1.2亿个。

2014年的红包峰值每分钟被拆开红包数量为2.5万个。我们可以看到,2017年是2014峰值的5000倍,红包数量达到百亿级别。

保障并发性能与资金交易安全,带来了超级挑战。

微信技术平台总结过红包技术有三大难点:

快——如何保证用户快速摇到红包?

准——如何保证摇到的红包能成功拆开?

稳——如何保证拆开的红包能分享出去?

微信红包技术结合电商平台设计的秒杀系统之基础,采用了以下技术解决方案:

  • SET集合化

  • 串行化请求队列

  • 双维度分拆数据库表

通过以上方案设计,形成了自己的高并发、资金安全系统解决方案。

我们先回到使用场景中。

当大量的微信用户在同一时间摇红包,就会产生每秒千万级请求。需要对请求疏导分流。

如果不进行负载均衡,分离流量,直接到达后端服务器,多大的服务器集群都会被如此大的流量负何过大而崩溃。

我们来看除夕当天后台监控数据曲线便能说明一切。如下图示:

各位可以看到,在前台红包重重的分流减压下,后端服务器负载仍然瞬间飙升几十倍甚至更高。

红包产品特点

微信红包,特别是群里的红包,我们称之为微信群红包。这个东西的产品形态上像极了电商平台上的商品“秒杀”活动。

举个场景栗子,某位土豪在微信群里发一个红包,这相当于商品“秒杀”商品上架。然后群里的其它人开始疯狂抢之,这个场面相当于“秒杀”的库存查询——看看还有没有货。当用户抢到红包后,红包在眼前晃呀晃时,食指轻点开拆红包的操作,它对应了“秒杀”活动中点击秒杀按钮动作。

有的时候,点击出红包会提示网络出问题,则是秒杀时你的库存队列没有别人的快,微信给了一个友好的提示罢了。

这点上,和我们在12306网站抢火车票是同样的道理。

且不急下定论,微信红包在产品形态上和商品秒杀相比,也有着自己的一些特点和难点。来看都是哪两点:

第一:微信红包产品与商品“秒杀”,数量大&并发量更高。

为啥这么说?各位看,当土豪在群里发了一个红包,相当在网站发布了一次秒杀活动对吧?有10万个微信群里的人在同一时刻发起红包请求,也就是说在瞬息之间,时时存在10万个“秒杀”活动发布出来。

接下来,10万个微信群里的用户同时开抢红包,便产生了海量的并发查询请求。

第二:微信红包产品需要极高的安全级别。

红包的收发,本质上就是资金的交易。微信红包本身是微信支付(底层支撑是财付通平台在干活)的一个商户,由微信红包来提供资金流转服务。

群里土豪发红包时,相当使用微信红包商户名义向微信支付申请购买了一笔“钱”,而收货地址是当前的微信群。

当土豪支付成功后,红包就“发货”到该微信群中,群里的人拆开红包后,微信红包商户提供将“钱”转入拆红包成功用户的微信零钱服务。

由于是和钱相关的交易业务,它比普通商品“秒杀”活动有更高的业务严密和安全级别要求,与银行的在线交易有过之而无不及。

而电商平台上“秒杀”商品由商家提供的,库存是被事先预设好的,即使出现“超卖”(即实际被抢的商品数量比计划的库存多)、“少卖”(即实际被抢的商户数量比计划的库存少)时也有办法解决,比如和用户商量、不发货或者做虚假繁荣,BD小伙伴对外吹吹牛也就算了。

对于微信红包产品就非常非常严谨,一块钱也不能多,一分钱也不能少,绝不能有半点错误。比如群里土豪发249元的红包绝对不可以被拆出250块钱,用户发了100块钱未被领取,在24小时的退还期内要精确地退还给原路——发红包的用户。

第三:微信红包与接口效率。

微信红包和微信支付与支付宝的最大区别是,自己不做金融(余额宝业务),所有的支付操作均与用户绑定的银行卡银行接口交互。因此,与银行接口的安全,效率性能等需要有严密的设计。

微信红包架构难点

上面几次说,红包架构与秒杀系统有着些许相似。我们先重温下典型的秒杀系统架构设计,来看下图所示。

这个系统可谓是经典。它由网关代理接入层、商业逻辑服务层、缓存与实体存储层等构成。其中:

代理层,可使用Nginx或Varnish来处理请求接入,Web服务器使用Nginx承载主要的业务逻辑,Cache层如使用Memcached或Redis来缓存库存数量、数据库,使用MySQL/MariaDB集群中,做数据库的持久化存储。

业务逻辑层可以是多个Nginx的集群,Cache层可以是多台机器组成的大的内存池,包括数据库缓存,OpCode缓存等不同类型。

从数据库侧阐述,数据库可以根据不同业务或日期进行分表分库,读写分离等组成一个负载平衡的集群。

在秒杀业务中,表现就是一个秒杀活动对应Inodb中的一条库存。当某个用户开始点秒杀动作时,系统的主要逻辑在于数据库中对库存的操作上。

这样,在数据库的事务中包含以下3个步骤:

1、锁定库存LOCK

2、插入秒杀记录 INSERT

3、更新库存 UPDATE

可以肯定的是,所有的大小电商网站均是依此套路。详解解释如下:

首先锁定库存为避免并发请求时出现“超卖”的情形,同时下单的用户需要等待此事务执行完后再执行下一个事务。

在数据库的事务完整性要求,这三步需要在一个时间段一个系列中完成,当中间有一处错误发生即进行回滚,相当于放弃当前事务,若无错误发生,则整体事务的执行顺利被完成。

商品库存在数据库中记为一行,大量的用户同时点击购买同一件SKU时,第一个到达数据库的请求就锁住了这行库存记录。

在第一个事务完成提交之前这个锁一直被第一个请求占用,后面的所有请求就需要排队等待。

同时参与“秒杀”的用户越多,并发进数据库的排队请求就越多,如同旅行时去卫生间,队形被排的很长。

所以并发请求抢锁的事备,成为典型的“秒杀”或抢购类系统的设计难点。

在微信红包系统的设计上,事务级操作量级更大。即便在普通的时间下,每一时刻都会有数以万计的微信群在同一时间端发起红包,就是引发几万并发请求抢锁同时在排队,这使得数据库的压力比普通单个商品“库存”被锁放大更多倍。

解决高并发的常用解决方案

常见商品秒杀活动,解决高并发问题,可以有如下几种解决方案:

一,内存数据库替代数据库事务

如上图所示,我们把实时扣库存的行为上移到内存数据库或者叫缓存层来干活,缓存操作完毕后再返回服务器成功,通过队列异步返回到数据库进行持久化。

使用内存操作替代磁盘操作,会明显提升并发性能。但是需要注意引发的缺点,如果在内存操作完成,数据库保存失败,或内存出现Crash,数据库的存储进程不会进行。因此,这种解决方案不适合与钱相关的交易系统应用,特别是微信红包。

二,使用乐观锁替代悲观锁

我们来回顾一下关系数据库管理系统中的两种锁的概念。

悲观锁是DBMS里的一种并发控制的方法,它阻止一个事务以影响其他用户的方式来修改数据。若一个事务执行的操作对某行数据加了锁,只有这个事务将锁释放,其他事务才能够执行与该锁冲突的操作。此描述对应于上面所说的并发请求抢锁行为。

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

秒杀系统中,使用乐观锁会在库存记录中维护一个版本号。在更新库存操作进行前,先取当前版本号,在更新库存的事务提交时,检查该版本号是否已被其他事务修改。若版本未被修改,则提交事务,版本号加1。如果版本号已被其他事务修改,则回滚事务,并给上层报错。

乐观锁方案解决了“并发请求抢锁”的问题,可以提高数据库的并发处理能力。

似乎问题被解决,使用乐观锁对于一般的应用系统足够,但将它应用于微信红包系统中,会引发下面几个问题。

如果拆红包采用乐观锁,在并发抢到相同版本号的拆红包请求中,只有一个人能拆红包成功,其他的请求将事务回滚并返回失败,给用户报错,用户完全不可能接受这种体验。

采用乐观锁将会导致第一时间同时拆红包的用户有一部分直接返回失败,反而那些『网慢手慢』的,会有可能因为并发减小后拆红包成功,这也会带来用户体验上的负面影响。

如果采用乐观锁的方式,会带来大数量的无效更新请求、事务回滚,给DB造成不必要的额外压力。

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

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

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

1 系统垂直集合化

集合(SET)化,即分组进行管理。

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

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

这样,每个集合间相互独立,互相解耦,不存在任何关联。

同一个红包ID的所有请求,包括发、抢、拆、查详情详情等,合并在一个集合内处理,形成高内聚。

通过此法,系统将所有红包请求这个巨大的洪流分散为多股小流,犹似诸侯各国,互不影响,各自治理。请看下图所示:

综上所述内容,这个方案对同时存在海量事务级操作的问题,将海量化为微量,问题得以解决。

2 逻辑服务层将HTTP请求队化列化,解决数据库并发

前面提到过,微信红包系统是个交易系统,而数据库操作的事务性(悲观/乐观锁,回滚等特性)是不可能不用的,因此势必会存在“并发抢锁”的现象。

我们把到达数据的事务操作(拆红包行为)的并发改为串行,由统一一个通道出口,就不会存在“并发抢锁”的问题了。

这个其实和很多电商平台,以及PUSH系统等原理相似。

这样我们的策略就清晰明白了,接着来把拆红包的事务操作串行地进入数据库,来将请求在服务器层以FIFO(先进先出)的方式排队,就可以达成串行的效果。

关于服务器的FIFO队列系统,在前面提到过阿里的RoketMQ、ActiveMQ还有RabbitMQ等消息中间件产品。当然腾讯的技术团队自己设计了一个分布式的、轻巧的、灵活的FIFO队列产品。

具体解决方案实现如下:

首先,将同一个红包ID的所有请求归聚到同一台服务器。使用集合化,将同一个红包ID的全部请求,提到到同一个集合中。同个SET中会存在多台服务器同时连接同一台数据库服务器。这是基于容灾、性能等考虑,多台服务器互备冗余,并且将流量进行均衡负载。

怎样将同一个红包ID所有请求,提到同一台服务器上?在集合化的设计之外,微信红包系统添加了一层基于红包ID 哈希值的分流,如下图所示:

这和很多分布式系统很像,如图片的分布式存储,数据库的哈希分布等,可谓大道相通。

我们接下来再设计单机请求排队之方案。当同一台服务器上的所有请求被接管后,然后按红包ID进行排队,串行地进入工作进程处理,达到排队的效果。看下图所示:

接下来我们使用memcached来控制并发数量,具体实施为:

为了防止服务器中的请求队列过载,导致队列被降级,所有请求又冲进了数据库,造成数据库锁与响应过慢,红包系统又增加了与服务器同机部署的memcached内存数据库,把它用来控制拆同一个红包的请求并发数。我们实际是利用memcached的CAS原子性累增操作,来控制同时进入数据库中执行拆红包事务的请求数,苦超过预先设定数值则直接拒绝服务,用于处理数据库负载升高时的降级体验。

通过以上三个措施,我们就控制了数据库的“并发抢锁”问题。

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

任何系统的进化,在持久层都开始分库分表,微信红包系统也不例外。

微信红包的分库表规则,最开始是根据红包ID的哈希值分为多库多表。

随着红包数据量逐渐增大,单表数据量也逐渐增加,数据库的性能与单表数据量有一定相关性,例如InndoDB单表数据量达到几T的时水平时,性能会有不同程序的下降,这样就影响系统性能稳定性。

我们可以采用冷(不经常被查询到)热(频率存取的)数据的分离,将历史冷数据与当前热数据分开存储,来解决这个问题。

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

具体如下,比如分库表规则使用哈希+月份的开工,类似db_xx.t_y_dd设计。其中:xx/y是红包ID的哈希值的后3位,dd是月份,取值范围在01~31,代表一个月天数最多到31天。

通过两种维度的分库表,我们解决了数据单表的大量膨胀,导致性能下降的问题,从而保障了系统性能的稳定性。同时在热冷数据分离的问题上,使得数据迁移变得简单优雅。

以上是微信红包系统在解决高并发问题上的设计方案。总结起就是:采用集合化分治、队列系统、多维度分库分表方案,使得单集群数据库的并发性能提升了多倍,取得了良好的用户体验。

在平时节假日、2015和2016春节实践中充分证明了可行性,取得了显著的效果。在刚刚过去的2017鸡年除夕夜,微信红包收发峰值达到76万每秒,收发微信红包142亿个。微信红包系统的表现稳定,实现了除夕夜红包收发顺畅零故障。

小结

本文从实战出发,讲解了电商平台以及交易系统的典型红包系统的构建,包括分布式集群系统的灵活应用,实现Web服务器、内存、缓存以及数据库的有效利用。通过秒杀系统触类而旁通到红包系统,用简单有效的思维来解决复杂问题。

作者:21CTO社区

说明:本文参考了腾讯大讲堂关于微信红包架构的文章,原文一部分生涩部分做了优化。阿里架构一部分内容参考了阿里云社区关于双十一的部分内容。

来源:http://www.sohu.com/a/126891351_505802

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值