《支付宝的架构到底有多牛逼?还没看完我就跪了!.docx》由会员分享,可在线阅读,更多相关《支付宝的架构到底有多牛逼?还没看完我就跪了!.docx(36页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、支付宝的架构到底有多牛逼?还没看完我就跪了!来源|Java之道自2020年度双11以来在每年度双11超大规模流量的冲击上蚂蚁金服都会不断打破现有技术的极限。2020年度双11的支付峰值为2万笔/分钟到2017年度双11时这个数字变为了25.6万笔/秒。2018年度双11的支付峰值为48万笔/秒2019年度双11支付峰值为54.4万笔/秒创下新纪录是2020年度第一次双11的1360倍。在如此之大的支付TPS背后除了削峰等锦上添花的应用级优化最解渴最本质的招数当数基于分库分表的单元化了蚂蚁技术称之为LDC逻辑数据中心。本文不打算讨论详细到代码级的分析而是尝试用最简单的描绘来讲明其中最大快人心的原
2、理。我想关心分布式系统设计的人都曾被下面这些问题所困扰过支付宝海量支付背后最解渴的设计是啥换句话讲实现支付宝高TPS的最关键的设计是啥LDC是啥LDC怎么实现异地多活以及异地灾备的CAP魔咒到底是啥P到底怎么理解什么是脑裂跟CAP又是啥关系什么是PAXOS它解决了啥问题PAXOS以及CAP啥关系PAXOS可以逃脱CAP魔咒么Oceanbase能逃脱CAP魔咒么假如你对这些感兴趣不妨看一场赤裸裸的阐述回绝使用晦涩难懂的词汇直面最本质的逻辑。LDC以及单元化LDClogicdatacenter是相对于传统的InternetDataCenter-IDC提出的逻辑数据中心所表达的中心思想是无论物理构造
3、怎样的分布整个数据中心在逻辑上是协同以及统一的。这句话暗含的是强大的体系设计分布式系统的挑战就在于整体协同工作可用性分区容忍性以及统一一致性。单元化是大型互联网系统的必然选择趋势举个最最通俗的例子来讲明单元化。我们总是讲TPS很难提升确实任何一家互联网公司比方淘宝、携程、新浪它的交易TPS顶多以十万计量平均程度很难往上串了。因为数据库存储层瓶颈的存在再多程度扩展的效劳器都无法绕开而从整个互联网的视角看全世界电商的交易TPS可以轻松上亿。这个例子带给我们一些考虑为啥几家互联网公司的TPS之以及可以那么大效劳的用户数规模也极为吓人而单个互联网公司的TPS却很难提升究其本质每家互联网公司都是一个独立
4、的大型单元他们各自效劳自己的用户互不干扰这就是单元化的根本特性任何一家互联网公司其想要成倍的扩大自己系统的效劳才能都必然会走向单元化之路。它的本质是分治我们把广阔的用户分为假设干局部同时把系统复制多份每一份都独立部署每一份系统都效劳特定的一群用户。以淘宝举例这样之后就会有很多个淘宝系统分别为不同的用户效劳每个淘宝系统都做到十万TPS的话N个这样的系统就可以轻松做到N*十万的TPS了。LDC实现的关键就在于单元化系统架构设计所以在蚂蚁内部LDC以及单元化是不分家的这也是很多同学比拟困扰的地方看似没啥关系实那么是单元化体系设计成就了LDC。小结分库分表解决的最大痛点是数据库单点瓶颈这个瓶颈的产生是
5、由当代二进制数据存储体系决定的即I/O速度。单元化只是分库分表后系统部署的一种方式这种部署形式在灾备方面也发挥了极大的优势。系统架构演化史几乎任何规模的互联网公司都有自己的系统架构迭代以及更新大致的演化途径都大同小异。最早一般为了业务快速上线所有功能都会放到一个应用里系统架构如下列图所示这样的架构显然是有问题的单机有着明显的单点效应单机的容量以及性能都是很局限的而使用中小型时机带来大量的浪费。随着业务开展这个矛盾逐渐转变为主要矛盾因此工程师们采用了以下架构这是整个公司第一次触碰到分布式也就是对某个应用进展了程度扩容它将多个微机的计算才能团结了起来可以完胜同等价格的中小型机器。渐渐的大众发现应用
6、效劳器CPU都很正常了但是还是有很多慢恳求究其原因是因为单点数据库带来了性能瓶颈。于是程序员们决定使用主从构造的数据库集群如下列图所示其中大局部读操作可以直接访问从库进而减轻主库的压力。然而这种方式还是无法解决写瓶颈写照旧需要主库来处理当业务量量级再次增高时写已经变成刻不容缓的待处理瓶这时候分库分表方案出现了分库分表不仅可以对一样的库进展拆分还可以对一样的表进展拆分对表进展拆分的方式叫做程度拆分。不同功能的表放到不同的库里一般对应的是垂直拆分按照业务功能进展拆分此时一般还对应了微效劳化。这种方法做到极致根本能支撑TPS在万级甚至更高的访问量了。然而随着一样应用扩展的越多每个数据库的链接数也巨量
7、增长这让数据库本身的资源成为了瓶颈。这个问题产生的本质是全量数据无差异的共享了所有的应用资源比方A用户的恳求在负载平衡的分配下可能分配到任意一个应用效劳器上因此所有应用全部都要链接A用户所在的分库数据库连接数就变成笛卡尔乘积了。在本质点讲这种形式的资源隔离性还不够彻底。要解决这个问题就需要把识别用户分库的逻辑往上层挪动从数据库层挪动到路由网关层。这样一来从应用效劳器a进来的来自A客户的所有恳求必然落库到DB-A因此a也不用链接其他的数据库实例了这样一个单元化的雏形就诞生了。考虑一下应用间其实也存在交互比方A转账给B也就意味着应用不需要链接其他的数据库了但是还需要链接其他应用。假如是常见的RPC
8、框架如Dubbo等使用的是TCP/IP协议那么等同于把之前与数据库建立的链接换成与其他应用之间的链接了。为啥这样就消除瓶颈了呢首先由于合理的设计应用间的数据交互并不巨量其次应用间的交互可以分享TCP链接比方A-B之间的Socket链接可以被A中的多个线程复用。而一般的数据库如MySQL那么不行所以MySQL才需要数据库链接池。如上图所示但我们把整套系统打包为单元化时每一类的数据从进单元开场就注定在这个单元被消化由于这种彻底的隔离性整个单元可以轻松的部署到任意机房而仍然能保证逻辑上的统一。下列图为一个三地五机房的部署方式蚂蚁单元化架构理论蚂蚁支付宝应该是国内最大的支付工具其在双11等活动日当日的
9、支付TPS可达几十万级将来这个数字可能会更大这决定了蚂蚁单元化架构沉着量要求上看必然从单机房走向多机房。另一方面异地灾备也决定了这些IDC机房必须是异地部署的。整体上支付宝也采用了三地五中心IDC机房来保障系统的可用性。跟上文中描绘的有所不同的是支付宝将单元分成了三类也称CRG架构RZoneRegionZone直译可能有点反而不好理解。实际上就是所有可以分库分表的业务系统整体部署的最小单元。每个RZone连上数据库就可以撑起一片天空把业务跑的溜溜的。GZoneGlobalZone全局单元意味着全局只有一份。部署了不可拆分的数据以及效劳比方系统配置等。实际情况下GZone异地也会部署不过仅是用于
10、灾备同一时刻只有一地GZone进展全局效劳。GZone一般被RZone依赖提供的大局部是读取效劳。CZoneCityZone顾名思义这是以城市为单位部署的单元。同样部署了不可拆分的数据以及效劳比方用户账号效劳客户信息效劳等。理论上CZone会被RZone以比访问GZone高很多的频率进展访问。CZone是基于特定的GZone场景进展优化的一种单元它把GZone中有些有着写读时间差现象的数据以及效劳进展了的单独部署这样RZone只需要访问本地的CZone即可而不是访问异地的GZone。 “写读时间差现象是蚂蚁架构师们根据理论统计总结的他们发现大局部情况下一个数据被写入后都会过足够长的时间后才会被
11、访问。生活中这种例子很常见我们办完银行卡后可能很久才会存第一笔钱我们创立微博账号后可能想半天才会发微博我们下载创立淘宝账号后可能得阅读好几分钟才会下单买东西。当然了这些例子中的时间差远远超过了系统同步时间。一般来讲异地的延时在100ms以内所以只要知足某地CZone写入数据后100ms以后才用这个数据这样的数据以及效劳就合适放到CZone中。相信大众看到这都会问为啥分这三种单元其实其背后对应的是不同性质的数据而效劳不过是对数据的操作集。下面我们来根据数据性质的不同来解释支付宝的CRG架构。当下几乎所有互联网公司的分库分表规那么都是根据用户ID来制定的。而围绕用户来看整个系统的数据可以分为以下两
12、类用户流水型数据典型的有用户的订单、用户发的评论、用户的行为记录等。这些数据都是用户行为产生的流水型数据具备天然的用户隔离性比方A用户的App上绝对看不到B用户的订单列表。所以此类数据非常合适分库分表后独立部署效劳。用户间分享型数据这种类型的数据又分两类。一类分享型数据是像账号、个人boke等可能会被所有用户恳求访问的用户数据。比方A向B转账A给B发消息这时候需要确认B账号是否存在又比方A想看B的个人boke之类的。另外一类是用户无关型数据像商品、系统配置汇率、优惠政策、财务统计等这些非用户纬度的数据很难讲跟详细的某一类用户挂钩可能涉及到所有用户。比方商品假设按商品所在地来存放商品数据这需要双
13、维度分库分表那么上海的用户仍然需要访问杭州的商品。这就又构成跨地跨Zone访问了还是达不到单元化的理想状态而且双维度分库分表会给整个LDC运维带来复杂度提升。注网上以及支付宝内部有另外一些分法比方流水型以及状态性有时候还会分为三类流水型、状态型以及配置型。个人觉得这些分法固然尝试去更高层次的抽象数据分类但实际上边界很模糊适得其反。直观的类比我们可以很轻易的将上述两类数据对应的效劳划分为RZone以及GZoneRZone包含的就是分库分表后负责固定客户群体的效劳GZone那么包含了用户间分享的公共数据对应的效劳。到这里为止一切都很完美这也是主流的单元化话题了。比照支付宝的CRG架构我们一眼就发现
14、少了CCityZoneCZone确实是蚂蚁在单元化理论领域的一个创新点。再来分析下GZoneGZone之所以只能单地部署是因为其数据要求被所有用户分享无法分库分表而多地部署会带来由异地延时引起的不一致。比方实时风控系统假如多地部署某个RZone直接读取本地的话很容易读取到旧的风控状态这是很危险的。这时蚂蚁架构师们问了自己一个问题难道所有数据受不了延时么这个问题像是翻开了新世界的大门通过对RZone已有业务的分析架构师们发现80%甚至更高的场景下数据更新后都不要求立马被读取到。也就是上文提到的写读时间差现象那么这就好办了对于这类数据我们允许每个地区的RZone效劳直接访问本地为了给这些RZone
15、提供这些数据的本地访问才能蚂蚁架构师设计出了CZone。在CZone的场景下写恳求一般从GZone写入公共数据所在库然后同步到整个OB集群然后由CZone提供读取效劳。比方支付宝的会员效劳就是如此。即便架构师们设计了完美的CRG但即便在蚂蚁的实际应用中各个系统仍然存在不合理的CRG分类尤其是CG不分的现象很常见。支付宝单元化的异地多活以及灾备流量挑拨技术探秘简介单元化后异地多活只是多地部署而已。比方上海的两个单元为ID范围为00194059的用户效劳。而杭州的两个单元为ID为2039以及60,79的用户效劳这样上海以及杭州就是异地双活的。支付宝对单元化的根本要求是每个单元都具备效劳所有用户的才
16、能即详细的那个单元效劳哪些用户是可以动态配置的。所以异地双活的这些单元还充当了彼此的备份。发现工作中冷备热备已经被用的很乱了。最早冷备是指数据库在备份数据时需要关闭后进展备份也叫离线备份防止数据备份经过中又修改了不需要关闭即在运行经过中进展数据备份的方式叫做热备也叫在线备份。也不知道从哪一天开场冷备在主备系统里代表了这台备用机器是关闭状态的只有主效劳器挂了之后备效劳器才会被启动。而一样的热备变成了备效劳器也是启动的只是没有流量而已一旦主效劳器挂了之后流量自动打到备效劳器上。本文不打算用第二种理解因为感觉有点野。为了做到每个单元访问哪些用户变成可配置支付宝要求单元化管理系统具备流量到单元的可配置
17、和单元到DB的可配置才能。如下列图所示其中Spanner是蚂蚁基于Nginx自研的反向代理网关也很好理解有些恳求我们祈望在反向代理层就被转发至其他IDC的Spanner而无需进入后端效劳如图箭头2所示。那么对于应该在本IDC处理的恳求就直接映射到对应的RZ即可如图箭头1。进入后端效劳后理论上假如恳求只是读取用户流水型数据那么一般不会再进展路由了。然而对于有些场景来讲A用户的一个恳求可能关联了对B用户数据的访问比方A转账给BA扣完钱后要调用账务系统去增加B的余额。这时候就涉及到再次的路由同样有两个结果跳转到其他IDC如图箭头3或者是跳转到本IDC的其他RZone如图箭头4。RZone到DB数据分
18、区的访问这是事先配置好的上图中RZ以及DB数据分区的关系为RZ0*-aRZ1*-bRZ2*-cRZ3*-d下面我们举个例子来讲明整个流量挑拨的经过假设C用户所属的数据分区是c而C用户在杭州访问了cashier.alipay随意编的。目前支付宝默认会按照地域来路由流量详细的实现承载者是自研的GLSBGlobalServerLoadBalancings:/developer.alipay/article/1889它会根据恳求者的IP自动将cashier.alipay解析为杭州IDC的IP地址或跳转到IDC所在的域名。大众自己搞过网站的化应该知道大局部DNS效劳商的地址都是靠人去配置的GLSB属于动
19、态配置域名的系统网上也有比拟火的类似产品比方花生壳之类建过私站的同学应该很熟悉的。好了到此为止用户的恳求来到了IDC-1的Spanner集群效劳器上Spanner从内存中读取到了路由配置知道了这个恳求的主体用户C所属的RZ3*不再本IDC于是直接转到了IDC-2进展处理。进入IDC-2之后根据流量配比规那么该恳求被分配到了RZ3B进展处理。RZ3B得到恳求后对数据分区c进展访问。处理完毕后原路返回。大众应该发现问题所在了假如再来一个这样的恳求岂不是每次都要跨地域进展调用以及返回体传递确实是存在这样的问题的对于这种问题支付宝架构师们决定继续把决策逻辑往用户终端推移。比方每个IDC机房都会有自己的
20、域名真实情况可能不是这样命名的:IDC-1对应cashieridc-1.alipayIDC-2对应cashieridc-2.alipay那么恳求从IDC-1涮过一遍返回时会将前端恳求跳转到cashieridc-2.alipay去假如是App只需要交换rest调用的接口域名后面所有用户的行为都会在这个域名上发生就防止了走一遍IDC-1带来的延时。支付宝灾备机制流量挑拨是灾备切换的根底以及前提条件发生灾难后的通用方法就是把陷入灾难的单元的流量重新打到正常的单元上去这个流量切换的经过俗称切流。支付宝LDC架构下的灾备有三个层次同机房单元间灾备同城机房间灾备异地机房间灾备同机房单元间灾备灾难发生可能性
21、相对最高但其实也很小。对LDC来讲最小的灾难就是某个单元由于一些原因部分插座断开、线路老化、人为操作失误宕机了。从上节里的图中可以看到每组RZ都有AB两个单元这就是用来做同机房灾备的并且AB之间也是双活双备的。正常情况下AB两个单元共同分担所有的恳求一旦A单元挂了B单元将自动承当A单元的流量份额。这个灾备方案是默认的。同城机房间灾备灾难发生可能性相对更小。这种灾难发生的原因一般是机房电线网线被挖断或机房维护人员操作失误导致的。在这种情况下就需要人工的制定流量挑拨切流方案了。下面我们举例讲明这个经过如下列图所示为上海的两个IDC机房。整个切流配置经过分两步首先需要将陷入灾难的机房中RZone对应
22、的数据分区的访问权配置进展修改。假设我们的方案是由IDC-2机房的RZ2以及RZ3分别接收IDC-1中的RZ0以及RZ1。那么首先要做的是把数据分区ab对应的访问权从RZ0以及RZ1收回分配给RZ2以及RZ3。即将如上图所示为初始映射RZ0*-aRZ1*-bRZ2*-cRZ3*-d变为RZ0*-/RZ1*-/RZ2*-aRZ2*-cRZ3*-bRZ3*-d然后再修改用户ID以及RZ之间的映射配置。假设之前为00-24-RZ0A(50%),RZOB(50%)25-49-RZ1A(50%),RZ1B(50%)50-74-RZ2A(50%),RZ2B(50%)75-99-RZ3A(50%),RZ3B
23、(50%)那么按照灾备方案的要求这个映射配置将变为00-24-RZ2A(50%),RZ2B(50%)25-49-RZ3A(50%),RZ3B(50%)50-74-RZ2A(50%),RZ2B(50%)75-99-RZ3A(50%),RZ3B(50%)这样之后所有流量将会被打到IDC-2中期间局部已经向IDC-1提议恳求的用户会收到失败并重试的提示。实际情况中整个经过并不是灾难发生后再去做的整个切换的流程会以预案配置的形式事先准备好推送给每个流量挑拨客户端集成到了所有的效劳以及Spanner中。这里可以考虑下为何先切数据库映射再切流量呢这是因为假如先切流量意味着大量注定失败的恳求会被打到新的正常
24、单元上去进而影响系统的稳定性数据库还没准备好。异地机房间灾备这个根本上跟同城机房间灾备一致这也是单元化的优点不再赘述。蚂蚁单元化架构的CAP分析回首CAPCAP的定义CAP原那么是指任意一个分布式系统同时最多只能知足其中的两项而无法同时知足三项。所谓的分布式系统讲白了就是一件事一个人做的如今分给好几个人一起干。我们先简单回首下CAP各个维度的含义Consistency一致性这个理解起来很简单就是每时每刻每个节点上的同一份数据都是一致的。这就要求任何更新都是原子的即要么全部成功要么全部失败。想象一下使用分布式事务来保证所有系统的原子性是多么低效的一个操作。Availability可用性这个可用性
25、看起来很容易理解但真正讲清楚的不多。我更愿意把可用性解释为任意时刻系统都可以提供读写效劳。举个例子当我们用事务将所有节点锁住来进展某种写操作时假如某个节点发生不可用的情况会让整个系统不可用。对于分片式的NoSQL中间件集群RedisMemcached来讲一旦一个分片歇菜了整个系统的数据也就不完好了读取宕机分片的数据就会没响应也就是不可用了。需要讲明一点哪些选择CP的分布式系统并不是代表可用性就完全没有了只是可用性没有保障了。为了增加可用性保障这类中间件往往都提供了分片集群复制集的方案。Partitiontolerance分区容忍性这个可能也是很多文章都没讲清楚的。P并不是像CA一样是一个独立的
26、性质它依托于CA来进展讨论。参考文献中的解释除非整个网络瘫痪否那么任何时刻系统都能正常工作言下之意是小范围的网络瘫痪节点宕机都不会影响整个系统的CA。我感觉这个解释听着还是有点懵逼所以个人更愿意解释为当节点之间网络不通时出现网络分区可用性以及一致性仍然能得到保障。从个人角度理解分区容忍性又分为“可用性分区容忍性以及“一致性分区容忍性。出现分区时会不会影响可用性的关键在于需不需要所有节点相互沟通协作来完成一次事务不需要的话是铁定不影响可用性的。庆幸的是应该不太会有分布式系统会被设计成完成一次事务需要所有节点联动一定要举个例子的话全同步复制技术下的MySQL是一个典型案例。出现分区时会不会影响一致
27、性的关键那么在于出现脑裂时有没有保证一致性的方案这对主从同步型数据库MySQL、SQLServer是致命的。一旦网络出现分区产生脑裂系统会出现一份数据两个值的状态谁都不觉得自己是错的。需要讲明的是正常来讲同一局域网内网络分区的概率非常低这也是为啥我们最熟悉的数据库MySQL、SQLServer等也是不考虑P的原因。下列图为CAP之间的经典关系图还有个需要讲明的地方其实分布式系统很难知足CAP的前提条件是这个系统一定是有读有写的假如只考虑读那么CAP很容易都知足。比方一个计算器效劳承受表达式恳求返回计算结果搞成程度扩展的分布式显然这样的系统没有一致性问题网络分区也不怕可用性也是很稳的所以可以知足
28、CAP。CAP分析方法先讲下CA以及P的关系假如不考虑P的话系统是可以轻松实现CA的。而P并不是一个单独的性质它代表的是目的分布式系统有没有对网络分区的情况做容错处理。假如做了处理就一定是带有P的接下来再考虑分区情况下到底选择了A还是C。所以分析CAP建议先确定有没有对分区情况做容错处理。以下是个人总结的分析一个分布式系统CAP知足情况的一般方法if(不存在分区的可能性|分区后不影响可用性或者一致性|有影响但考虑了分区情况-P)if(可用性分区容忍性-AunderP)returnAPelseif(一致性分区容忍性-CunderPreturnCPelse/分区有影响但没考虑分区情况下的容错if(
29、具备可用性-A具备一致性-CreturnAC;这里讲明下假如考虑了分区容忍性就不需要考虑不分区情况下的可用性以及一致性了大多是知足的。程度扩展应用单数据库实例的CAP分析让我们再来回首下分布式应用系统的来由早年度每个应用都是单体的跑在一个效劳器上效劳器一挂效劳就不可用了。另外一方面单体应用由于业务功能复杂对机器的要求也逐渐变高普通的微机无法知足这种性能以及容量的要求。所以要拆还在IBM大卖小型商用机的年度代阿里巴巴就提出要以分布式微机替代小型机。所以我们发现分布式系统解决的最大的痛点就是单体单机系统的可用性问题。要想高可用必须分布式。一家互联网公司的开展之路上第一次与分布式相遇应该都是在单体应
30、用的程度扩展上。也就是同一个应用启动了多个实例连接着一样的数据库为了简化问题先不考虑数据库是否单点如下列图所示这样的系统天然具有的就是AP可用性以及分区容忍性一方面解决了单点导致的低可用性问题。另一方面无论这些程度扩展的机器间网络是否出现分区这些效劳器都可以各自提供效劳因为他们之间不需要进展沟通。然而这样的系统是没有一致性可言的想象一下每个实例都可以往数据库insert以及update注意这里还没讨论到事务那还不乱了套。于是我们转向了让DB去做这个事这时候数据库事务就被用上了。用大局部公司会选择的MySQL来举例用了事务之后会发现数据库又变成了单点以及瓶颈。单点就像单机一样(本例子中不考虑从库
31、形式)理论上就不叫分布式了假如一定要分析其CAP的话根据上面的步骤分析经过应该是这样的分区容忍性先看有没有考虑分区容忍性或分区后是否会有影响。单台MySQL无法构成分区要么整个系统挂了要么就活着。可用性分区容忍性分区情况下假设恰好是该节点挂了系统也就不可用了所以可用性分区容忍性不知足。一致性分区容忍性分区情况下只要可用单点单机的最大好处就是一致性可以得到保障。因此这样的一个系统个人认为只是知足了CP。A有但不出色从这点可以看出CAP并不是非黑即白的。包括常讲的BASE最终一致性方案其实只是C不出色但最终也是到达一致性的BASE在一致性上选择了让步。关于分布式应用单点数据库的形式算不算纯粹的分布
32、式系统这个可能每个人看法有点差异上述只是我个人的一种理解是不是分布式系统不重要重要的是分析经过。其实我们讨论分布式就是祈望系统的可用性是多个系统多活的一个挂了另外的也能顶上显然单机单点的系统不具备这样的高可用特性。所以在我看来广义的讲CAP也适用于单点单机系统单机系统是CP的。讲到这里大众似乎也发现了程度扩展的效劳应用数据库这样的系统的CAP魔咒主要发生在数据库层。因为大局部这样的效劳应用都只是承当了计算的任务像计算器那样本身不需要相互协作所有写恳求带来的数据的一致性问题下沉到了数据库层去解决。想象一下假如没有数据库层而是应用自己来保障数据一致性那么这样的应用之间就涉及到状态的同步以及交互了Z
33、ooKeeper就是这么一个典型的例子。程度扩展应用主从数据库集群的CAP分析上一节我们讨论了多应用实例单数据库实例的形式这种形式是分布式系统也好不是分布式系统也罢整体是偏CP的。现实中技术人员们也会很快发现这种架构的不合理性可用性太低了。于是如下列图所示的形式成为了当下大局部中小公司所使用的架构从上图我可以看到三个数据库实例中只有一个是主库其他是从库。一定程度上这种架构极大的缓解了读可用性问题而这样的架构一般会做读写别离来到达更高的读可用性幸运的是大局部互联网场景中读都占了80%以上所以这样的架构能得到较长时间的广泛应用。写可用性可以通过Keepalived这种HA高可用框架来保证主库是活着
34、的但仔细一想就可以明白这种方式并没有带来性能上的可用性提升。还好至少系统不会因为某个实例挂了就都不可用了。可用性勉强达标了这时候的CAP分析如下分区容忍性照旧先看分区容忍性主从构造的数据库存在节点之间的通信他们之间需要通过心跳来保证只有一个Master。然而一旦发生分区每个分区会自己选取一个新的Master这样就出现了脑裂常见的主从数据库MySQLOracle等并没有自带解决脑裂的方案。所以分区容忍性是没考虑的。一致性不考虑分区由于任意时刻只有一个主库所以一致性是知足的。可用性不考虑分区HA机制的存在可以保证可用性所以可用性显然也是知足的。所以这样的一个系统我们认为它是AC的。我们再深化研究下
35、假如发生脑裂产生数据不一致后有一种方式可以仲裁一致性问题是不是就可以知足P了呢。还真有尝试通过预先设置规那么来解决这种多主库带来的一致性问题的系统比方CouchDB它通过版本管理来支持多库写入在其仲裁阶段会通过DBA配置的仲裁规那么也就是合并规那么比方谁的时间戳最晚谁的生效进展自动仲裁自动合并进而保障最终一致性BASE自动规那么无法合并的情况那么只能依赖人工决策了。蚂蚁单元化LDC架构CAP分析战胜分区容忍性在讨论蚂蚁LDC架构的CAP之前我们再来想想分区容忍性有啥值得一提的为啥很多大名鼎鼎的BASE最终一致性体系系统都选择损失实时一致性而不是丢弃分区容忍性呢分区的产生一般有两种情况某台机器宕
36、机了过一会儿又重启了看起来就像失联了一段时间像是网络不可达一样。异地部署情况下异地多活意味着每一地都可能会产生数据写入而异地之间偶然的网络延时尖刺网络延时曲线图陡增、网络故障都会导致小范围的网络分区产生。前文也提到过假如一个分布式系统是部署在一个局域网内的一个物理机房内那么个人认为分区的概率极低即便有复杂的拓扑也很少会有在同一个机房里出现网络分区的情况。而异地这个概率会大大增高所以蚂蚁的三地五中心必须需要考虑这样的问题分区容忍不能丢同样的情况还会发生在不同ISP的机房之间想象一下你以及朋友组队玩DOTA他在电信你在联通。为了应对某一时刻某个机房突发的网络延时尖刺活着间歇性失联一个好的分布式系统
37、一定能处理好这种情况下的一致性问题。那么蚂蚁是怎么解决这个问题的呢我们在上文讨论过其实LDC机房的各个单元都由两局部组成负责业务逻辑计算的应用效劳器以及负责数据持久化的数据库。大局部应用效劳器就像一个个计算器自身是不对写一致性负责的这个任务被下沉到了数据库。所以蚂蚁解决分布式一致性问题的关键就在于数据库想必蚂蚁的读者大概猜到下面的讨论重点了OceanBase下文简称OB中国第一款自主研发的分布式数据库一时间也确实获得了很多光环。在讨论OB前我们先来想想WhynotMySQL首先就像CAP三角图中指出的MySQL是一款知足AC但不知足P的分布式系统。试想一下一个MySQL主从构造的数据库集群当出
38、现分区时问题分区内的Slave会认为主已经挂了所以自己成为本分区的Master脑裂。等分区问题恢复后会产生2个主库的数据而无法确定谁是正确的也就是分区导致了一致性被破坏。这样的结果是严重的这也是蚂蚁宁愿自研OceanBase的原动力之一。那么怎样才能让分布式系统具备分区容忍性呢按照老惯例我们从可用性分区容忍以及一致性分区容忍两个方面来讨论可用性分区容忍性保障机制可用性分区容忍的关键在于别让一个事务一来所有节点来完成这个很简单别要求所有节点共同同时介入某个事务即可。一致性分区容忍性保障机制老实讲都产生分区了哪还可能获得实时一致性。但要保证最终一致性也不简单一旦产生分区怎样保证同一时刻只会产生一份
39、提议呢换句话讲怎样保障仍然只有一个脑呢下面我们来看下PAXOS算法是怎样解决脑裂问题的。这里可以发散下所谓的“脑其实就是具备写才能的系统“非脑就是只具备读才能的系统对应了MySQL集群中的从库。下面是一段摘自维基百科的PAXOS定义Paxosisafamilyofprotocolsforsolvingconsensusinanetworkofunreliableprocessors(thatis,processorsthatmayfail).大致意思就是讲PAXOS是在一群不是十分可靠的节点组成的集群中的一种共识机制。Paxos要求任何一个提议至少有(N/2)1的系统节点认可才被认为是可信的这
40、背后的一个根底理论是少数服从多数。想象一下假如多数节点认可后整个系统宕机了重启后仍然可以通过一次投票知道哪个值是合法的多数节点保存的那个值。这样的设定也巧妙的解决了分区情况下的共识问题因为一旦产生分区势必最多只有一个分区内的节点数量会大于等于(N/2)1。通过这样的设计就可以巧妙的避开脑裂当然MySQL集群的脑裂问题也是可以通过其他方法来解决的比方同时Ping一个公共的IP成功者继续为脑显然这就又制造了另外一个单点。假如你解析过比特币或区块链你就知道区块链的根底理论也是PAXOS。区块链借助PAXOS对最终一致性的奉献来抵御恶意篡改。而本文涉及的分布式应用系统那么是通过PAXOS来解决分区容忍
41、性。再讲本质一点一个是抵御局部节点变坏一个是防范局部节点失联。大众一定听讲过这样的描绘PAXOS是唯一能解决分布式一致性问题的解法。这句话越是理解越觉察得诡异这会让人以为PAXOS逃离于CAP约束了所以个人更愿意理解为PAXOS是唯一一种保障分布式系统最终一致性的共识算法所谓共识算法就是大众都按照这个算法来操作大众最后的结果一定一样。PAXOS并没有逃离CAP魔咒毕竟达成共识是(N/2)1的节点之间的事剩下的(N/2)-1的节点上的数据还是旧的这时候仍然是不一致的。所以PAXOS对一致性的奉献在于经过一次事务后这个集群里已经有局部节点保有了本次事务正确的结果共识的结果这个结果随后会被异步的同步
42、到其他节点上进而保证最终一致性。以下摘自维基百科Paxosisafamilyofprotocolsforsolvingconsensusinanetworkofunreliableprocessors(thatis,processorsthatmayfail).Quorumsexpressthesafety(orconsistency)propertiesofPaxosbyensuringatleastsomesurvivingprocessorretainsknowledgeoftheresults.另外PAXOS不要求对所有节点做实时同步本质上是考虑到了分区情况下的可用性通过减少完成一次事
43、务需要的介入者个数来保障系统的可用性。OceanBase的CAP分析上文提到过单元化架构中的成千山万的应用就像是计算器本身无CAP限制其CAP限制下沉到了其数据库层也就是蚂蚁自研的分布式数据库OceanBase本节简称OB。在OB体系中每个数据库实例都具备读写才能详细是读是写可以动态配置参考第二局部。实际情况下大局部时候对于某一类数据固定用户号段的数据任意时刻只有一个单元会负责写入某个节点其他节点要么是实时库间同步要么是异步数据同步。OB也采用了PAXOS共识协议。实时库间同步的节点包含自己个数至少需要(N/2)1个这样就可以解决分区容忍性问题。下面我们举个马教师改英文名的例子来讲明OB设计的
44、精妙之处假设数据库按照用户ID分库分表马教师的用户ID对应的数据段在0-9开场由单元A负责数据写入。假设马教师用户ID假设为000正在用支付宝App修改自己的英文名马教师一开场打错了打成了JasonMaA单元收到了这个恳求。这时候发生了分区比方A网络断开了我们将单元A对数据段0,9的写入权限转交给单元B更改映射马教师这次写对了为JackMa。而在网络断开前恳求已经进入了A写权限转交给单元B生效后A以及B同时对0,9数据段进展写入马教师的英文名。假设这时候都允许写入的话就会出现不一致A单元讲我看到马教师设置了JasonMaB单元讲我看到马教师设置了JackMa。然而这种情况不会发生的A提议讲我建
45、议把马教师的英文名设置为JasonMa时发现没人回应它。因为出现了分区其他节点对它来讲都是不可达的所以这个提议被自动丢弃A心里也明白是自己分区了会有主分区替自己完成写入任务的。同样的B提出了将马教师的英文名改成JackMa后大局部节点都响应了所以B成功将JackMa写入了马教师的账号记录。假设在写权限转交给单元B后A突然恢复了也没关系两笔写恳求同时要求获得(N/2)1个节点的事务锁通过no-wait设计在B获得了锁之后其他争抢该锁的事务都会因为失败而回滚。下面我们分析下OB的CAP分区容忍性OB节点之间是有相互通信的需要互相同步数据所以存在分区问题OB通过仅同步到局部节点来保证可用性。这一点就
46、讲明OB做了分区容错。可用性分区容忍性OB事务只需要同步到N/2)1个节点允许其余的一小半节点分区宕机、断网等只要(N/2)1个节点活着就是可用的。极端情况下比方5个节点分成3份2:2:1那就确实不可用了只是这种情况概率比拟低。一致性分区容忍性分区情况下意味着局部节点失联了一致性显然是不知足的。但通过共识算法可以保证当下只有一个值是合法的并且最终会通过节点间的同步到达最终一致性。所以OB仍然没有逃脱CAP魔咒产生分区的时候它变成AP最终一致性C。整体来讲它是AP的即高可用以及分区容忍。结语个人感觉本文涉及到的知识面确实不少每个点单独展开都可以讨论半天。回到我们紧扣的主旨来看双十一海量支付背后技
47、术上大快人心的设计到底是啥我想无非是以下几点基于用户分库分表的RZone设计。每个用户群独占一个单元给整个系统的容量带来了爆发式增长。RZone在网络分区或者灾备切换时OB的防脑裂设计PAXOS。我们知道RZone是单脑的读写都在一个单元对应的库而网络分区或灾备时热切换经过中可能会产生多个脑OB解决了脑裂情况下的共识问题PAXOS算法。基于CZone的本地读设计。这一点保证了很大一局部有着“写读时间差现象的公共数据能被高速本地访问。剩下的那一丢丢不能本地访问只能实时访问GZone的公共配置数据也兴不起什么风作不了什么浪。比方用户创立这种TPS不会高到哪里去。再比方对于实时库存数据可以通过“页面展示查询走应用层缓存“实际下单时再校验的方式减少其GZone调用量。而这就是蚂蚁LDC的CRG架构相信54.4万笔/秒还远没到LDC的上限这个数字可以做到更高。当然双11海量支付的成功不单单是这么一套设计所决定的还有预热削峰等运营技术的手段和成百上千的兄弟姐妹共同奋战特此在这向各位双11留守同学致敬。感谢大众的浏览文中可能存在缺乏或者遗漏之处欢送批评指正。同时欢送所有开发者扫描下方二维码填写?开发者与AI大调研?只需2分钟便可收获价值299元的AI开发者万人大会在线直
限制150内