微信红包业务量级的高速发展,对后台系统架构的可用性要求愈来愈高。在保障微信红包业务体验的前提下,红包后台系统进行了一系列高可用方面的优化设计。本次演讲介绍了微信红包后台系统的高可用实践经验,主要包括后台的 set 化设计、异步化设计、订单异地存储设计、存储层容灾设计与平行扩缩容等。听众能够了解到微信红包后台架构的设计细节,共同探讨高可用设计实践上遇到的问题与解决方案。数据库
微信红包介绍服务器
微信红包从 2014 年开始发展到如今 2017 年,中间经历了 3 年时间。在这三年的时间里,整个系统可用性产生了较大的提高。2015 年年初的时候,天天晚上九点钟是微信红包的业务高峰期,系统常常性地出现性能问题。到了 2017 年的今天,即便在节假日高峰期,系统也不会出现问题。微信
如上图所示,微信红包的业务包含包、发、抢、拆、查询发送红包和收红包数量,其中最关键的步骤是发红包和抢红包。架构
微信红包是微信支付的商户,微信红包这个商户出售的是钱。发红包用户在微信红包平台使用微信支付购买一份钱,微信红包将钱发放到相对应的微信群。群里的用户抢红包获得微信零钱。这个过程当中,微信红包和微信支付之间的关系是商家和第三方支付平台的关系。并发
微信红包和微信支付之间的交互,与普通商家与微信支付的交互同样,须要通过六个步骤。用户发红包时,进入微信红包下一笔订单,系统记录发红包用户、发红包金额、红包数量和要发送到的用微信群。而后微信红包系统请求微信支付服务器进行下单,用户使用微信支付进行支付。运维
支付成功后,微信支付后台系统通知微信红包后台系统支付成功结果,微信红包后台系统收到通知后推送微信红包消息到微信群。微信群里用户即可抢红包。这就是微信红包和微信支付的关系以及交互过程。异步
微信红包系统架构性能
微信红包的系统流程微信支付
上图是微信红包系统角度上的流程,业务主流程是包、发、抢、拆四个操做,每一个操做包括几个关键步骤。优化
包红包,系统为每一个红包分配一个惟一 ID,即红包发送订单号,而后将发红包用户、红包个数、红包数额写入存储,最后去微信支付下单。
发红包,用户使用微信支付完成付款,微信红包后台系统收到微信支付系统的支付成功通知。红包系统将红包发送订单状态更新为用户已支付,并写入用户发红包记录(用户发红包记录,就是微信钱包中,查看到的用户每年总共发出及收到的红包记录)。最后微信红包后台系统发送微信红包消息到微信群。
抢红包,指微信群里的用户收到微信红包消息后,点开红包消息。这个过程,微信红包后台系统会检查红包是否已被抢完,是否已过时,是否已经抢过。
拆红包是最复杂的业务是操做。包括查询这个红包发送订单,判断用户是否可拆,而后计算本次可拆到的红包金额。而后写入一条抢红包记录。若是把拆红包过程,类比为一个秒杀活动的过程,至关于扣库存与写入秒杀记录的过程。更新库存对应于更新红包发送订单,写入秒杀记录对应于写入这个红包的领取红包记录。另外,还要写入用户总体的红包领取记录。最后请求微信支付系统给拆到红包用户转入零钱,成功后更新抢红包的订单状态为已转帐成功。
微信红包的总体架构
上图所示,是微信红包的系统架构。包括微信统一接入层,下面是微信红包系统 API,包括发、抢、拆、查红包详情、查红包用户列表。再下面是封装微信红包关键业务的逻辑服务;最下面一层是数据存储层,微信红包最主要的数据是订单数据,包括发红包订单和拆红包订单两部分。业务逻辑和存储服务器之间是数据接入层,它最重要的做用是封装数据库操做的领域逻辑,使得业务逻辑服务不须要感知对 MySQL 的链接管理、性能、容灾等问题。
微信红包数据的访问热度,随着时间流逝会急剧下降,也就是数据的访问时间段很是集中,通常红包发出三天后,99% 的用户不会再去点开这个红包了。所以微信红包系统采起按时间作冷热数据分离,下降数据的存储成本,同时提高了热数据的访问性能。
数据平台用于对红包数据的分析计算,好比朋友圈里的文章,统计从 2016 年 1 月 1 日到 2017 年 1 月一个用户总共抢红包的金额,在全国的排名状况,发红包数最多的城市等。另一个做用就是对帐,红包的订单和微信支付的订单须要对帐,以保证最终资金的一致性;订单的数据和订单的 cache 须要作对帐,以保证数据的完整性;订单数据和用户的收发记录须要对帐,以保证用户列表完整性。
微信红包系统可用性实践
系统可用性影响因素
系统的可用性影响因素可分红两类,一类计划外,一类计划内。计划外包含不少因素,系统用到的全部东西均可能产生故障,均可能成功影响可用性的因素。从这个角度上来说,能够说故障是没法避免的,系统的运做必定会产生故障,尤为是服务器有成千上万个的时候。计划内的影响因素,主要有与升级相关、运维相关的操做,以及平常的备份等。这一类影响因素,经过精细地设计方案,是能够避免对可用性形成影响的。
微信红包系统可用性设计方向
基于上面两个分析结论,能够总结出微信红包后台系统的可用性的设计方向。就是在不能避免意外故障的状况下,尽量下降出现意外故障时对可用性的影响。另外一方面,绝大多数计划内的平常维护能够经过方案的设计避免影响可用性,其中平行扩容特指关于存储层的平行扩容。
下面从下降故障影响和微信红包系统的平行扩容两方面进行分析。
首先是下降意外故障的影响,重点讲解订单存储层在订单 DB 故障的状况下如何下降对红包系统可用性的影响。
业务逻辑层 - 部署方案设计
首先是业务逻辑层的部署方案。业务逻辑层是无状态的,微信红包系统的业务逻辑层,部署在两个城市,即两地部署,每个城市部署至少三个园区,即三个 IDC。而且每一个服务须要保证三个 IDC 的部署均衡。另外,三个 IDC 总服务能力须要冗余三分之一,当一个 IDC 出现故障时,服务能力仍然足够。从而达到 IDC 故障不会对可用性产生影响。
业务逻辑层 - 异步化设计
第二是异步化设计。如上图所示,微信红包的某些步骤不实时完成也不会影响用户对红包业务可用性的体验。好比拆红包,正常的业务流程很长,但关键步骤只有订单相关的几步。至于转零钱、写红包记录等操做不须要实时。用户抢到红包时,通常不会实时去钱包查看微信零钱,而是在微信群中点开消息查看本次抢到金额和他人抢红包金额。因此拆红包时只须要从 cache 查询用户是否拆过红包,而后写入拆红包的订单记录,更新发红包订单,其余的操做均可以异步化。固然,不是每一个业务均可以进行异步化设计,须要进行业务分析,判断是否存在非关键步骤以外的事情能够将其异步化,并经过异步对帐保证最终一致。
接下来是微信红包订单存储设计。上图是 2014 年微信红包存储层的模型。业务逻辑层请求数据层操做时,使用订单号 hash 路由到订单 SERVER。订单 SERVER 与每一组 MYSQL 数据库链接。
微信红包的订单号是在发红包时系统生成惟一标识,使用序列号服务生成惟一 ID,后面拼接三位微信红包的订单分库表的标识。因此,总共能够分一百个逻辑库,每一个逻辑库含有十张表。一百个逻辑库均匀地分布到十组物理 DB,每组 DB 存十个逻辑库。
这个架构的最大问题是,一组 DB 故障时,会影响其余 DB。2014-2015 年期间,微信红包量涨得特别快,扩容速度跟不上业务增加速度。一组 DB 的性能出现瓶颈时,数据操做变慢, 拆红包的事务操做在 MYSQL 排队等待。因为全部十组 DB 机器与全部的订单 SERVER 链接,致使全部的订单 SERVER 都被拖住,从而影响红包总体的可用性。这个架构的另外一个问题是扩容不方便,后面会介绍。
为解决 DB 间的相互影响,须要将 DB 间相互隔离,订单存储层 SET 化。SET 化指订单 DB 和订单接入 SERVER 垂直 stick 一块儿。业务逻辑层访问订单时,根据订单倒数第2、三位数字找到所属订单 SET,一个 SET 的请求不能路由到其余 SET。
找到对应的订单接入服务器以后,在服务器内的多个进程中找到指定进程,让同个红包的全部拆请求串行化。当一组 DB 出现故障,只会影响该组 DB 对应的 SERVER。
这里有一个问题,DB 故障拖住某些订单 SERVER,会不会也拖住更上层业务逻辑服务?业务逻辑层为何不一块儿 SET 化?业务逻辑层承载了用户维度相关的业务操做,不能够按照订单的维度分业务逻辑,例如务逻辑层会请求用户的头像、昵称等,若是继续按照订单分业务逻辑,会致使跨地域调用。
微信红包系统采起的方案是,在订单 SERVER 服务端增长快速拒绝服务的能力。SERVER 主动监控 DB 的性能状况,DB 性能降低、自身的 CPU 使用升高,或者发现其余的监控维度超标时,订单 SERVER 直接向上层报错,再也不去访问 DB,以此保证业务逻辑层的可用性。
一组 DB 故障不会影响整个系统的可用性。有影响的,只有十分之一,若扩成 100 组,影响便只有一百分之一。因此经过 SET 化获得的好处是,控制 DB 链接数、隔离故障影响和分流并发。
完成 SET 化以后,DB 故障仍对业务有十分之一影响,那么这十分之一该怎么解决?经过对系统进行研究分析以后,发现 DB 能够作到故障自愈。
如上图所示,所设尾号 90-99 的 SET 故障时,若是业务逻辑服务后续再也不生成属于这个 SET 的订单,那后续的业务就能够逐渐恢复。
也就是在发生故障时,业务逻辑层发布一个版本,屏蔽故障号段的单号生成,就能够恢复业务。进一步想,除了人为发版本,有没有方法可让 DB 故障时自动恢复?在 DB 故障致使业务失败时,业务逻辑层可获取到故障 DB 的号段,在发红包时,将这些故障的号段,换一个可用的号段就可恢复业务。订单号除了最后三位,前面的部分已能保证该红包惟一性,后面的数字只表明着分库表信息,故障时只须要将最后三位换另一个 SET 即可自动恢复。
完成这个设计后,即便 DB 出现故障,业务的可用性也不会有影响。这里还有一点,新的发红包请求可避免 DB 故障的影响,但那些故障以前已发出未被领取的红包,红包消息已发送到微信群,单号已肯定,拆红包时仍是失败。对这种状况,因为不会有增量,采用正常的主备切换解决便可。
平行扩缩容设计
上图是微信红包早期的扩缩容方式。这个扩容方式,对扩容的机器数有限制。前面讲到,红包系统按红包单号后面两个数字分多 SET,为了使扩容后数据保持均衡,扩容只能由 10 组 DB 扩容到 20 组、50 组或者 100 组。另外,这个扩容方式,过程也比较复杂。首先,数据要先从旧数据库同步复制到新扩容的 DB,而后部署 DB 的接入 SERVER,最后在凌晨业务低峰时停服扩容。
这个扩容方式的复杂性,根本缘由是数据须要从旧 SET 迁到新 SET。若是新产生数据与旧数据不要紧,那么就能够省掉这部分的迁移动做,不需停服输。分析发现,须要把旧数据迁出来的缘由是订单号段 00-99 已所有被用,每一个物理数据库包含了 10 个逻辑库。若是将订单号从新设计,预留三位空间,三位数字每个表明独立的物理 DB,原来 10 组 DB 分别为 000-009 号段。
这种设计,缩容时,好比要缩掉 000 这组,只需在业务逻辑服务上不生成订单号为 000 的红包订单。扩容时,好比扩为 11 组,只需多生成 010 的订单号,这个数据便自动写入新 DB。固然,缩容须要一个前提条件,也就是冷热分离,缩容后数据变为冷数据,可下线热数据机器。以上就是红包的平行扩缩容方案。
写在最后
微信红包系统的可用性实践,主要包括了部署设计、SET 化设计、异步化设计、DB 故障自愈能力建设、平行扩容设计。在完成这些设计后,微信红包系统的可用性获得了很大提高,在 2017 年春节实现了 0 故障,在日常的运行中达到 99.99% 可用性。