与传统意义上的红包相比,近两年火起来的“红包”,彷佛才是现在春节的一大重头戏。历经上千年时代传承与变迁,春节发红包早已成为历史沉淀的文化习俗,融入了民族的血脉。按照各家公布的数据,除夕全天微信用户红包总发送量达到80.8亿个,红包峰值收发量为40.9万个/秒。春晚直播期间讨论春晚的微博达到5191万条,网友互动量达到1.15亿,网友抢微博红包的总次数超过8亿次。html
为此,InfoQ策划了“春节红包”系列文章,以期为读者剖析各大平台的红包活动背后的技术细节。本文为微信篇。算法
微信红包在通过15年春晚摇一摇以后,2015年上半年业务量一度呈指数级增加。尤为是微信红包活跃用户数的大量增加,使得2016除夕跨年红包成为极大挑战。为了应对16年春节可预知的红包海量业务,红包系统在架构上进行了一系列调整和优化。主要包括异地架构、cache系统优化、拆红包并发策略优化、存储优化一系列措施,为迎接2016春节红包挑战作好准备。 下面介绍最主要的一些思路。数据库
微信用户在国内有深圳、上海两个接入点,习惯性称之为南、北(即深圳为南,上海为北)。用户请求接入后,不一样业务根据业务特性选择部署方式。微信红包在信息流上能够分为订单纬度与用户纬度。其中订单是贯穿红包发、抢、拆、详情列表等业务的关键信息,属于交易类信息;而用户纬度指的是红包用户的收红包列表、发红包列表,属于展现类信息。红包系统在架构上,有如下几个方面:缓存
南北分布服务器
一、订单层南北独立体系,数据不一样步微信
用户就近接入,请求发红包时分配订单南北,并在单号打上南北标识。抢红包、拆红包、查红包详情列表时,接入层根据红包单号上的南北标识将流量分别引到南北系统闭环。根据发红包用户和抢红包用户的所属地不一样,有如下四种状况:架构
1) 深圳用户发红包,深圳用户抢并发
订单落在深圳,深圳用户抢红包时不须要跨城,在深圳完成闭环。异步
2) 深圳用户发红包,上海用户抢高并发
订单落在深圳,上海用户抢红包,在上海接入后经过专线跨城到深圳,最后在深圳闭环完成抢红包。
3) 上海用户发红包,上海用户抢
订单落在上海,上海用户抢红包时不须要跨城,在上海完成闭环。
4) 上海用户发红包,深圳用户抢
订单落在上海,深圳用户抢红包,从深圳接入后经过专线跨城到上海,最后在上海闭环完成抢红包。
系统这样设计,好处是南北系统分摊流量,下降系统风险。
二、用户数据写多读少,全量存深圳,异步队列写入,查时一边跨城
用户数据的查询入口,在微信钱包中,隐藏的很深。这决定了用户数据的访问量不会太大,并且也被视为可旁路的非关键信息,实时性要求不高。所以,只须要在发红包、拆红包时,从订单纬度拆分出用户数据写入请求,由MQ异步写入深圳。后台将订单与用户进行定时对帐保证数据完整性便可。
三、支持南北流量灵活调控
红包系统南北分布后,订单落地到深圳仍是上海,是能够灵活分配的,只须要在接入层上作逻辑。例如,能够在接入层中,实现让全部红包请求,都落地到深圳(不管用户从上海接入,仍是深圳接入),这样上海的红包业务系统将不会有请求量。提高了红包系统的容灾能力。同时,实现了接入层上的后台管理系统,实现了秒级容量调控能力。可根据南北请求量的实时监控,作出对应的调配。
四、DB故障时流量转移能力
基于南北流量的调控能力,当发现DB故障时,可将红包业务流量调到另一边,实现DB故障的容灾。
预订单
支付前订单落cache,同时利用cache的原子incr操做顺序生成红包订单号。优势是cache的轻量操做,以及减小DB废单。在用户请求发红包与真正支付之间,存在必定的转化率,部分用户请求发红包后,并不会真正去付款。
拆红包入帐异步化
信息流与资金流分离。拆红包时,DB中记下拆红包凭证,而后异步队列请求入帐。入帐失败经过补偿队列补偿,最终经过红包凭证与用户帐户入帐流水对帐,保证最终一致性。
这个架构设计,理论基础是快慢分离。红包的入帐是一个分布事务,属于慢接口。而拆红包凭证落地则速度快。实际应用场景中,用户抢完红包,只关心详情列表中谁是“最佳手气”,不多关心抢到的零是否已经到帐。由于只须要展现用户的拆红包凭证便可。
发拆落地,其余操做双层cache
一、Cache住全部查询,两层cache
除了使用ckv作全量缓存,还在数据访问层dao中增长本机内存cache作二级缓存,cache住全部读请求。
查询失败或者查询不存在时,降级内存cache;内存cache查询失败或记录不存在时降级DB。
DB自己不作读写分离。
二、DB写同步cache,容忍少许不一致
DB写操做完成后,dao中同步内存cache,业务服务层同步ckv,失败由异步队列补偿,定时的ckv与DB备机对帐,保证最终数据一致。
微信红包的并发挑战,主要在于微信大群,多人同时抢同一个红包。这种状况,存在竞争MySQL行锁。为了控制这种并发,团队作了如下一些事情:
一、请求按红包订单路由,逻辑块垂直sticky,事务隔离
按红包订单划分逻辑单元,单元内业务闭环。服务rpc调用时,使用红包订单号的hash值为key寻找下一跳地址。对同一个红包的全部拆请求、查询请求,都路由到同一台逻辑机器、同一台DB中处理。
二、Dao搭建本机Memcache内存cache,控制同一红包并发个数
在DB的接入机dao中,搭建本机内存cache。以红包订单号为key,对同一个红包的拆请求作原子计数,控制同一时刻能进DB中拆红包的并发请求数。
这个策略的实施,依赖于请求路由按红包订单hash值走,确保同一红包的全部请求路由到同一逻辑层机器。
三、多层级并发量控制
1) 发红包控制
发红包是业务流程的入口,控制了这里的并发量,表明着控制了红包业务总体的并发量。在发红包的业务链路里,作了多层的流量控制,确保产生的有效红包量级在可控范围。
2) 抢红包控制
微信红包领取时分为两个步骤,抢和拆。抢红包这个动做自己就有控制拆并发的做用。由于抢红包时,只须要查cache中的数据,不须要请求DB。对于红包已经领完、用户已经领过、红包已通过期等流量能够直接拦截。而对于有资格进入拆红包的请求量,也作流量控制。经过这些处理,最后可进入拆环节的流量大大减小,而且都是有效请求。
3) 拆时内存cache控制
针对同一个红包并发拆的控制,上文已经介绍。
四、DB简化和拆分
DB的并发能力,有不少影响因素。红包系统结合红包使用情境,进行了一些优化。比较有借鉴意义的,主要有如下两点:
1) 订单表只存关键字段,其余字段只在cache中存储,可柔性。
红包详情的展现中,除了订单关键信息(用户、单号、金额、时间、状态)外,还有用户头像、昵称、祝福语等字段。这些字段对交易来讲不是关键信息,却占据大量的存储空间。
将这些非关键信息拆出来,只存在cache,用户查询展现,而订单中不落地。这样能够维持订单的轻量高效,同时cache不命中时,又可从实时接口中查询补偿,达到优化订单DB容量的效果。
2) DB双重纬度分库表,冷热分离
使用订单hash、订单日期,两个纬度分库表,也即db_xxx.t_x_dd这样的格式。其中,x表示订单hash值,dd表示01-31循环日。订单hash纬度,是为了将订单打散到不一样的DB服务器中,均衡压力。订单日期循环日纬度,是为了不单表数据无限扩张,使天天都是一张空表。
另外,红包的订单访问热度,是很是典型的冷热型。热数据集中在一两天内,且随时间急剧消减。线上热数据库只须要存几天的数据,其余数据能够定时移到成本低的冷数据库中。循环日表也使得历史数据的迁移变得方便。
首先,若是红包只有一个,本轮直接使用所有金额,确保红包发完。
而后,计算出本轮红包最少要领取多少,才能保证红包领完,即本轮下水位;轮最多领取多少,才能保证每一个人都领到,即本轮上水位。主要方式以下:
计算本轮红包金额下水位:假设本轮领到最小值1分,那接下来每次都领到200元红包能领完,那下水位为1分;若是不能领完,那按接下来每次都领200元,剩下的本轮应所有领走,是本轮的下水位。
计算本轮红包上水位:假设本轮领200元,剩下的钱还足够接下来每轮领1分钱,那本轮上水位为200元;若是已经不够领,那按接下来每轮领1分,计算本轮的上水位。
为了使红包金额不要太悬殊,使用红包均值调整上水位。若是上水位金额大于两倍红包均值,那么使用两倍红包均值做为上水位。换句话说,每一轮抢到的红包金额,最高为两倍剩下红包的均值。
最后,获取随机数并用上水位取余,若是结果比下水位还小,则直接使用下水位,不然使用随机金额为本轮拆到金额。
系统处处存在发生异常的可能,须要对全部的环节作好应对的预案。下面列举微信红包对系统异常的主要降级考虑。
一、 下单cache故障降级DB
下单cache有两个做用,生成红包订单与订单缓存。缓存故障状况下,降级为直接落地DB,并使用id生成器独立生成订单号。
二、 抢时cache故障降级DB
抢红包时,查询cache,拦截红包已经抢完、用户已经抢过、红包已通过期等无效请求。当cache故障时,降级DB查询,同时打开DB限流保护开关,防止DB压力过大致使服务不可用。
另外,cache故障降级DB时,DB不存储用户头像、用户昵称等(上文提到的优化),此时一并降级为实时接口查询。查询失败,继续降级为展现默认头像与昵称。
三、 拆时资金入帐多级柔性
拆红包时,DB记录拆红包单据,而后执行资金转帐。单据须要实时落地,而资金转帐,这里作了多个层级的柔性降级方案:
大额红包实时转帐,小额红包入队列异步转帐 全部红包进队列异步转帐 实时流程不执行转帐,过后凭单据批量入帐。
总之,单据落地后,真实入帐可实时、可异步,最终保证一致便可。
四、 用户列表降级
用户列表数据在微信红包系统中,属于非关键路径信息,属于可被降级部分。
首先,写入时经过MQ异步写,经过定时对帐保证一致性。
其次,cache中只缓存两屏,用户查询超过两屏则查用户列表DB。在系统压力大的状况下,能够限制用户只查两屏。
调整后的系统通过了16年春节的实践检验,平稳地度过了除夕业务高峰,保障了红包用户的体验。
方乐明,2011年毕业于华南理工大学通讯与信息系统专业,毕业后就任于财付通科技有限公司。微信支付团队组建后,主要负责微信红包、微信转帐、AA收款等支付应用产品的后台架构。
原文:http://www.infoq.com