背景介绍
易贝()于2018年全面启动下一代支付系统的设计与实现,支付宝的双十一、微信财付通的春节红包,都向世界展示了当前支付行业的工程成果。 那么作为下一代支付系统,如何才能做得更好呢? 支付宝支付系统在双十一期间可支持数十万笔并发交易。 我们的支付系统是否有可能支持更高、更稳定的交易? 俗话说,先擒贼先擒王。 支付系统最重要的组成部分之一是会计系统,其对业务准确性和稳定性要求极其严格。 我们以此为突破口,启动了一项艰巨的工程。
2018年底接到项目后,我们的支付团队对支付行业进行了深入的研究,首先确定了下一代记账系统的设计目标:
商业目标
支持所有支付业务功能
扩展接口支持所有互金功能
灾难恢复目标:
三地五中心部署,数据中心级容灾
数据毫秒级实时异地同步备份,服务秒级异地主备切换
绩效目标:
自动线性膨胀
能够处理全球所有支付公司峰值流量的总和
数据目标:
实时数据中心
具备区块链所具备的一定的数据防篡改能力
接下来,我们进行了为期半年的系统设计和原型实现。 2024年一季度原型系统通过验收,下一代核心核算系统项目正式启动。 经过半年的紧张开发,该系统于今年第三季度正式灰度上线,并通过了性能和容灾验收。
本文主要介绍核心计费系统的性能和容灾能力,包括以下内容:
核心会计系统简介
百万TPS压测实验
系统架构分析
开源项目
核心会计系统介绍 业务介绍
支付系统为账户之间的资金流动提供系统的解决方案。 支付系统在处理转账业务时,需要根据活期账户资金及流向情况,对资金流向的金额、流向、业务合理性等进行必要的业务验证。 核心会计系统负责维护所有这些核心转账操作以及所有账户的资金和流量。 支付系统几乎所有的支付能力都是基于核心记账系统,因此核心记账系统是最重要的系统之一。
介绍
账户资金是账户当前的状态,每次资金流转都会查询和修改这些状态。 当用户和业务数量超过一定规模时,单机无法满足系统的性价比要求。 因此,互联网行业普遍采用集群多机解决方案。 但多机方案会遇到很多单机方案没有的挑战:
如何将状态划分到多台机器上
多机之间连接出现问题时如何正确维护状态
单数据中心故障时如何保证业务的正确性和稳定性
跨城数据备份如何处理网络延迟问题
如何快速扩容和缩容系统
如何保证分布在多个节点上的数据不被恶意篡改
核心记账系统还面临着许多其他挑战,随着系统流量的增加,这些挑战将变得更加严峻。 当系统发生量变时,我们需要寻求质变。 接下来,我们就来看看下一代核心会计系统如何应对量变和质变的挑战。
百万TPS压测实验实验目标
下一代核心会计系统的首要设计目标是更好地支持电子商务业务。 电商企业通常面临闪购等短期超大规模用户需求。 这时,系统需要具备瞬时线性扩展能力,以保证用户体验。 为此,我们设计了百万TPS压力测试来验证下一代核心记账系统的相关能力。
实验意义
支付宝的双十一、微信的春节红包等项目对于10万TPS的问题已经有成熟的解决方案。 但针对百万级及以上TPS的问题,业界尚无具有代表性的系统案例。 100万TPS是指支付宝、微信财付通、国际卡组织、国际第三方支付等全球所有支付系统在线峰值流量之和。 由于支付业务与人类活动相关,存在物理上限,解决百万TPS问题就意味着一劳永逸地解决记账系统的基础设施问题。
此外,系统性能的一个数量级的提升往往意味着架构的迭代更新。 我们借此机会针对老问题提出新的解决方案。 我们希望这些新的想法能够应用到更多的其他系统中,解决其他行业的更多问题。
实验过程
实验分为两部分:第一部分验证单组节点性能,业务场景为单个商户闪购业务,系统验证点为单组节点所能支持的最高TPS; 第二部分验证多节点集群的性能,业务场景是主站有大促销,系统验证点是TPS请求逐渐增加时系统的自动扩展能力。
系统准备
正式生产环境中,核心核算系统部署在三地五中心。 本次压测采用简化版的两地三中心部署。 每组3个节点,部署在全市2个数据中心。 共准备了667组、2001个业务节点进行压测。 外围辅助节点2350个。 总共准备了4351个节点。 这些节点的总带宽为个CPU核,总内存为45T,总硬盘存储空间为84T。 所有硬件消耗3个机柜,共300台物理机,总成本450万美元/3年。
实验结果单组节点测试
公用事业、电煤气缴费、用户还款、电商闪购等业务都需要大量用户在指定时间点将资金转入单一账户。 由于单个账户无法再进行分库分表处理,因此单组节点的性能上限决定了单个账户的交易量上限。 因此,我们需要实现单组节点压力测试来了解单个账户的局限性。
两地三中心结果
本实验中,三个数据节点部署在两个远程数据中心,通过基于Raft共识算法的强一致性协议进行实时数据同步。 这是最常见的部署方案,同时考虑到灾难恢复和业务处理响应时间。 从上图的测试结果来看,1KB请求每秒可处理的最大交易量为7800笔。
值得一提的是,当达到峰值时,P99(第99个百分点)下的单个传输请求的延迟显着增加,因为请求接收阶段的处理能力已达到上限。 在批量日志写入阶段,一次打包的日志数量大幅增加,部分抵消了海量请求的影响。 P90下延迟的增加相对较小。
整个测试过程中发生了Raft 选举,导致TPS下降。 这是因为新所有者需要先更新其业务状态,然后才能处理新的转让请求。 与基于 Raft 协议(例如)的传统应用程序相比,这是支付应用程序的独特之处。
同城三个中心结果
本次实验为同机房三节点部署。 从上图可以看出,系统每秒最多可以处理 9,500 笔交易。 由于在数据复制过程中,只要有一个从节点(Raft)成功写入日志,就认为事务完成,而同一数据中心的主从之间数据复制的延迟仅为1/12跨数据中心的 1/8。 ,因此每秒的交易数量相应增加。 这个效果与部署在三个异地中心时主从在同一个数据中心时的效果一致。 另外值得指出的是,由于数据中心内的网络比跨数据中心的网络更加稳定,因此整个实验过程中没有进行选举,TPS更加稳定。
单中心结果
本实验采用单节点部署来测试数据复制对事务吞吐量的影响。 与前两次相比,在本次部署中,只要主节点(也是唯一的Raft节点)本地写入成功,就认为事务完成,节省了数据复制的时间。 从上图可以看出,在此部署下,每秒交易数可以稳定在9700笔,最大可处理交易数近笔。 可以看出,同一机房单节点部署和三节点部署的系统吞吐能力相差无几。 这部分归功于我们在提高网络吞吐量方面的优化。
多组节点测试
在实际应用中,单组节点往往无法满足大型电商平台总交易量的实时要求。 因此需要部署多组节点,每组节点只负责账户的一部分交易请求。 我们在两个典型业务场景下测试了系统的性能。
流量阶梯上升,节点数量动态调整。
本次实验模拟的业务场景是主站每日流量有涨有跌,交易量会随着某些外部事件而动态变化。 例如,在全站促销期间,网站流量会随着人们的作息而慢慢波动。
从上图可以看出,实验开始时只有222组节点。 当系统监测到单组节点的平均吞吐量开始上升并超过阈值(意味着交易量增加,即将达到并超过单组节点的处理能力)时,系统将自动部署新节点来共享整体交易量。 随着节点数量的增加,平均吞吐量开始慢慢下降到阈值以下,同时保证整体交易量能够得到及时处理。 弹性膨胀过程如下图所示:
系统可以动态调整节点数量以适应流量的变化,保证业务不受影响的同时也提高了硬件利用率。 例如,当交易量较低时,可以通过合并节点来减少资源。
瞬时超高流量,节点数量不变
该实验模拟了主网站上的重大促销活动。 比如每年双11午夜,流量洪水会在极短的时间内涌向支付系统。 我们测试了系统在瞬间接收50万笔和100万笔交易的极端情况下的性能。
50万
从图中可以看出,在这两种情况下,系统都能从容、稳定地响应。 虽然部分节点更换了所有者,但对整体流量的影响微乎其微。 测试过程中甚至发现延迟短暂下降,这主要是由于批处理阶段打包效率的提升。
当流量达到峰值时,我们还随机检查了部分节点的资源使用情况,发现CPU未满,部分线程未满负荷运行。 这说明流水线各阶段的处理能力各不相同,经过后续调优后系统应该表现得更好。
系统架构分析 总体架构设计 核心设计原则
在解决超大流量时,电商系统和支付系统最流行的解决方案是通过分库分表对流量进行分段,通过分布式事务解决分库分表带来的分布式一致性问题。 这是一个久经考验的解决方案。 然而,近十年来,通过开源社区和各大互联网厂商的不断努力,数据系统的设计取得了长足的进步,出现了更多更好的解决方案。 由于我们是从头开始设计一个新系统,没有历史负担,所以我们决定采用更先进的系统设计来解决核心会计系统面临的业务和系统复杂性问题。
业务复杂度处理
金融系统是典型的业务复杂系统。 我们测算,信用卡业务共有573,099,840种不同的业务场景。 传统的解决方案是直接基于数据库表来开发所有系统。 传统解决方案的问题在于数据库以二进制格式存储数据,没有业务逻辑。 系统使用数据库时,需要基于二进制形式重构业务逻辑,正确性难以保证。
幸运的是,随着本世纪初领域驱动设计(- )模型的出现,金融系统的复杂性得到了系统的解决。 我们首先使用领域模型对金融业务进行建模,将业务表示层和数据存储层分离。 其次,用于保证业务处理的正确性和历史状态100%的追溯和恢复。 此外,还利用CQRS实现系统读写分离。 最后,使用流处理来统一从上到下、从外到内的所有设计。
多机交易问题
系统在进行水平扩展时需要处理数据正确性问题。 传统方法一般采用分布式事务。 基于记账系统特殊的业务逻辑,我们提出了基于消息最终一致性和业务补偿的解决方案。
除了正确性之外,多机解决方案还有一些其他问题需要注意。 首先,至少多了一项网络开销,这会增加请求延迟。 其次,系统内部流量翻倍,单机提供的服务TPS减半。 最后,由于基于消息最终一致性的实现无法同步返回结果给调用者,因此系统需要添加异步转同步组件。
单机交易问题
多机交易要求每台机器都具备本地交易能力。 为了提高事务执行性能,传统数据库一般采用多线程并发执行机制。 但本世纪初的一些研究发现,对于某些业务场景,尤其是金融行业,多线程并不是最优方案。 因此,在核心记账系统的设计过程中,我们保证核心记账业务逻辑只在单线程中执行,以充分利用单线程执行带来的事务保障和性能优势。
单线程带来的另一个好处是线性一致性()。 事务只能保证多个任务按照一定的顺序串行执行()。 当存在多个可选订单时,交易调度算法不保证每次都能选择相同的确定订单。 与事务一致性不同,线性一致性确保每个调度的顺序完全一致。 记账系统要求所有记账按照一定的顺序记录,并且在系统回滚和重放后需要恢复到相同的顺序。 因此,线性一致性是会计系统正确性的一个非常重要的保证。
系统性能
电子商务和支付系统通常采用基于SOA的节点间服务调用和基于Java Bean的节点内组件调用。 但当出现闪购等场景时,需要做一些特殊的削峰填谷工作。 削峰填谷通常都会使用消息队列来进行缓冲,因此消息队列也成为了必不可少的组件。
与经典设计中使用的部分异步实现不同,我们在设计中完全使用了基于消息的异步解决方案,包括系统之间和系统内部的函数调用。 异步方案带来的挑战是没有同步接口,增加了调用方的复杂度。 因此,需要使用上面提到的异步转同步组件来降低调用者的复杂度。
系统容灾
金融系统对灾难恢复的要求极高。 首先,数据需要支持本地和异地备份,保证数据具有区域容灾能力。 此外,还需要支持业务的快速自动主备切换。 时间就是金钱。
传统的解决方案是基于数据库自带的异地备份,分为异步和同步两种备份方式:
如果是异步备份,由于数据没有及时同步到备份节点,当主节点出现故障时,数据就会丢失。
如果是同步备份,主备机必须同时在线。 任何一台机器出现问题都会导致业务中断。 备份机越多,任何一台出现问题导致业务中断的概率就越大。 所以,同步备份的问题是,数据容灾能力越强,系统就越不稳定。
我们采用了新的方法来同时提高数据灾难恢复和系统稳定性。 新方法要求备份机像同步备份一样同步返回备份结果,但只要求返回大部分,而不是全部。 这种方法称为共识算法族()。 我们选择了Raft算法,并从头开始实现了我们自己的高效、定制的强一致性算法。
记账系统的核心数据将通过强一致性算法实时同步到3个数据中心的5个存储节点。 只要超过一半的节点工作正常,系统就可以正常运行,因此部署方案允许5个节点中任意2个同时出现问题。 由于单个数据中心的问题最多只能影响2个节点,因此该部署方案可以支持数据中心级别的灾难恢复需求。 这种部署俗称三地五中心部署。 三地五中心的简化版就是两地三中心,这也是我们本次压测采用的模型,如下图所示:
我们采用两层(核心业务层和基础设施层)一体化设计,实现业务主备快速自动切换。 当数据进行容灾切换时,定制的Raft算法会将数据和业务逻辑同时切换到容灾节点。
为了更好地证明系统的容灾能力,我们在生产环境中部署了定时自动容灾演练系统。 系统会时不时地对系统进行随机可用性攻击,以验证系统对生产环境中网络、硬盘、内存等异常情况的容忍能力。
分层设计
核心记账系统从上到下分为4层:
会计业务层
基础核算层
基础设施层
存储层
还有一个垂直贯穿的监控层,负责采集监控数据和跨层监控。 架构图:
顶层会计业务层提供外部访问接口,负责处理顶层业务逻辑。 它有一定的外部 I/O 请求,并且内部是无状态的。 业务将被分解为多个条件转移请求,发送到底层基础记账层。 基础计费层负责计费,没有外部I/O请求,有内部状态。 该状态由基础设施层提供的状态机来维护。 基础设施层负责提供基于Raft算法的高效稳定的状态机实现。 其性能由单线程保证,稳定性由强一致性算法保证。 基础记账层处理的结果就是记账账本,并输出到存储层。 完整的分层架构图如下所示:
原则
基础记账层和基础设施层按照 的原则进行设计,这也是核心记账系统最重要的架构设计。 有 4 个主要组成部分:
:外部请求
:事件
:状态
:状态机
所有外部请求首先发送到状态机。 状态机结合当前状态生成事件。 事件存储到事件仓库()后,会被状态机执行,从而改变状态机中的状态。 如下所示:
下图是多事件处理的时序图:
举一个会计系统的例子。 会计系统收到的指令是“从A转账100美元到B,但A不能余额不足”。 目前的状态是“A有150美元,B有50美元”。 状态机收到命令后,检查当前状态,确认转账后A的余额不会不足,于是产生“A转出100美元,B转入100美元”事件。
请注意,状态机可能会为同一命令生成不同的事件,这完全取决于当前状态。 还是用前面的例子,如果此时A的余额只有50美元,那么转账100美元的命令就不会成功执行。 此时状态机会产生传输失败事件。
一旦事件产生并存储在事件仓库中,该事件就会被状态机执行,从而改变状态机内的状态。 以本例为例,A的起始状态为150美元,转账100美元后结束状态为剩余50美元。
命令和事件按顺序记录和处理。 这个过程是一个经典的数据库回滚日志(WAL,Log)案例,也是记账系统的本地数据存储格式。 由于单机故障可能导致日志丢失,因此我们使用Raft强一致性算法来增强数据容灾能力。 日志首先会以临时状态存储,只有当日志安全备份到一半以上的机器上后,才会更改为已提交状态,允许外部访问和处理。
数据存储格式为数据库回滚日志。 当系统出现故障时,将执行标准的数据库回滚和恢复流程。 如下所示:
连续QRS
CQRS(),俗称读写分离,也是一个已经被提出的概念。 命令和事件会改变状态机的状态,这是一个写入过程。 事件一旦生成,就无法修改。 同时,事件之间存在着严格的顺序关系。 用户可以通过顺序监听事件来重建状态备份,甚至添加自己的特殊逻辑来生成自定义视图。 这是一个读取的过程。
例如,核心记账系统中的所有事件都是记账消息。 我们通过监控消息生成余额状态,并将其保存到关系数据库和其他数据流系统中进行实时聚合。
流处理
我们将 CQRS 更进一步。 由于命令和事件都是通过消息系统来传输的,而CQRS设计模式中的写入和读取操作也是通过消息系统来传输的,所以自然的整体解决方案就是采用流处理架构来设计整个账户。 服务系统中的消息传递和处理。
每个处理节点,例如处理事件的节点或生成视图的节点,都可以视为流处理的计算节点。 流处理顶层节点采用强一致性算法,保证数据和状态的高可用性和一致性。 但这些已经通过强一致性同步的数据在向下游流动的过程中仍然可能会丢失。 但由于最上游的数据有线性一致性保证,下游可以通过检测线性一致性来判断是否发生数据丢失,然后通过查询上游来进行数据补偿。 这意味着下游数据不一定需要强一致性算法。 例如,我们可以选择一致性稍弱的消息系统作为下游消息管道。 如下所示:
系统实施
前面的章节提到了系统的分层。 业务层主要处理记账业务逻辑,是无状态节点,易于水平扩展,采用Java实现。 核心业务层和基础设施层负责业务状态的处理和维护。 它们是有状态的节点,需要稳定性、强一致性和性能,并且用C++实现。 其余辅助组件由go实现。
我们选择了C++17标准,利用了新标准下的一些新特性,并在实现过程中大量运用了函数式编程思想。 采用函数式编程思想的主要目的是保证核心逻辑的可组合性和行为可复现性,同时也保证多线程情况下核心数据结构的正确性。
优化
优化主要集中在C++部分,主要优化两点:1.吞吐量; 2. 延迟。 我们创新性地采用了两层(核心业务层和基础设施层)一体化设计,结合管道和批处理,提高系统吞吐量并降低延迟,同时避免了常见的网络造成的双层分离。 各种状态不一致。 为了保证设计实现的正确性,我们采用了测试框架,专门设计了测试用例,保证系统在出现各种异常情况时能够正常工作。
提高系统吞吐量的常用方法是流水线。 将外部请求的处理分为几个阶段。 每个阶段独立运行。 队列用于连接各个阶段。 前一级的输出是下一级的输入,形成管道。 这种设计的优点是可以针对每个阶段的特性进行独立优化。 例如,在数据接收阶段,采用多线程来增加单位时间接收的请求数量; 在数据同步阶段,采用批处理的方式,减少网络开销; 在核心处理阶段,每个请求都必须顺序执行,以确保状态正确,因此我们使用了一些仅在对冲基金高频交易系统中使用的特殊优化来提高处理速度。
系统延迟主要发生在网络请求上。 观察到的跨数据中心请求的延迟约为几毫秒,发生网络抖动时的延迟约为数十毫秒。 正常的网络请求对用户体验没有太大影响。
但它会带来两个问题:
通过一些特殊的数据结构优化和运行顺序调整,我们成功优化了绝大多数网络请求。 最终的结果是:对于同一批需要处理的事件,系统只需要进行一次网络同步。 我们还证明,在多线程强共识算法的情况下,当多节点群集更改其主机时,每个状态机可以运行或滚动回正确的状态。 优化的2个事件,1步连续网络同步过程如下图所示:
部署
该系统由基于K8S的云平台部署,并支持一键式云部署。 同时,由于系统抽象并封装了所有IO,因此可以通过分布式配置服务动态切换存储媒体。 部署系统时,您可以完全基于本地独立文件系统选择远程部署或部署,该文件通常称为独立版本。 独立版本包括完整的业务,数据,存储,监视和其他系统,这极大地促进了系统开发和启动。
开源项目
我们将逐渐打开系统功能和代码三个步骤:
大学和其他科学研究机构的开源代码
向商业合作伙伴开放功能和源代码
大家开源
目前,我们已经与英国和美国的几所大学进行了深入的科学研究合作,并以核心会计系统为研究对象对分布式系统进行了尖端研究。 我们与业务合作伙伴的合作也正在进行中。 我们将在明年年底之前开放所有代码和文档,因此请继续关注。
写在最后
核心会计系统在设计和实施过程中遇到了许多挑战,并获得了很多帮助。 感谢的管理层的信任和战略支持。 感谢中国研发中心的管理层的跨部门合作。 感谢的全球云计算团队和SRE团队的强大支持,他们在实验过程中赞助了所有云资源,并帮助实施了许多优化工作。 感谢筏作者对系统体系结构的建议和评论。 这只是 Pay的一小步,我们仍然有更广阔的空间可以探索。
关于作者
Ren Jie拥有 的学士学位和硕士学位。 2007年加入了摩根士丹利( ),后来曾担任衍生品风险引擎的全球负责人,负责所有利率,外汇和信贷衍生品业务。 2017年,他加入了支付宝的核心支付团队,并参与了相关业务,例如支付宝和在线银行业务。 2018年加入了eBay支付团队,并负责核心会计系统。
原文链接
超越“双重十一” - eBay的百万TPS付款会计系统的设计和实施