当前位置: 首页 > 科技观察

严选交易数据源自主切换实践

时间:2023-03-17 14:36:53 科技观察

1.前言在严选早期的开发过程中,为了快速交付需求,大部分系统都采用单体架构,主站商城也不例外。随着业务的日益复杂,业务拆分也逐渐开始。各业务团队(商城、渠道、仓配等)在各自业务领域推进服务化转型,主站商城业务团队紧随其后。孵化交易中心、推广中心、用户中心等业务中心。但各业务中心共享DB资源的情况并没有得到改善,导致各业务中心的数据不断裸奔,业务系统的稳定性也大大降低。交易作为其中之一,经过20-21年的平台改造,通过业务抽象,使得交易中心的平台能力更加凝聚稳定,所以我们决定乘胜追击,独立拆解交易DB资源。本文主要介绍当前业务背景下存在的挑战以及如何应对。最后详细介绍了基础保障工作的实施和核心独立流程的组织衔接。2.业务背景严选业务发展初期,为支撑业务的快速发展,采用了中心化的架构和开发模式。上图展示了严选交易架构的演进路线。早期的事务不仅与商城内的业务耦合,而且DDB集群是商城业务之间共享的。截至21年,交易借助业务抽象、架构分层和标准化,逐渐向中台架构演进,但订单操作等核心业务仍保留在交易前端业务,导致成本高需求迭代和严重的代码损坏。同时,商城内各业务DDB资源利用率不一,存在产能过剩和瓶颈两极分化突出的情况,急需各业务进行边界治理。边界治理的核心难点之一是如何保证稳定性,因为它涉及能力迁移和内外依赖转换。如何保证变换范围的完整性、准确性和平滑性,与系统的稳定性密切相关。以交易能力迁移为例,核心交易能力积累20+,能力依赖接口1000+,涉及表30+。因此,基于交易核心能力高使用频率的前提,采用先完成交易能力恢复,再进行交易DB独立执行策略,于22月初完成全交易能力的迁移.基于这样的背景,进行了事务DB的独立迁移工作。3.挑战在共享交易DB和商城DB的背景下,需要实现交易DB独立于商城DB的核心目标,而目标的实现涉及到交易DB迁移的独立性,结合交易业务场景的特殊性,交易作为核心业务的强依赖方,DB的任何变化都可能触及在线用户的感知,所以这对我们保证对用户的影响是正确的提出了很大的挑战。极小,并避免独立迁移带来的一系列连带负面影响(如:资金损失、客户投诉等),主要表现在三个方面,用户在交易前不能进行交易行为,用户的交易行为是交易过程中阻塞中断,交易后交易数据不一致。可以简单概括为数据一致性和平滑迁移的保证:数据一致性保证数据不会丢失:无论是切换到目标数据库还是切换回源数据库,都保证不丢失数据;不产生脏数据:需要保证新旧数据库的同一个订单数据是一致的。平滑迁移确保数据源的平滑切换:在新旧数据库切换过程中,尽可能保证平滑切换;平滑的业务切换:需要保证在切换到新数据库的过程中,受影响的用户和业务场景的范围最小。3.1挑战:数据一致性保障在数据一致性保障方面,我们主要从两个方面入手,即数据迁移工具的选择和业务切换方案,确保使用数据迁移工具实现源库和目标库的一致性数据库。数据同步保证数据不丢失,业务切换方案的制定防止迁移过程中引入脏数据。3.1.1迁移工具3.1.1.1航研NDC数据同步一般分为离线和实时两种。业界常见的离线数据同步方案有3种:Sqoop、DataX、Kettle。实时数据同步主要有Canal、Otter、航研自己的GrindingNDC。但是我们的业务场景决定了需要采用实时同步方案,最终方案选择采用了NDC(网易数据运河)。是网易开发的一套集数据迁移、数据订阅、数据实时同步、数据校验为一体的数据传输服务。在支持0->1全量数据迁移的同时,也可以很好的支持1->1.1的增量同步,更重要的是可以更好的支持DDB(目前NDC同步功能源端可以支持MySQL,一共有三种DDB和Oracle,同步功能的目标端可以支持MySQL、DDB和Oracle,事务业务使用DDB作为存储依赖)。3.1.1.2架构介绍从架构上来说,NDC大致可以分为三部分:源系统、NDC集群和目标系统。NDC从源系统拉取全量或增量数据,转换过滤后写入目标系统。架构图如下:3.1.1.3注意事项NDC的播放过程大致可以理解为与source建立连接,拉取sourcebinlog,解析binlog,对target进行相应的dml操作,但应该是注意整个回放过程不是原子的。所以在镜像库切换的过程中,偶尔会出现数据不完整的情况。建议:用户需要结合业务场景对数据完整性和实时CasebyCase分析的需求。如果要求很高,可以先切换镜像库再切换主库。3.1.2业务切换业务平滑切换常见的方案有三种,即停写、不停写和双写。不同的方案各有优缺点,虽然双写在用户层面的感知是最少的,但改造成本和迁移周期也会相应增加。在考虑了严选商城C端现有业务流量特点(夜间流量相对较低)和成本等各种综合因素后,最终方案选择采用数据库写停止方案来实现。方案优缺点不停写成本低,简单迁移过程中影响业务正常运行不停写成本低,简单迁移过程中可能产生脏数据,双写手工修复,真正意义上的平滑切换,用户感知不到整体改造工作量大,时间跨度大,需要解决数据一致性问题。通过write-stop方案,可以保证同一时间只有一个事务数据源可以提供写入,避免了多个数据源写入造成的数据同步。数据覆盖,导致脏数据的产生。3.2挑战:平滑迁移保障平滑迁移保障主要从两个方面入手:数据源动态切换和账户精准控制:通过数据源的动态切换,保证切换过程中DB配置实时生效,无需重启即可实现切换到目标数据源作用:针对账户的精准管控,在源库进行账户重新分配、授权、回收等一系列措施,确保不会有遗漏在实际切换到目标数据库期间。3.2.1数据源动态切换3.2.1.1严选Pandora在数据源切换过程中需要明确支持数据源动态切换。业界也有很多成熟的动态切换数据源方案(dynamic-datasource-spring-boot-starter、Springboot-basedAbstractRoutingDataSource等),总的原理是通过配置多个数据源来达到动态切换的效果.最后我选择了严格自研的中间件Pandora。相比业界常见的方案,支持在不重启基础能力的情况下动态切换数据源,也支持动态下载数据源配置生效。SourcedataDiff(最好结合数据源切换)等功能特性。3.2.2账户精准管控在迁移过程中,需要保证切换到新的交易数据源后不会出现漏表等情况,避免二次切换,因为我们在中采用的解决方案切换过程是停写的,在生产环境中,这无疑会增加对在线用户的伤害感知(即使是在流量低峰期),所以需要保证切换时不会有遗漏尽可能处理。3.2.2.1高质量的业务监控如何保证无遗漏场景,即对事务DB存在的所有写操作都被完整收集,不存在遗漏的写操作。这是我们需要关注和解决的。Phase1:DB层监控最初寄希望于DDB本身,希望可以通过指定表的ip进行访问监控,可惜无法支持,考虑使用Binlog消费进行分析,但是整个的Binlog主站太大。Phase2:Proxylayermonitoring由于无法进行DB层监控,所以考虑代理层。APM维护了服务表之间的链接关系,可以显式支持一些表集合和服务之间是否存在访问关系,但是会随之而来的问题是这种关系无法详细区分读写,需要额外的成本支持.但是,通过这种方式,可以确定事务表与服务之间存在直接连接。Phase3:应用层监控既然服务范围已经划定,那么可以直接对具体的读写请求进行编码,进行DAO拦截分析识别,辅以监控告警,可以有效帮助识别是否有意外场景。解决方案总结:APM查表+AOP拦截3.2.2.2专用账户在迁移过程中需要保证切换到新的事务数据源后不会出现漏表等场景,避免二次切回,因为它们是switchingWriting在此过程中停止。在生产环境中,这无疑会增加在线用户的负面认知。因此,需要尽可能保证切换过程中不会出现遗漏。在实现策略上,主要通过隔离账户和权限来保证。确保专用账户:账户隔离复制现有账户yanxuan,同权限账户yanxuan_new权限隔离yanxuan账户excludetransactiontablecollectionforyanxuan_new只允许访问交易表集合3.2.2.3质量回归此外,可以使用现有的沉淀自动化回归测试帮助我们发现,在账号切换环节或权限恢复环节验证了现有流程的正确性,防止场景遗漏,但随之而来的问题是现有沉淀的自动化测试用例并没有100%覆盖。如果完全依赖人工代码检查,将面临检查周期长、耗能大、可能遗漏等问题。代码变更分析SDK:目前该SDK应用于集团各部门精准测试领域。由集团BU测试团队维护共建并开源。主要支持版本变更分析和指定方法分析:版本变更分析可以针对项目(包括依赖工程)对两个不同分支或版本之间的差异代码进行diff计算,得到变更的类和变更的方法。同时通过静态代码调用链路分析,计算出这些变化方法影响到的顶层Controller接口(或Service/Component/RPC方法)。指定方法分析可以分析项目(包括依赖项目)中指定类的指定方法,通过静态代码调用链接分析计算出这些变化的方法影响的顶层Controller接口(或Service/Component/RPC方法)。借助代码变更分析来分析SDK指定的方法,可以完美满足我们的需求。大致实现原理如下图所示:下图为天机平台(基于精准SDK平台产品)进行样本分析的DEMO。指定项目、指定类名、指定方法的方式帮助我们有效构建依赖链接:4本质保障工作4.1数据源的动态切换和转换涉及迁移的业务方需要显式访问Pandora进行动态交付数据库配置。除了Pandora接入外,由于只有我们应用中的交易切换到新的交易DB,部分业务必然会保留对主站DB的接入。因此整体改造的设计思路是实现数据源复制+数据源动态切换识别。具体实现思路可以参考下图:DataSourceA是系统默认的数据源(主站DB),DataSourceB是DataSourceA的副本。在切换主站DB之前,DataSourceA和DataSourceB都是用来访问主站DB的。通过Pandora切换到事务DB后,DataSourceA的连接从源数据库(主站DB)切换到目标数据库(事务DB),但是由于系统默认数据源为DataSourceA,访问非事务业务DB资源需要通过DataSourceB才能获取到,所以需要显式标识switch。4.2事务中切换数据源由于所有涉及迁移项目的项目都使用Spring+MyBatis来访问和操作数据源,基于事务DB独立性的必然性,必然会涉及到事务中切换数据源的问题。我们知道,如果启动一个Spring事务,首先会有一个SpringTransaction,然后Mybatis在创建SqlSession的时候,会创建一个SpringManagedTransaction,添加到SqlSession中。通过查看源码可以看出,SpringManagedTransaction中的Connection会从TheadLocal中获取(@Transaction会创建Connection放入ThreadLocal中,ThreadLocal是以DataSource生成的actualKey为key和ConnectionHolder封装的Map作为价值)。因此,如果要在事务中支持切换数据源,就必须重写SqlSessionTemplate,重写getSqlSession方法,根据要切换的key(对应具体的数据源)重构SqlSession。如果SqlSession中包含的数据源是启动事务的数据源,则取Spring已经创建的数据源,否则重新创建。4.3大数据平台切换根据数据集成平台Datahub现有的功能支持,如果主站库(源库)表直接切换到订单库(目标库)和订单已有的数据仓库表命名规则使用的数据库,迁移后的所有rdb表名都改了,工作量大,风险大。考虑到目标数据库(历史已经存在,但核心交易表相关数据仍然存在于主站数据库中)现有数据仓库表仅被一个下游任务依赖,单独配置订单数据库binlogKafka主题,rdb表名适配切换迁移主表的命名方式,基本可以实现迁移表相关的离线数仓任务无需感知影响,将下游影响降到最低。5独立流程编排独立流程是通过制定人工操作指令来实施的,如何在实施过程中高效地保证不出错和完全独立是需要关注的问题。所有参与者都需要理清整体的独立思路,敲定详细的独立步骤(约束行为),通过反复的独立演练帮助我们发现问题,不断优化和完善我们的独立流程。5.1独立思考整体迁移的思考是在事务表写权限已经恢复的背景下进行的(依赖于事务能力的全收集)。整体流程大致可以分为两个阶段:镜像库切换阶段和主库切换阶段。在镜像库切换过程中,可以先切换主库,有助于发现问题;因为引入了NDC,相比常规的镜像数据库复制过程,链路变大,延迟略有改善。主库切换主库切换完成后,需要断开源库和目标库之间的NDC同步任务,同时创建反向同步任务,防止切回造成数据丢失。5.2独立过程大致的迁移过程如图所示,主要包括迁移阶段、回滚阶段、关闭阶段。5.3验证演练由于事务DB切换涉及的服务较多(共13个核心服务),切换到生产环境前需要在测试环境进行反复演练,即forward(源库->目标库)和逆向(目标库->源库)流程全切换演练。交接演练有助于完善现有交接脚本,细化人员配置安排,明确业务影响观察指标。在测试环境迁移事务DB的过程中,依靠前期改进后的用例场景的全回归,不仅可以帮助发现迁移过程中是否存在遗漏,还可以进行二次检查遗漏和弥补原有交易能力,确保万无一失。.在切换过程中,可以利用NDC的数据比对和校验能力,帮助我们检测源端和目标端数据不一致的情况,保证数据同步功能的正确性。6总结了严选事务DB是如何实现数据源独立性的,以及数据源切换的整体流程的解决方案以及实现迁移过程中遇到的一些问题。作为经验分享给大家,希望对后续业务团队开展相关工作的开发有所帮助。