陆金所从年启动全站去O项目以来,在不做任何服务降级的情况下,历时2年通过上百次变更,把全站98%的Oracle数据库无缝切换到MySQL上。其中,这98%的数据库覆盖了陆金所的账务、资金、资产中心、支付、交易、用户、基金、主账户、网贷、资管、银行理财等全金融场景。整个去O的全程0故障、0风险、对用户几乎不感知。
陆金所去Oracle实践有四大特点:
一是在线更换数据库,不做服务降级。让去O这类重大架构改造实施落地的时候对全站用户影响最小,同时也最考验去O的架构改造的技术实现能力。
二是对于高频上线了上百次的去O变更,全程0故障、0风险,这一点非常考验陆金所去O的变更工具水平。
三是在短短24个月的时间完成全站98%的数据库去O改造,并且涉及陆金所全部最核心的业务,去O的整体落地效率非常快。
四是在去O各个环节实现了从开发、测试到运维各种自研智能工具来把控去O各个核心环节的质量,这也是把一个庞大、复杂、高风险的金融核心系统,在非常短的时间内0风险、0故障,稳妥落地去O的关键。
陆金所为什么要全站去Oracle?
陆金所为什么需要启动去全站去O,并且是%全部去O。
在去O项目立项之初,我们希望通过去O来实现三个方面的提升。
首先是降低昂贵的金融系统数据库运营成本。年至年期间,陆金所的业务成长了上百倍。业务量增长带来的数据库运营成本暴增。无论是传统的IOE架构还是去IE后的X86+Oracle分布式架构都是如此。IOE架构下,高端服务器和高端存储的价格随着提供的计算和IO能力呈现指数型增长。X86+Oracle架构下,分布式改造和数据库细粒度水平拆分后虽然没有I和E的成本,但数据库节点暴增后导致Oracle软件授权费用暴增。
其次是希望通过去O来打造一个不依赖特定数据库特性的金融交易系统,彻底摆脱被商业数据库厂商技术绑架的风险。传统金融交易系统使用数据库特性承担了大量的业务逻辑和架构属性,造成系统对某个数据库特性的强依赖,也大大增加了被技术绑架的风险。陆金所通过全站去O实现了把金融交易系统里数据库的角色转化为只支持基本增、删、改、查的存储引擎,全站系统架构弱依赖数据库特性。
最后一点也是最重要的一点,我们希望通过全站去O这样一个涉及到开发、测试、架构、DBA等全部研发团队都参与的重大架构改造项目,来锻炼研发队伍、提升研发能力,并把历史上一些架构设计不完善的地方,通过全站去O进行重构。因为去O不仅仅是更换数据库,更重要的是落地架构拆分、微服务化、分布式事务等配套的大量架构改造工作。这些工作需要开发、架构、测试、运维高度协同配合,并稳妥落地。所以去O是非常考验研发团队技术水平的架构改造项目。通过,我们也希望通过去O打造“研发规范——研发工具——研发人员”的研发管理体系闭环。这一块我们在后面会详细展开,并向大家进行介绍。
技术选型:为什么是MySQL,又不仅是MySQL
决定去Oracle之后,选择什么数据库或存储引擎来承载Oracle的流量?我们从功能、资源、案例和压测四个方面来进行选型和评估。
首先,选择的数据库要从功能和性能上能够承接Oracle在各种场景下计算和IO能力。其次,它还要具备最广泛的社区资源、技术资料和问题处理案例,通俗的说就是大量坑被踩过,以及最广泛的用户基础,外面招开发和运维工程师都比较好招。然后,还要在业界有可参考的金融场景案例。这一点相信大家都很熟悉,阿里和腾讯在金融场景上已经有不少成功的案例。
最后,同时也是最重要的一个评估标准就是陆金所自身上线前严格的压测环节。陆金所在切换任何一张表流量的时候,都会使用生产环境完全真实的数据搭建O和M并行压测环境,来获取访问这张表的所有读写接口的在Oracle11.2和MySQL5.7下的性能比对报告。经过每一轮非常严格的压测后,发现MySQL5.7的性能比我们预估中的更好。通过从边缘系统往核心系统的逐步去O演进中,MySQL5.7就成为陆金所去O最主要的替代存储引擎。
我们都知道Oracle是个非常优秀、且覆盖场景非常全面,无论是OLTP还是OLAP场景表现都很优秀,所以这种功能承接应该远远不止一种数据库或存储引擎,涉及到多种存储引擎发挥他们的优势在各种特定场景下来替换Oracle。
所以最终的结论是综合选型下来确定使用MySQL为主,TiDB、Redis、ES、HBase等多种存储引擎为辅的方式,%全部替换掉Oracle。
陆金所去Oracle方案
接下来,我们就详细介绍陆金所的去Oracle方案。
去O双写和切换方案
陆金所去Oracle改造主要是分为应用和数据库两个部分来落地的。
首先介绍一下应用层部分的落地。应用层在去O的时候会做一个整体规划,把一个大的系统或库拆分成多个可独立落地的批次,然后会把应用的业务逻辑层从数据库的访问接口尽可能剥离出来,让DAL层专注只做好数据库交互的操作。同时,在OracleDAL层的基础上,对MySQLDAL层的进行重构,并且配置流量开关让上层的业务逻辑层可以自由选择和数据库的交互是走OracleDAL层还是MySQLDAL层。每个批次都会有自己单独的流量开关进行控制。批次拆分的时候遵循一个原则就是把具备业务相关性和事务相关性的表放在一个批次里。
再说数据库层的落地,在Oracle还在不断对外提供服务的时候,我们会在后台建立起一个和Oracle保持实时数据同步的MySQL数据库,即当Oracle的事务提交后,秒级同步到后端的MySQL里面。同时这个同步是双向的,当未来流量切换到MySQL后,也会在MySQL事务提交完成后,把数据秒级同步回Oracle,这就类似MySQL的双master架构,只不过数据是在Oracle和MySQL这个异构数据库之间建立双master架构。
在这个架构中为了确保数据库的一致性和完整性,一定是严格要求某个批次的写流量只能在某个时间点只能在O和M一个地方写入。陆金所研发了一整套自动化构建数据库双写的工具平台,只要在平台上选择需要建立批次的Oracle表,就能在后台全自动完成OracletoMySQL从表结构转化、数据全量同步、数据增量同步、数据实时同步、数据校验和数据双向同步建立整个全流程繁琐。依据这套自动化平台,陆金所只投入2个DBA就完成了全站上万张表的去O数据库迁移和运维层的全部准备工作。
最后是流量切换,我们设计并研发了一套总控开关机制来协调从应用、到数据库、到传输、最后到流向的全盘流量切换。实现当流量在O时,实时同步到M。当流量在M时,实时同步到O。保证切换一瞬间,最后一笔事务在源库提交成功,在目标库传输成功,并完成最后一笔事务的数据在源库和目标库的数据校验后,同一个批次下所有表的写流量在同一个时间点同时完成切换。
应用流量在O和M之间快速切换
虽然去O流量切换会在10秒内瞬间完成,但整个过程按照细粒度划分会有十多个步骤。为了方便介绍,我们把这十几个步骤精简成了三个状态。
首先是初始状态,这个状态下生产的只读流量可以在Oracle或MySQL,写流量可以在Oracle,由Oracle对外提供服务。这个状态状态可以理解为Oracle为主库,MySQL为Oracle的异构实时备库。
其次是中间状态,这个状态下Oracle和MySQL会进入一个非常短暂的写保护静止状态。在完成最后一笔Oracle事务提供成功,并同步至MySQL,且完成最后一笔数据一致性校验后,会把应用开关的流量切换到MySQL,这个时候这个批次的写流量在某个时间点全部一致性都切换到MySQL。
一旦在MySQL里写流量进来,就进入了第三个状态即完成状态,一旦写流量的事务在MySQL中提交成功,双向实时同步链路会把MySQL的数据秒级同步回Oracle,这个时候可以理解为MySQL是主库,Oracle是MySQL的实时备库。
需要注意的是,这个架构下需要解决大量的细节问题,比如避免同一笔记录双向循环写的问题。
陆金所实现的这个双写框架流量切换速度极快,在数秒内就能实现有状态的写流量从O到M的快速切换,整个过程在低峰期落地对业务影响非常小,甚至是不感知。如果在去O之前在Oracle内部已经完成了对用户的水平拆分,以批次和用户双重细粒度进行去O流量切换,那么整个更换数据库过程几乎是无感的。
在流量从O切换到M后,以陆金所落地的经验来看,大概有一定概率(比如程序的bug)需要回切到回Oracle。这套切换框架可以确保在几秒内流量快速回到Oracle,且在MySQL写入的少量数据也会同步会Oracle,且在保证Oracle和MySQL两边的数据严格一致性和完整性的过程中,进行流量的快速前滚和回滚。
适用于金融核心系统的稳妥去O推进方案
了解了去O流量切换的架构和方案,接下来我们介绍如何在一个关联系统庞大、业务逻辑复杂、改造风险极高的金融核心系统里落地整个去O方案。
首先我们会以表为粒度来把一个复杂、庞大的金融核心系统和数据库拆分成多个批次,拆分的原则上面也提到了一点,即把有业务相关性和事务相关性的表放在同一个批次里,在确保这个基本原则的情况下,把单个大库尽可能的拆分成多个批次,确保每个批次里的表尽可能的少。
为什么要基于这个原则来落地实施呢,因为批次是去O变更的单位,O和M之间的流量切换开关是控制到批次的。把批次拆分的足够细,最终目标是为了实现“改造难度可控、上线进度可控、切换风险可控”的3原则。
首先对于金融核心系统中一个复杂的模块来说,去O改造的周期会横跨半年甚至一年以上,在这个过程中,金融核心系统在7*24小时不间断对外提供服务,应用层的代码和功能每个月甚至是每周也处在高速迭代中,不断的新功能被加入到系统并被发布到生产。
而在这个过程中,要落地去O这类庞大的架构改造,必须框定一个可快速迭代和实施的改造范围,批次就是一个合理设定的单次去O改造和变更的范围。批次拆分的粒度细,可以确保在单个批次的去O改造工作量可控、改造难度也可控。
同时因为批次的粒度细,在做去O变更切换流量时,对整个金融核心系统的影响也可控。基于这种思路,就可以实现“小步快跑”的高速迭代方式来改造应用、上线版本以及切换流量。即每次只改动核心系统的一小部分,改动完成后快速测试、快速发版上线、并且风险可控的把这部分流量切换到MySQL运行,如果有问题依靠强大的流量切换框架,快速把流量回切回Oracle。
从图中大家可以看到一个庞大的金融核心系统去O改造中,应用改造、上线版本和流量切换这3件事情实在并行落地的。
最开始是应用改造,改造完了上线发版,发版后就有了这个批次O和M的流量开关,并具备了切换条件,之后在某个变更日把流量从O切换到M,如果遇到任何问题可以快速切回来。应用版本在不断上线迭代,流量在分批次不断切换,一个庞大的金融核心系统就在多次高速迭代中一点点的从O切换到了M。
整个过程对核心业务不影响、不感知,且对参与去O的开发、测试和运维开展去O工作非常友好,让他们可控的去落地各项工作。
在这个过程中,从第1张表从Oracle切换到MySQL,到最后一张表关闭Oracle流量,在非常长的一段时间内,整个应用是由Oracle和MySQL在同时提供服务。其中某些表已经完成去O,读写的流量在MySQL上,由MySQL同步到Oracle,部分表还未完成去O,读写流量在Oracle上,由Oracle同步至MySQL。这就非常考验运维的能力,要确保在这个架构下每天高频的各种发版和数据库变更都非常准确。
基于此,陆金所是有研发一整套配套去O变更工具,来确保整个去O过程中大量变更准确实施和落地。以陆金所交易、主账户、资产中心、基金、账务等核心库为例,从第一张表流量切换到MySQL到最后一张表切换到MySQL,历时12个月以上。按照上述方案一点一点的替换掉Oracle数据库,整个过程完全不做服务降级,对陆金所的多万用户无感知。
陆金所去Oracle方案的落地
在PPT中画出去Oracle的架构图是很简单的事情,但是架构改造的难点和重点在于落地。要在生产环境落地是非常庞大且复杂的系统工程,尤其是对一个7*24小时的金融核心系统来说,进行重大架构改造本身就是一件高风险的工作,既要做到规避风险,确保各种工程实现细节有效落地,同时又要保证系统的业务连续性,甚至是对外部用户不感知。
去Oracle架构改造的本质是什么?我觉得有两方面,一是细节规则,二是上生产前发现和上生产后兜底。
去O的重点不仅仅是方案本身,更重要的是组成方案的数百条细节规则,能在一个参与去O的、庞大的研发团队里每个开发所写的每一行代码都有效遵守规则,同时在每个运维设计的生产变更方案里每一条命令都有效遵守规则。方案通过从边缘系统往核心系统逐步推进过程中,会逐步趋于完善,方案中的规则也会被逐步积累和完善起来,那么把这些规则落地到研发团队的每个人上,是关键和重点。
上生产前发现是指如果规则在某个微小的细节实施时没有被遵守,如何尽可能的在上生产环境之间发现隐患。上生产后兜底如果问题突破了所有检测环节上了生产,如何设计一个兜底方案可以有效控制风险,把影响尽可能降低。
去Oracle落地工作都应该围绕有效解决这两个本质问题展开,并提升这两个问题的解决效率,降低人力成本。
陆金所的做法是建立“人员——规则——工具”的闭环。
陆金所通过“人员制定规则——规则通过工具落地——工具确保所有人员的代码和变更符合规则”的方式来确保各种细节工作落实到位,整套工具最终沉淀为陆金所数据库升级平台。
以陆金所的去O落地经验来看,一个不起眼的细节问题如果未进行有效管控,都有可能引发严重的生产故障。所以我们可以把陆金所数据库升级平台理解成为一套强大的去O风控系统。这套风控系统覆盖SQL重构、表结构转化、数据迁移、数据校验、分布式事务构建、流量切换等横跨从开发到运维在去O架构改造方方面面会遇到的问题。通过这套工具平台,有效确保参与去O的研发团队在每个细节上都处理的非常规范,从而实现历时24个月的全站去O,无风险平稳落地。
除了确保各种规则精准落地外,金融核心系统去O改造需要多个研发团队协同作战、有效配合、共同推进。其中涉及到大量工程实现细节工作需要多团队有条不紊、事无巨细的协同配合好。任何疏漏都有可能会引发严重的生产故障。
经验总结:谈谈企业去Oracle的目标
去Oracle的口号喊了很久了,但是为什么要去Oracle,去Oracle想要达到什么样的目标…有些企业可能没有想得很清楚,所以我也想从自己的角度和经历来谈谈去Oracle的目标。
目标一:省钱
去O完成后,使用“免费的开源数据库+X86架构的PCServer”来搭建金融核心系统,真的很省钱。因为搭建金融核心系统从昂贵的高端服务器、高端存储和Oracle一体机,以及昂贵的Oracle软件授权变成只需要6万一台的X86服务器,花在数据库上的运营成本降为之前的10%不到。
在整个去Oracle的过程中,陆金所架构从一个传统金融的超大型数据库支持各种核心业务的架构变成了以微服务化驱动的分布式架构,这种架构具备以下特点:
每个服务有自己独立的应用和数据库。每个库只提供给服务内的应用直接访问,即服务内的应用可以通过SQL访问。服务之外的应用访问数据库需要走应用层的服务接口,避免跨服务访问数据库。服务分为同步调用和异步消息。在服务内实现数据库的水平扩展。对于类似用户、交易、资金等公共类基础服务,逐步迭代为中台服务。通过微服务化拆分,几套集中式的IOE大库就变成了微服务小库,同时对于访问量和数据量较大的中台服务,又会进一步细粒度水平拆分。
目标二:架构升级和改造
除了降低成本,我认为更重要的是通过去O实现传统金融系统全方位的架构升级和改造。
对于一个传统金融系统来说,借助去O来实施和落地全系统的架构改造和升级,应该是一个再好不过的机会。以陆金所为例,通过去O实现了以下的升级和改造:
数据库底层计算和IO能力的水平扩展,并且这种水平扩展完全基于6万一台的X86服务器,扩容成本极低。同时实现了应用访问数据库的规范化,应用和应用之间的服务化。全站的调用链会非常清晰,应用和数据库之间不合理的依赖将大幅降低。另外实现数据库层去中心化,单个数据库的可用率对全局可用率影响有限,消除中心化的单点隐患最后借助去O实现的分布式架构,可以把各个分片的数据库部署在不同的机房,从而实现真正意义上的机房多活。目标三:引入更合适的存储引擎
提到去Oracle,可能很多人在第一时间就想到了MySQL。其实,MySQL是承接Oracle主要流量的数据库,但MySQL无法承接Oracle的全部流量,例如以下几类经典场景:
Oracle在oltp场景当中少量hashjoin查询场景。Oracle中多表关联和多层复杂嵌套查询场景。MySQL细粒度拆分后,跨库、跨分片的查询场景。在MySQL集群和Hadoop集群之间构建一个秒级数据同步的ODS层。在这些场景中,可以引入TiDB、Elasticsearch、Impala+kudu、Redis等多种存储引擎。这些存储引擎在合适的场景下替换Oracle,产生的效果是不但比IOE架构成本低得多,性能也会比Oracle快得多。
我们以TiDB为例来讲讲使用MySQL之外的存储引擎是如何支撑Oracle流量的。
陆金所有个实时对账的场景,需要跨用户库、交易库、资金库和资产库进行复杂的关联查询。在完成去O后,数据库在MySQL上做了细粒度拆分,无法跨多个独立的服务库进行复杂且高频的跨库查询。
为了支持这个场景,我们研发了数据总线来实施解析MySQLbinlog并生成消息同步至TiDB,事务在MySQL提交后实现秒级同步至TiDB。之后通过TiDB4.0的TiFlash功能(类似clickhouse的列式存储),在MySQL和Hadoop之间搭建一个实时ODS,实现了秒级处理跨库、多表、复杂关联的查询场景。性能远超去O之前在IOE架构下的处理结果。