一、银行新一代核心系统建设背景及架构
在银行的 IT 建设历程中,尤其是中大行,大多都基于大型机和小型机来构建核心系统。随着银行业务的快速发展,这样的系统对业务的支持越来越举步维艰,主要体现在以下四个方面:
首先是难以支持银行快速发展的业务。随着国内电商、互联网支付、手机支付的迅猛发展,银行的交易量出现指数级的增长。比如我们的某银行客户,当前每秒的交易量峰值在一万多左右,预计在未来几年会逐渐增长到每秒 6 万笔交易,而且后续还会继续增长。在这种情况下,基于大型机的集中式架构,单纯靠硬件的升配,已经无法支持业务的持续增长。
第二是难以匹配银行系统的迭代更新速度。原有的基于大型机的胖核心架构,迭代周期往往在数月甚至半年。但随着银行间、以及银行与互联网金融企业之间的竞争加剧,银行迫切需要快速推出新业务进行创新,他们也希望能够像互联网公司那样,能够按周级进行快速迭代,快速响应业务需求。
第三是系统风险。银行业迫切需要做到软件及硬件的自主可控。
第四是生态封闭。大型机技术发展慢、人才难招。现在再去外面招一个懂 IBM 大型机的人已经很难了。
因此,在国家现有政策的引导下,各大银行最近几年都在做一个事情:把原有的核心架构从大型机下移到传统的通用服务器架构上,并建设一套自主可控的新技术体系,简称核心系统下移。
在进一步理解银行系统之前,我们先了解下银行客户的业务体量、业务需求以及核心系统对业务支持情况。以一个国有大行来举例:它的客户量在 5-7 亿,有 10-20 亿账户,在全国有 2-4 万个网点。从每秒峰值交易量来看,约为每秒 5-8 万笔交易。
具体到数据库层,支持以上业务还需要联机交易系统,例如存贷汇业务。数据库层最大的表有百亿级记录数,TPS 达到百万级。此外,统一查询业务要求支持近十年交易明细的查询,即万亿级的查询记录数。即使放到互联网公司用的通用服务器,也是需要上千台服务器才能支撑相关业务的开展。
通过以上的介绍,大家可以发现,银行客户的业务体量和数据量已经达到了大型互联网公司的量级。如果想把这个系统从大型机下移到通用服务器架构,那么原有的集中式架构肯定是无法满足的,必须像互联网公司一样采用分布式架构。
因为银行有和大型互联网公司相近的业务体量,因此在技术体系上,也借鉴了互联网公司的技术体系。
从 IaaS 层来看,银行采用了 X86、ARM 架构的通用服务器,也用到了混合云技术,大量使用了虚拟机与容器服务。
在 PaaS 层,银行使用了大量的分布式系统,如开源的微服务框架(例如 SpringCloud ),以及开源的或者商业的数据库,包括分布式/单机/关系型/缓存型的数据库,以及日志数据库 ES、时序数据库等。在中间件层,也用到了大量的开源的或者基于开源改造后的组件,例如消息队列、对象存储、分布式锁等。
在 SaaS 层,银行主要通过单元化 + 微服务的架构来实现分布式扩展。银行将自身业务应用划分成三种单元。
最上层是全局单元,主要是起到全局路由及流量分发的作用。
第二层是业务单元,核心的业务逻辑都在该部分来实现。同时,为了实现业务的横向扩展并支持数亿客户量,银行业跟互联网公司一样,对业务进行单元化拆分。例如我们接触到的某银行,就是将自身的业务拆分为了 16 个业务单元,每个单元五千万客户, 16 个单元部署在两个机房形成同城双活的架构。
最底层是公共单元,一些不太好或没必要做单元化拆分的应用,放在公共单元提供公共服务。
通过上述分析可以看到,在新一代银行核心系统里面,整体的架构体系已经和互联网公司很接近了,大家用的都是相同的技术栈,只是服务的业务场景不同。在未来,银行业跟互联网业的技术交流会进一步紧密,人才的流动也会进一步频繁。
在业务采用了单元化划分后,数据库的架构是怎么样的呢?目前在银行的新核心系统下移中,主要采用了以下两种数据库架构:
第一种是单机数据库架构。这种数据库架构比较简单,故障域较小,但相对来说业务系统会比较复杂。因为有些模块,如全局路由模块,是全局的总入口,没法做单元化拆分。因此一组单机数据库无法满足性能与容量需求,依然需要在业务层做数据拆分。除此之外,单机数据库无法完全支持业务单元层的业务落地。前面提到,我们接触到的某银行一个业务单元要承担五千万的客户数,一组单机数据库依然无法支持。于是在业务层进一步拆分为 4 组数据库共 64 张子表,业务层需要去解决大量的拆分及分布式事务相关的业务逻辑,整体就更复杂了。
另外一种是分布式数据库架构。这样的数据库内部架构虽然更为复杂,但它可以提供更好的性能。对业务层来说,一个单元采用一组数据分布数据库即可,业务层的逻辑就更为简单了。
因此我们认为,随着分布式数据库的逐步成熟与应用逐渐广泛,业务单元化 + 分布式数据库会逐渐成为流行的银行业务架构。
综上,银行核心系统在下移的场景下,对数据库在如下几个方面提出了要求:
第一是分布式扩展性。由于采用了通用服务器,它的单机性能要远弱于大型机或者小型机。在这种情况下,数据库需要具备分布式可扩展的能力来满足上亿客户的金融需求。
第二是强一致性。金融场景对数据正确性、一致性的要求极高。因此要严格保障对事务的 ACID 特性。否则,业务层就要做大量的工作。
第三是容灾能力。通用服务器在硬件故障率方面要比大型机、小型机高很多。因此需要我们的数据库有更为可靠的可用机制以保障 SLA。同时,监管对于容灾能力的要求也在不断提升。比如,对于新建设的核心系统,监管要求必须满足 5 级以上的容灾能力,且满足同城双活并保证 RPO 为 0。在具体执行上,监管的要求也越来越严格,比如同城双活,之前是只需要具备相关的技术方案即可,但现在每年人行的监管都会直接到现场,要求做机房级实战故障切换。
第四是运维能力。系统下移到通用服务器并实现去 IOE,数据库节点数量要出现 50 倍的增长。以我们的一个银行客户举例,从小型机下移后,数据库节点数从 20 增长到 1000(当然这里面也预留了几倍的性能增量)。在和客户的交流过程中,他们也认同这个观点,认为系统下移后,节点数要增长一到两个数量级。但运维的人力不可能因此增加几十倍,在这种情况下,就要求我们的运维效率要有质的提升,需要能够智能化、自动化去做相关的运维工作。
二、分布式数据库 GaiaDB-X 的金融场景方案
接下来我们分享第二部分,分布式数据库 GaiaDB-X 针对金融场景的解决方案。
GaiaDB-X 数据库是百度智能云研发的 Shared Nothing 架构的分布式数据库,它可以基于通用服务器做横向扩展,来满足高性能、大数据容量的需求。
总体来看它分为计算层、存储层、元数据三层架构:
计算层是无状态、可横向扩展的一层。它对外兼容 MySQL 协议,接收到 SQL 请求后,再经过 SQL 解析、权限检查、逻辑优化、物理优化之后,生成 DistSQL 下发到各个存储层的分片。为了达到更好的性能,逻辑与物理上尽量将数据过滤及计算能力下推到存储层,收到结果后,再把数据进行聚合计算,最后返回给客户端。
计算层的下面是存储层。它采用多分片的方式进行扩展,数据按照一定的分片规则打散到了各个分片中。我们支持 Hash、Range、List 等分区方式来做数据分区。同时,分片内数据采用多副本的方式来保证可靠性,
第三是 GMS 节点,即全局元数据管理模块。它用来管理全局性数据,例如表的 Schema 信息、权限信息、表的路由信息,还有后面要介绍到的用于做分布式事务的全局逻辑序列号。GMS 也采用多副本的方式,采用 Raft 协议进行数据同步。
在最底层是我们的统一数据库管控平台,来实现对数据库集群的管理。比如在百度集团内部数十万的数据库节点,都是由该管控平台来管理的。
GaiaDB-X 数据库是百度集团发展历史最久、应用最广泛的一款数据库,到现在为止已有 18 年的发展历史。它的发展也与百度的业务发展息息相关,大概可以归纳为四个阶段:
第一阶段是从 2005 年开始,为了满足搜索、社区业务中大量读请求的场景,我们通过一主多从的集群化外加读写分离来扩展读性能。
第二阶段是为了支持凤巢广告系统与百度网盘,满足它们对万亿级数据量的需求,我们开始做分布式系统。到了 2014 年,我们就已经在凤巢广告系统中替换了基于 Oracle 的盘柜,为凤巢每年节省了上千万的成本。针对百度网盘,我们有个 3000 台服务器的集群支持网盘业务,所有网盘文件的元数据信息都存储在这里,最大的表达到万亿级记录数,至今仍是国内最大的关系型数据库集群之一。
第三阶段是随着百度钱包等泛互联网业务的兴起,对数据的一致性要求更高了。因此,我们实现了分布式事务强一致的特性,保障金融数据的正确性。
第四阶段,也就是现在。随着百度智能云对外技术输出,我们已经把数据库输出到了十余个行业,覆盖 150 家客户。在金融行业,GaiaDB-X 已经承接了金融核心业务,包括百信银行、银联商务、某交易所及国有行等。
对于分布式数据库,水平扩展能力是其核心能力。除了在计算层与存储层做水平扩展外,我们还要着力去解决影响我们扩展能力的单点。
第一个是 GMS,即全局元数据模块。因为它要提供一个全局递增的全局逻辑时钟,每一次事务都需要调用它。为了避免其成为瓶颈,我们采用批量预分配的方式来提升其总吞吐,在此模式下,其每秒可分配 1200 万个 TSO 序号,远超出百万级 TPS 的需求。
第二个是全局事务表。为了保证分布式事务的原子性,我们需要将正在进行中的事务保存到一张全局表中,因此它的性能也会直接影响到全局性能。我们采用自管理的方式,将全局事务表做成分布式表,分布式地存储在集群中,这样就可以实现分布式扩展。
在实际应用中,比如说像 19 年的春晚抢红包,我们支持了三亿用户抢红包,支撑了峰值达每秒 12 万交易量。除此之外,针对某银行拥有 8000 万账户的核心账务系统,我们也平稳支持了其 6 万每秒的 TPS ,充分验证了 GaiaDB-X 的水平扩展能力。
除分布式外,我们也支持单机场景,实现了单机分布式一体化。为什么需要单机分布式一体化呢?以我们的一个银行客户来说,全行的业务系统有 200 多个,其中大部分系统(大概占 70% 左右)对性能与吞吐的要求并不高,一组单机数据库就能够满足其业务需求。但对于剩下的 30% 业务,它对性能的要求是单机数据库无法满足的,需要分布式数据库来满足其扩展性。
因此我们通过一体化的方式,来满足银行不同体量的业务对于数据库的需求。同时,我们也具备单机数据库扩展为分布式的能力,在对应业务的数据量增长后,能够扩容为分布式。
扩展性的另外一个目的是自动做数据分离。在金融场景里面,存在多个业务共用一个数据库集群的场景,比如业务分为联机交易系统与查询类系统,数据库便对应划分为交易库和历史库两个。
对于交易库来说,只保存联机交易会频繁使用到的数据。例如账务结果数据及当天的交易记录,以满足对交易业务的快速响应。对于查询不那么频繁的即时交易记录,这可能就是一个相当大的数据量,一般都能达到千亿甚至万亿级别。这时,我们就可以将这个数据自动转移到历史库上去,用更高密度的存储机型来存储。一方面可以降低硬件成本,同时也可以避免对联机业务的影响。
这样做对业务来说,对外呈现的是一套数据库,业务可以根据需要来处理不同数据分区的逻辑,也不用在多套库之间通过 DTS 做数据同步。同时还把交易数据和历史数据做分离,以保障对联机业务的性能,同时也满足了查询业务的查询需求,避免其相互影响。
在金融场景中,对事物的 ACID 特性有着严格的要求:
持久性。指的是事务一旦提交就不会丢失,一般通过多副本 + 强同步来解决。
原子性。一个事务要么全部提交,要么全部回滚,不存在部分提交的情况。通常,数据库的 XA 协议,通过两阶段提交能解决这个问题。
但是 XA 协议不能很好地满足一致性与隔离性。以简单的转账场景为例,A、B 原来各有 100 块钱,总共 200 块。然后 A 给 B 转账 50 块钱。此时,我们会先给 A 扣 50,再给 B 加 50。如果通过 XA 协议来做的话,先走 prepare 再 commit,我们可以看到,commit(图中第 7、第 8 步)过程不是原子过程,存在一个执行时间差。在这个时间差内,另外一个事务去读取数据,就可能存在读到提交了一半的数据,A 和 B 的总和是 150 而不是 200。这是 XA + 2PC 解决不了的问题。
为了解决这个问题,业内一般是引入一个全局时钟来做一致性的保证。通常有三种实现方式:
TrueTime 方案。这个是大家比较熟悉的方案,Google Spanner 也发过论文。但它的缺陷是依赖硬件,要引入 GPS 与原子钟,这个一般来说是难具备的。
HLC 方案。采用该方案的典型数据库系统是 CockroachDB,它的优点是不依赖硬件,而且是去中心化的。但是缺点也很明显,一致性比较弱,而且要求服务器间的时钟误差不能超过 250ms,否则就无法正常运行。
TSO 方案,比如 TiDB 就是采用了这种方案。TSO 本质上来说是一个全局唯一而且自增的逻辑序列号,一个事务在开始时与事务 commit 时需要两次找 GMS 获取序列号,然后把 TSO 号作为版本号提交到存储层,存储层的 MVCC 机制来判断数据是否可见。它不需要硬件具备强一致性,但缺点是依赖一个全局中心的时钟分配器 GMS。但这并不是一个问题,因为刚刚我们也提到了,虽然 GMS 不具备扩展性,1200 万的 TPS 已经完全满足业务的常规需要了。因此我们最终采用了这种方案。
除了保障事务的一致性外,我们还需要保障上下游系统的数据一致性。在开始之前,我们首先要讲一下银行的典型业务场景,它一般分为三个子系统:
第一个是联机交易系统,例如存取款、在线支付等。这个系统的并发量高、延迟敏感,直接影响到用户体验。
第二个是跑批类的业务系统。例如结息,每天晚上半夜计算前一天的利息。这些业务是后台业务,有大量的读取与计算操作,延迟不敏感,但是对数据一致性要求高。怎么能够让这样的业务尽量避免对在线业务的影响,同时又能够读取到最新的数据呢?我们的方式是让跑批业务去读取从库数据,从而避免对主库的性能影响,同时结合 TSO,即全局逻辑时钟的对位对齐机制。等到从库水位追齐之后,才返回读取数据。当然这会引入一定的延时,但是因为跑批业务对响应延时不那么敏感,所以是可以接受的。
第三个子系统是大数据类的离线业务。通常来说,就是银行内部的各种大数据、数仓等系统,需要把数据库的数据同步过去。这样的业务对实时性要求不高,但要求最终的数据是一致的。由于各个计算节点都会承担流量,也会生成 BinLog。因此,如何对多份 BinLog 进行排序,让它们能够严格保持时序是我们需要解决的问题。我们的全局 BinLog 有两个模块,一个是 pump,从各个 CN 节点抽取 BinLog,然后在 Sorter 节点基于 TSO(全局逻辑时钟)进行排序,来保障形成一个全局时序正确的 BinLog,以保障这个离线系统收到的数据的最终正确性。
接下来我们看一下容灾能力,除了对单机故障的容灾之外,还有对特定机型的容灾。因为银行把系统下移到通用服务器,通常都是通过两阶段来实施:第一阶段是下移到 X86 的 CPU 芯片上,这个过程银行、互联网厂商都一定的经验。第二阶段是要实现服务器芯片的基本国产化,就是说使用国产的鲲鹏、飞腾或海光 CPU 芯片,这方面大家都是在探索性的开展相关业务。
以百信银行举例,它与其母行中信银行一样,选择了基于鲲鹏做国产化的路线,而且在业内比较超前。相较于其他银行仅在周边系统或者数据库从库来做国产化,百信银行的周边业务跟核心系统都和主站一样基于鲲鹏服务器来做,这个在业内是较为领先的。
为了保证客户业务系统实现平滑的国产化,我们在产品上实现了一库多芯的方案,主要资源池基于鲲鹏,但放置了一个独立 X86 资源池,在技术上实现托底,同时也能够将原有换下来的服务器能够利用上,避免资源浪费。
根据人行的监管要求,银行核心系统一般要具备 5 级以上的容灾能力,这就要求具备两地三中心的容灾能力。
下图是我们客户的一个典型机房部署架构。首先在北京有两个同城机房,其物理距离在 50-100 公里左右,网路延迟在 1ms 左右。同时还有一个异地机房做灾备,物理距离一般是 1000 公里左右,比如合肥,网络延时是 10ms。
同城两个机房业务做双活部署,同时接受业务流量。数据库在两个机房采用 3 + 2 的部署形式,机房间采用强同步的方式来保障在发生机房级的故障之后,数据库能进行故障切换,而且保障数据的 RPO 为 0。
为保证单机房故障后的零数据丢失,我们采用分组强同步的方式,将 id1、id2 各划分一个复制组,复制组间采用强同步的方式。每个复制组保证至少有一个副本接收到数据之后才返回成功。这样在容忍少数副本故障的同时也能够保证单个机房故障后的零数据丢失。
异地机房的目标是当北京的两个机房都出现灾难性的事件之后,能够降级完成核心业务。它采用异步级联的方式来同步数据,首先异步是为了避免阻塞对主地域的数据库写入;采用级联方式,没有跟主地域机房形成复制组,主要一个为了保持灾备机房的数据库的拓扑独立性,减少依赖,保障在关键时刻可切换,另外也是降低跨地域同步的数据量,只需要同步一份数据即可。
结合在多家金融客户的实践,我们和中国信通院一起发布了金融数据库的容灾技术报告《金融级数据库容灾备份技术报告(2021 年)》。大家可以在公众号后台回复「金融级数据库容灾备份技术报告」获取。
最后一部分是运维能力。核心系统下移及国产化的背景之下,数据库系统呈现两个变化:
一是数据库的节点数出现了 50 倍的增长,这里面既有技术架构的原因,也有数据库预留了一定的性能空间的原因。
二是数据库的种类也变多了。对于银行系统来说,之前基本就是选择 Oracle 或 DB2。现在则开始使用多种开源数据库和国产数据库。除此之外,为了避免像之前一样被单一厂商绑定,银行也会特意选择多家数据库厂商,在这种情况下,对银行的运维的挑战就更大了。
因此,结合百度集团及百度智能云管理大规模数据库节点方面的经验,我们将 GaiaDB-X 数据库云管平台进一步泛化,形成了具备管理多元数据库能力的统一平台,它除了能够管理 GaiaDB-X 自身,也能管理其他的开源数据库。通过帮助银行建立企业级的 DBPaaS 管理平台,进一步提升了银行的运维效率。
三、金融应用案例介绍
接下来,我来分享百度智能云在金融方面的一些典型案例。
首先是百信银行。它的特点是完全去 O,是一家完全没有 Oracle 的银行。全行 200+ 业务系统,无论是核心账务系统还是周边系统,几乎全部是基于 GaiaDB-X 数据库来构建的,至今已经平稳运行五年。
按数据库节点数计算,百信银行目前的数据库国产化率达到了 99.93%,遥遥领先于行业平均水平。
同时,百信银行在容灾和国产化领域也比较领先,在 2019 年就完成了全行主要系统的同城双活建设,2022 年开始将全行业务逐步迁移到基于鲲鹏的国产云上,进而实现了全栈的国产化。
在硬件成本方面,我们通过采用通用服务器来替代 IOE 硬件,帮助百信银行的单账户平均硬件成本降低了 70% 以上。
下图是人行下面直属的某交易所。因为是涉及到国家金融稳定,所以在核心系统上需要逐步摆脱对 Oracle 的依赖,并拥有两地三中心的容灾能力。
由于当前的一些数据库都不能满足他们的业务场景需求,因此该交易所和百度采用了联合开发的模式,共建数据库能力。在两年的合作过程中,我们从外围的信息管理系统入手,逐步深入到核心交易系统,再到离线库数据分析系统,进而逐步实现数据库国产化。
此外,由于交易所的交易系统对低延时的要求较高,同时基于容灾要求又有同城双活的要求,如何在跨机房的情况下保障交易延时就成了亟待解决的问题。因此我们共同建设了 Collocate 机制,来尽量减少跨机房数据的访问,最终将交易延时从 80 毫秒降低到了 15 毫秒。
下图是国内某国有大行客户。他们在最近两年把原有的基于小型机的核心系统下移到了通用服务器中,数据库也从 Oracle 替代为了开源单机数据库。
但在这个过程中,该行面临两个问题:一是数据库节点数增长了 50 倍,服务器数量到达了 1000 台左右,如何做好数据库的自动化部署、上线变更、版本升级、参数管理、性能诊断等工作。二是如何结合业务的单元化,形成业务与数据库的同城双活与异地容灾能力。
借助百度智能云提供的统一数据库管控平台的能力,历时两年,我们与客户一起实现了新核心系统的全面投产,也顺利通过了人行的验收。
评论