查看: 47|回复: 0

微信红包后台系统可用性设计实践

[复制链接]
  • TA的每日心情

    2017-2-20 17:47
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    1473

    主题

    1777

    帖子

    26万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    263363
    发表于 2017-9-18 12:02:28 | 显示全部楼层 |阅读模式
    微信红包业务量级的高速发展,对后台系统架构的可用性要求越来越高。在保障微信红包业务体验的前提下,红包后台系统进行了一系列高可用方面的优化设计。本次演讲介绍了微信红包后台系统的高可用实践经验,主要包括后台的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一起。业务逻辑层访问订单时,根据订单倒数第二、三位数字找到所属订单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%可用性。

    91源码社区-诚信做互联网,致力于中国最大的源码分享交流平台,VIP免费下载.源码仅限研究和学习使用,禁止用于非法用途。
    回复

    使用道具 举报

    使用 高级模式(可批量传图、插入视频等)
    您需要登录后才可以回帖 登录 | 立即注册

    快速回复 返回顶部 返回列表