21CTO社区导读:
红包是我国国庆,婚宴等重大典礼上,一个最有喜气的货币附送典礼,它的意义不在于有多少金额,而在于它包含的蕴涵与问候。
再到后来,红包被用在互联网电子商务上,拿来做为订购商品做为现金抵用,实际上指的是代金券。
接出来微信创造了两个现象级的产品:一是全民打客机,一是全民抢红包。后者已经谢幕,抢红包却历久弥新。
红包不仅仅是娱乐和游戏。满足人的贪、嗔、痴等欲望的同时,它也具备了打通社交、商业、公共服务任督二脉的威力。
腾讯有一个广为人知的传统:旧历春节后下班第三天,马化腾和公司高层要亲自给职工派发红包,职工把这个传统称作“刷总办红包”。
这个时侯,有人提出玩点不一样的。延续现实世界的传统,把公司内部发红包的传统,弄成一个应用,在微信好友之间传播。于是,腾讯的产品总监提出了“抢红包”的方案。当时距离节日只有不到两个礼拜的时间。
微信将红包的概念和使用场景进一步扩大,到目前为止,微信红包有如下几个类型:
也就是微信群里人们领取和争抢的红包;
两个人在聊天界面时双向发送的红包;
两个人之间免加好友,可直接给对方发红包
人们常说的红包,亦即是群红包。现今群里抢红包的行为也显得很稀松平时,一言不合就开始来一发。
微信红包从2014年被张小龙团队发明,到2017年的现今,已两年半多的时间。
2015年新年期间,微信红包遇见收发困难等性能问题,甚至显示发送成功,虽然是用了一些产品上的方法,存在较大的性能问题。
其构架至此开始快速进化。其中包括:
后端流量控制
主要思路是减短关键业务流程,分离可以通过异步、缓存等方法解决的问题,减少系统压力,推动响应速率,在储存层上面建上一座水坝。
CGI无状态
接入层无状态,逻辑层也无状态,可以便捷地水平扩充。但依赖MySQL事务保证交易完整,保证红包系统的精简,降低困局的存在。
资源静态化
尽量把动态内容转为静态资源。静态资源和CGI分离,静态资源通过CDN就近接入,降低用户和CGI的交互,降低访问延时和数据恳求。
业务流程异步化
关键流程精简,非关键流程和后续业务逻辑步入异步队列进行处理,降低了用户的等待时间,也极大减少了峰值雪崩的机率。繁杂的非关键链路也不会影响到主流程。
过载保护
后端保护前端,能在后端处理,就不传递到前端。后端须要按前端能力做削峰限流;顾客端、接入层、逻辑层逐层控制流量;后端更容易容错处理,竭力保护储存层。微信的过载保护在顾客端已提早预埋件了策略,在联接失败或超时情况下会有相应提示,降低用户重复恳求次数。接入层针对频繁发出恳求的顾客端限制响应速率,并对系统负载界定出若干等级,达到不同阀值时引导顾客端使用不同限速速度;在异常情况出现时,异步限流降速减少服务器端压力避免过载。
多级读缓存
发一个群红包,抢红包的恳求量远小于发红包,假如早已领过完全可以拒绝。逻辑层降低缓存,类似可以缓存的恳求都缓存上去,进一步降低储存层流量。
订单写缓存
微信红包与订单处理
订单在完成支付前可以先落在缓存中,完成支付后再持久化。
如上图所示,微信红包的业务包含包、发、抢、拆、查询发送红包和收红包数目,其中最关键的步骤是发红包和抢红包。
微信红包是微信支付的商户,微信红包这个商户转让的是钱。发红包用户在微信红包平台使用微信支付订购一份钱,微信红包将钱领取到相对应的微信群。群里的用户抢红包得到微信零钱。这个过程中,微信红包和微信支付之间的关系是店家和第三方支付平台的关系。
微信红包和微信支付之间的交互,与普通店家与微信支付的交互一样,须要经过六个步骤。用户发红包时,步入微信红包下一笔订单,系统记录发红包用户、发红包金额、红包数目和要发送到的用微信群。之后微信红包系统恳求微信支付服务器进行下单,用户使用微信支付进行支付。
支付成功后,微信支付后台系统通知微信红包后台系统支付成功结果,微信红包后台系统收到通知后推送微信红包消息到微信群。微信群里用户便可抢红包。这就是微信红包和微信支付的关系以及交互过程。
微信红包系统构架
微信红包的系统流程
上图是微信红包系统角度上的流程,业务主流程是包、发、抢、拆四个操作,每位操作包括几个关键步骤。
包红包,系统为每位红包分配一个惟一ID,即红包发送订单号,之后将发红包用户、红包个数、红包数额写入储存,最后去微信支付下单。
发红包,用户使用微信支付完成付款,微信红包后台系统收到微信支付系统的支付成功通知。红包系统将红包发送订单状态更新为用户已支付,并写入用户发红包记录(用户发红包记录,就是微信皮夹中,查看到的用户每一年总共发出及收到的红包记录)。最后微信红包后台系统发送微信红包消息到微信群。
抢红包,指微信群里的用户收到微信红包消息后,点开红包消息。这个过程,微信红包后台系统会检测红包是否已被偷完,是否已过期,是否早已抢过。
拆红包是最复杂的业务是操作。包括查询这个红包发送订单,判定用户是否可拆,之后估算本次可拆到的红包金额。之后写入一条抢红包记录。假如把拆红包过程,类比为一个秒杀活动的过程,相当于扣库存与写入秒杀记录的过程。更新库存对应于更新红包发送订单,写入秒杀记录对应于写入这个红包的发放红包记录。另外,还要写入用户整体的红包发放记录。最后恳求微信支付系统给拆到红包用户转到零钱,成功后更新抢红包的订单状态为已汇款成功。
微信红包的整体构架
上图所示,是微信红包系统之总体构架。
包括微信统一接入层,下边是微信红包系统API,包括发、抢、拆、查红包详情、查红包用户列表。再下边是封装微信红包关键业务的逻辑服务;最下边一层是数据储存层,微信红包最主要的数据是订单数据,包括发红包订单和拆红包订单两部份。业务逻辑和储存服务器之间是数据接入层,它最重要的作用是封装数据库操作的领域逻辑,致使业务逻辑服务不须要感知对MySQL的联接管理、性能、容灾等问题。
微信红包数据的访问热度,随着时间流逝会随之减少,也就是数据的访问时间段十分集中,通常红包发出两天后,99%的用户不会再去点开这个红包了。因而微信红包系统采取按时间做冷热数据分离,增加数据的储存成本,同时提高了热数据的访问性能。
数据平台用于对红包数据的剖析估算,例如同学圈里的文章,统计从2016年1月1日到2017年1月一个用户总共抢红包的金额,在全省的排行情况,发红包数最多的城市等。另外一个作用就是对帐,红包的订单和微信支付的订单须要对帐,以保证最终资金的一致性;订单的数据和订单的cache须要做对帐,以保证数据的完整性;订单数据和用户的收发记录须要对帐,以保证用户列表完整性。
微信红包系统可用性实践
系统可用性影响诱因
系统的可用性影响诱因可分成两类,一类计划外,一类计划内。计划外包含好多诱因,系统用到的所有东西都可能形成故障,都可能成功影响可用性的诱因。从这个角度上来讲,可以说故障是难以避开的,系统的运作一定会形成故障,尤其是服务器有成千上万个的时侯。计划内的影响诱因,主要有与升级相关、运维相关的操作,以及日常的备份等。这一类影响诱因,通过精细地设计方案,是可以防止对可用性导致影响的。
微信红包系统可用性设计方向
基于前面两个剖析推论,可以总结出微信红包后台系统的可用性的设计方向。就是在不能防止意外故障的情况下,尽可能减少出现意外故障时对可用性的影响。另一方面,绝大多数计划内的日常维护可以通过方案的设计避开影响可用性微信订单系统,其中平行扩容特指关于储存层的平行扩容。
下边从减少故障影响和微信红包系统的平行扩容两方面进行剖析。
首先是减少意外故障的影响,重点讲解订单储存层在订单DB故障的情况下怎样增加对红包系统可用性的影响。
业务逻辑层-布署方案设计
首先是业务逻辑层的布署方案。业务逻辑层是无状态的,微信红包系统的业务逻辑层,布署在两个城市,即两地布署,每一个城市布署起码三个园区,即三个IDC。而且每位服务须要保证三个IDC的布署均衡。另外,三个IDC总服务能力须要冗余三分之一,当一个IDC出现故障时,服务能力依然足够。进而达到IDC故障不会对可用性形成影响。
业务逻辑层-异步化设计
第二是异步化设计。如上图所示,微信红包的个别步骤不实时完成也不会影响用户对红包业务可用性的体验。例如拆红包,正常的业务流程很长,但关键步骤只有订单相关的几步。至于转零钱、写红包记录等操作不须要实时。用户抢到红包时,通常不会实时去皮夹查看微信零钱,而是在微信群中点开消息查看本次抢到金额和别人抢红包金额。
所以拆红包时只须要从cache查询用户是否拆过红包,之后写入拆红包的订单记录,更新发红包订单,其他的操作都可以异步化。其实,不是每位业务都可以进行异步化设计,须要进行业务剖析,判定是否存在非关键步骤之外的事情可以将其异步化,并通过异步对帐保证最终一致。
接出来是微信红包订单储存设计。上图是2014年微信红包储存层的模型。业务逻辑层恳求数据层操作时,使用订单号hash路由到订单服务器。订单服务器与每一组MySQL数据库联接。
微信红包的订单号是在发红包时系统生成惟一标示,使用序列号服务生成惟一ID,前面拼接三位微信红包的订单分库表的标示。所以,总共可以分一百个逻辑库,每位逻辑库富含十张表。一百个逻辑库均匀地分布到十组数学DB,每组DB存十个逻辑库。
这个构架的最大问题是,一组DB故障时,会影响其他DB。
在2014-2015年期间,微信红包量涨得非常快,扩容速率跟不上业务下降速率。一组DB的性能出现困局时,数据操作变慢,拆红包的事务操作在MYSQL排队等待。因为所有十组DB机器与所有的订单服务器联接,造成所有的订单都被拖住,因而影响红包整体的可用性。这个构架的另一个问题是扩容不便捷,旁边会介绍。
为解决DB间的互相影响,须要将DB间互相隔离,订单储存层SET化。SET化指订单DB和订单接入垂直Stick一起。业务逻辑层访问订单时,依照订单倒数第二、三位数字找到所属订单SET,一个SET的恳求不能路由到其他SET。
找到对应的订单接入服务器以后,在服务器内的多个进程中找到指定进程,让同个红包的所有拆恳求串行化。当一组DB出现故障,只会影响该组DB对应的。
这儿有一个问题,DB故障拖住个别订单,会不会也拖住更下层业务逻辑服务?业务逻辑层为何不一起SET化?业务逻辑层承载了用户维度相关的业务操作,不可以根据订单的维度分业务逻辑,比如务逻辑层会恳求用户的头像、昵称等,假如继续依照订单分业务逻辑,会造成跨地域调用。
微信红包系统采取的方案是,在订单服务端降低快速拒绝服务的能力。服务器主动监控DB的性能情况,DB性能增长、自身的CPU使用下降,或则发觉其他的监控维度超标时,订单直接向下层报错,不再去访问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的接入,最后在傍晚业务低峰时停服扩容。
这个扩容形式的复杂性,根本缘由是数据须要从旧SET迁到新SET。假如新形成数据与旧数据没关系,这么就可以省掉这部份的迁移动作,不需停服输。剖析发觉,须要把旧数据迁下来的缘由是订单号段00-99已全部被用,每位化学数据库包含了10个逻辑库。假如将订单号重新设计,预留三位空间,三位数字每一个代表独立的化学DB,原先10组DB分别为000-009号段。
这些设计,缩容时,例如要缩掉000这组,只需在业务逻辑服务上不生成订单号为000的红包订单。扩容时,例如扩为11组,只需多生成010的订单号,这个数据便手动写入新DB。其实,缩容须要一个前提条件,也就是冷热分离,缩容后数据变为冷数据,可下线热数据机器。以上就是红包的平行扩缩容方案。
储存层的高可用设计
读写分离
写恳求须要在DB主机上,实时读也须要走主机。有大量对延时不这么敏感,又影响性能的查询,完全可以放在DB从机。读写分离策略是MySQL分布式的入门,简约地提升了系统容量。
水平切分
数据的水平切分,实质就是分库分表;选定一张数据表根据主要经度把数据拆分开。实现储存层的平行扩充。有效减少了单台数据库机器的负载,也降低了服务不可用的可能性。单台数据库宕机只会造成部份数据不能访问。主要须要考虑路由规则的选取,便捷扩缩容以及数据的均衡分布。
垂直切分
数据表不仅水平切分,行内数据可以按属性进一步分开。核心表只保留最关键的数组,保证数据文件短小紧凑。以红包为例,爱称和问候语这类较长的信息,不属于核心数据,完全可以切分到别的机器上,进一步提高核心数据库的容量。不同数据适宜的储存类型也不一样,这类重复率高的长字符串更适宜NoSQL储存,对储存空间和性能都是节省极大。
空间换时间
按不同经度组织表,例如按订单属性和用户属性进行组织;适应不同的恳求场景,防止复杂的查询。不同经度的表可以通过对帐对齐,非核心表可以适当冗余,降低多次恳求。
锁的优化
多人争抢红包通过数据库事物来保证,必然存在竞争MySQL行锁。核心事物必须尽量精简,防止死锁。同一个订单的所有恳求,尽量在逻辑层进程预排队后通过一个联接发送恳求到数据库。
冷热分离
核心数据库储存高频数据,其他数据可以定时移到成本低的冷数据库中。
这样可以为核心数据库使用最好的SSD设备,快速设备容量较小较贵,不可能在全量数据上使用。同时可以保证数据表的容量不会仍然积累,大表也会造成性能增长。
小结
微信红包系统的可用性实践微信订单系统,主要包括了布署设计、SET化设计、异步化设计、红包订单储存构架迭代,数据库故障自愈能力建设、平行扩容设计。
在业务从起步到小跑再到腾飞的过程中,背后的海量服务能力将对其最终胜败有着越来越深远的影响。
在完成这种设计后,微信红包系统的可用性得到了很大提高,在2017年元旦实现了0故障,在平时的运行中达到99.99%可用性。
免责声明:部分文章信息来源于网络以及网友投稿,本站只负责对文章进行整理、排版、编辑,出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性,如本站文章和转稿涉及版权等问题,请作者在及时联系本站,我们会尽快为您处理。