文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 :
免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备
免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,完成职业升级, 薪酬猛涨!加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷1)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷2)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷3)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取
美团太狠:100亿级分库分表,不停机迁移,如何处理?
说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如腾讯、美团、阿里、拼多多、极兔、有赞、希音的面试资格,遇到一几个很重要的面试题:
-
数据库如何不停机迁移?
-
100亿级库表,如何不停机迁移?
-
等等等等.....
其实,答案不是一成不变的。
参考答案其实千千万万,在这里,尼恩一直结合行业案例,梳理一个最为全面、最为系统化的答案,
这里有一个新的行业案例《菜鸟积分系统稳定性建设 - 分库分表&百亿级数据迁移》,尼恩从 面试维度,对这个方案,进行二次重构和梳理,现在把其作为参考答案,收入咱们的《尼恩Java面试宝典 PDF》 V82版本
供后面的小伙伴参考,大家一定好好看看这个生产级别的答案。
本文原文:《菜鸟积分系统稳定性建设 - 分库分表&百亿级数据迁移》 原始方案的作者是 星花 ,原文来自于 公号,阿里开发者。
下面的内容,是尼恩是结合自己的3高架构笔记,以及尼恩的3高架构知识体系(3高架构宇宙),在原文的基础上,做的二次架构分析和创作。
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF文件,请到公号【技术自由圈】取
本文目录
目录- 美团太狠:100亿级分库分表,不停机迁移,如何处理?
分库分表&数据迁移的技术重要性
分库分表&数据迁移,不仅仅是一个技术难题,考验的一个人的技术功底。
分库分表&数据迁移,也是一个协调难题,需要协调开发、运维,而是一个人就能搞定的。考验的一个人的协调功底。
所以,分库分表&数据迁移是大厂面试、架构面试的核心问题。
积分系统的巨大价值
伟大的系统,都是迭代出来的。
在早期,为了快速试错,菜鸟积分系统单体系统,数据库是单库多表。
随着业务快速增长,菜鸟C端用户已经过3亿+,消费者从查、取、寄快件开始慢慢扩展到玩、购。
玩、购主要是裹酱商城以及各个业务线多种多样的活动,这些活动包含了停留、任务、开奖、分享、签到、助力、兑换、抽奖等多种多样的互动手段。
菜鸟的积分代表用户虚拟权益,在其中起到了钩子的作用。
菜鸟的积分为互动产品本身提供了某些“价值”,使得消费者在平台停留时间增加。
从这个维度来说,菜鸟积分系统一直扮演着一个底层核心角色,承载用户核心资产。
积分系统的功能架构如下
总体的 功能架构,如上图所示。
积分系统面临的巨大挑战
在大促期间需要支持大流量的活动,整个积分系统在大促期间面临挑战是非常大的。
菜鸟C端用户已经过3亿+,单体应用不可能支撑,存储层的单库多表也是不可能支撑的。
为了支持菜鸟C端营销业务的持续爆炸式增长,菜鸟积分系统需要升级。
问题是:如何在业务不暂停的情况下,完成积分从单库单表到分库分表的数据架构升级?
还有就是:这一高风险操作是如何逐步分阶段完成的?
在开始设计迁移方案之前,菜鸟积分团队认真进行了问题分析,发现了本项目面临以下几个主要的挑战:
- 从1到N在系统架构上差异较大:原来的是单库单表的系统,之前的设计开发都是基于单库单表的,例如SQL查询,在单表上建了多个索引来支持这些查询业务,切换到分库分表之后,不带分表键的查询就不能支持了。
- 业务不可暂停:整个迁移过程,营销业务不允许暂停,类似于开着飞机换引擎,比一些银行系统的暂停服务来做迁移的难度大。
- 数据量大:单表数据量超级大,对数据同步链路的稳定性提出了很大的挑战。
- 系统架构旧:积分系统建立时间很早,所选用的技术框架老旧,有些甚至已经不再维护了,导致整个改造成本加大,改动过程风险很大。
- 接口版本多:由于历史原因,积分的发放和消耗接口版本非常多,有些历史包袱在里面,使得迁移的难度和风险都很大。
- 可监控、可灰度、可回滚:阿里稳定性三板斧:可监控、可灰度、可回滚。如果要求可灰度、可回滚,则必须要求数据的双向同步,加大了数据同步链路的风险。
- 1.可灰度:任何变更,都必须是可以灰度的,即控制变更的生效范围.先做小范围变更,验证通过之后才扩大范围
- 2.可监控:在灰度的过程中,必须能做到可监控,能了解到变更之后对系统的应用
- 3.可回滚:当通过监控发现变更后会引发问题时,还需要有方法可以回滚
- 时间紧迫:需要在特定时间前完成拆库和数据源迁移(近1个多月的时间),封网期间加大了操作流程的复杂性。
重构风险极大,但不得不做
由于涉及到数据的重构,项目风险极大,没处理好可能就要背包走人了。
为啥呢?
- 第一:数据一旦错乱或者丢失,有可能会造成部分数据不可恢复。
- 第二:或者即使能恢复,恢复时间通常也很长,按小时,甚至按天计算。业务很难承受这个代价。
然而,既然风险这么大,那能不干这个分库分表迁移项目吗?
不能!为啥呢:
- 因为菜鸟积分系统在2020年双十一期压测期间,已经成为瓶颈了。
- 已经到了不得不迁移重构的地步,而且这个重构越晚做,风险越大。
正所谓:箭在弦上,不得不发。
100亿级库表重构和迁移的方案设计
存量数据分析
表的情况:积分系统主要2张核心的表,积分总表和积分明细表。
数据的情况:2个库中的数据达百亿,积分明细的增量数据规模大,日新增数据也在千万级。
服务接口分析
积分系统对外提供的服务接口主要有:
- 读积分
- 加积分
- 扣减(冻结积分)
- 退还积分。
为了临时解决大促期间系统性能瓶颈问题,读积分会通过缓存tair(类似redis)做查询,击穿缓存才会到达数据库,写积分会直接更新数据库(缓存是)。
数据库的压力,在写不在读。
通过观察,大促期间,数据库瓶颈是在写积分对数据库的压力上。
如果把数据库纵向扩展,升级最高配置,也不能彻底解决问题:
- 一方面预算上花费太高,
- 另一方面也不一定能支撑预估流量,即使这次侥幸度过,将来也无法再做水平扩展。
解决100亿级库表性能瓶颈的可选方案
40岁老架构师提升:作为架构师,一定要提供多个候选方案,可选方案。
解决100亿级库表性能瓶颈的可选方案,主要有三个方案:
- 分库分表,数据迁移:考虑数据库性能,决定将积分系统由单库多表升级为分库分表
- 对数据库操作进行优化,减少加积分数据库操作
- 对业务优先级进行排序,部分场景降级,不写积分明细
方案二、方案三指标不治本, 只是延迟了问题,并没有解决问题。延迟的结果是, 越拖成本越高。
通过综合考虑, 选择方案一进行优化,彻底解决 解决100亿级库表性能瓶颈。
分库分表+数据迁移方案设计
分库分表方案设计
(1) 分库分表的分片键设计:
由于是积分总表和明细表,所以从用户维度进行分表
(2) 分库分表的规模设计:
分库分表是分8个库,1024张表
具体的分库分表的方法论,请参见尼恩秒杀视频。或者参考尼恩的推送中台视频。
(3)主键ID 的方案设计
在迁移数据的过程中特别要注意的是主键ID,主键ID需要程序生产的分布式主键.
也就是说,需要在程序中,手动的去指定主键。
而不能使用DB自增主键,防止ID生成顺序错误
具体的主键ID 的方案设计,请参见尼恩秒杀视频。或者参考尼恩的推送中台视频。
数据迁移方案设计
分库分表肯定要涉及数据迁移,数据迁移必定涉及一个全量和增量的数据,
数据迁移的关键是:如何保证数据不会重复,不会丢失,而且保证唯一性
数据迁移方案包括:全量迁移,增量迁移。
使用阿里数据迁移工具 精卫,这个工具既可以进行 全量迁移,也可以进行增量迁移。
精卫工具 会在全量任务的时候相当于记录数据库的一个副本,然后增量的时候可以进行任务回溯,
如何进行数据唯一性保证?该迁移工具可以保证数据的唯一性,对于已经存在的记录可以进行更新操作。
尼恩提示:
如果不是阿里,可以使用开源的数据同步工具。
比如阿里开源的DTS,就是是一件非常不错的工具。
DTS工具可以实现不同数据源之间的数据迁移、数据同步,只需要配置好两端的数据源就可以自动实现,不在需要人为的操作,非常的方便。
当然,如果熟悉kettle的,也可以使用kettle进行数据同步。
总之,有很多类似的中间件,或者自己编写迁移脚本
动态读写切换改造
由于是动态迁移,不停服迁移,肯定不能通过发布程序来切换数据源,
所以,在程序层面进行改造,进行动态读写切换改造。
大致的思路:在程序里面手动去指定双数据源,预先在程序里面应该加载两个db的数据源,通过配置预先设定开关,然后动态进行读写切换。
为了实现可监控、可灰度、可回滚,还需要进行灰度。
从配置的维度来说,不仅仅是 切换的开关需要配置化,而且 需要保证灰度过程中切换比例,可以通过配置进行调控
不停服、100亿级数据迁移执行流程
数据迁移执行流程,大概有10个步骤:
- 环境准备:线上库配置完成
- 全量同步:数据迁移工具上新建2张表(积分表、明细表)的全量任务
- 增量同步:全量迁移完成后开启增量(自动回溯全量开始时间,消息多次消费会进行幂等)
- 数据校验:全量数据校验,查看数据是否一致
- 切流测试:改造代码预发测试(采集线上流量进行回放,多种case跑一下,切流开关等校验),没问题发布上线
- 二次校验:再次全量进行校验&订正(数据追平)
- 开启双写:打开双写(保证数据实时性)
- 开启读灰度:低流量节点(凌晨过后)进行灰度切流
userId%x
,进行验证,逐步流量打开,持续观察 - 只写新库:双写开关切到新库,保证只写新库,完成数据迁移方案
- 迁移完成: 系统稳定运行一段时间,迁移&双写代码下线,老库进行资源释放
step1:环境准备:线上库配置完成
线上库配置完成,并且找到 业务低峰时段,进行迁移操作
1)配置工作
- 申请db资源 8个库
- 创建逻辑库,配置逻辑表
- 配置逻辑表路由算法
- 应用中配置好分库分表规则
- 多数据源配置
有关多数据源配置,可以参考尼恩推送中台中的多数据源配置。
2)通过监控查看业务低峰时段
- 从监控找出业务低峰期,预估操作时段,由图我们可以看出业务低峰时间在2:00-5:00
step2:开始全量数据迁移
全量数据迁移周期很长。
“全量数据迁移”是指是 老库的数据。这是真正的数据的迁移,它迁移的是老数据库表里已经存在的数据(这些数据可能是历史数据,早已经写入,也可能刚刚写入不久的数据,非未来新增的数据),一般来说, 会通过Select 获取源端数据库里的表的数据。然后通过Insert、Replace into、Update、Delete 的方式,写入到新库。
数据迁移的时间,有可能是一周,有可能是1个月
每一次数据迁移都需要一段漫长的时间,不是一天两天就搞定了的。
通常来说我们迁移数据的过程基本如下图:
开启全量同步
-
使用精卫(阿里数据同步工具),它可以根据配置好的分库分表规则,自动将数据同步到相应的物理分表中
-
全量开始时间,选择
gmt_modified
作为条件字段 -
全量迁移的时候,源数据 默认走备库,目标端写入的是主库。
无论是全量还是校验,其实都会对源端备库,目标端的主库造成压力。所以这里需要注意一下,以免对线上服务造成影响。
-
在迁移数据过程中,当写入发生冲突时,转换为
update
执行 -
注意一下数据迁移完成的时间,假设我们以80亿数据上,同时开启8个任务,每个任务上线tps为1w,计算公式如下:
- 数据迁移看板,实时查看迁移进度(ps:本工具是阿里内部的,外部也有很多类似开源系统)
step3: 开启增量同步
增量同步:全量迁移完成后开启增量(自动回溯全量开始时间,消息多次消费会进行幂等)
完成全量的迁移后,然后需要处理新增的这部分数据。
需要实时的增量数据在写完原本的数据库之后然后写到我们的新的存储,在这一过程中我们需要不断的进行数据校验。
当我们校验基本问题不大的时候,然后进行切流操作,直到完全切流之后,我们就可以不用再进行数据校验和增量数据迁移。
在数据迁移工具(精卫)中,开启增量任务, 增量同步需要注意的地方:
-
在INSERT时,出现主键冲突,精卫会将
INSERT
改成UPDATE
事件。用户无需担心主键冲突产生异常。 -
异常处理机制:增量任务产生异常后,迁移工具默认会在同一机器上重试三次,若三次都失败后,会给出报警信息,并稍后换一台机器继续重试。
增量同步涉及到同步位点说明:增量同步主要是参照原库的binlog位点开始的,这个同步位点,也叫做消费位点。
具体来说, 消费位点是指当前已经成功消费的Binlog队列的位置,位点是一个 'yyyy-MM-dd HH:mm:ss' 格式的时间戳。
step4:数据校验
全量数据校验,查看数据是否一致
全量同步之后,我们需要不断的进行数据校验。
增量同步之后,我们也需要不断的进行数据校验。
当我们校验基本问题不大的时候,然后进行切流操作,直到完全切流之后,我们就可以不用再进行数据校验和增量数据迁移。
数据校验包括:
- 全量校验服务
- 全量订正服务
- 积分对账(业务校验)
全量校验服务
下面使用的工具是阿里内部的,原理都类似,可以参考阿里对外开源的数据传输服务DTS。
- 全量校验服务和全量迁移服务类似,配置流程同上。校验服务执行完成,会在页面展示缺失和差异的数量。
- 验证源端和目标端的数据是否一致,也是全量订正服务必须的前置操作。
通过校验,找到 数据的差异,进行数据的修正,或者叫做订正
全量订正服务
- 通过订正服务可以将不一致的源端DB和目标端DB进行数据订正,保证一致性。
- 使用订正服务前必须进行校验服务。
积分对账(业务校验)
业务校验主要是进行数据的一致性校验。
需要注意:业务校验任务注意不要影响线上运行的服务,通常校验任务会写很多批查询的语句,会出现批量扫表的情况,如果代码没有写好很容易导致数据库挂掉。
对账标准:target数据库和source数据库中数据保持一致(所有字段)
对账梳理:可以从积分总表和积分明细两个方面来处理
对账流程:通过定时任务轮询执行已经完成迁移的用户在新老库的数据一致性。需要注意的是由于读取新老库有先后顺序,所以产生瞬时的数据不一致,对于这种问题可以采用对账重试,只要保证最终一致即可。
1)抽样数据校验
按业务类型或者用户id,对最新增量数据进行抽样校验(下面校验工具为阿里内部工具,外部可以参考阿里数据传输服务DTS),然后需要对有问题数据进行订正
2)Odps离线数据校验
使用odps的小时表来进行对账。思路很简单,利用odps数据同步能力,离线数据的处理能力,加上动态脚本的编写快速实现多系统间对账。
不需要进行应用的改造,稳定性上也有保障。对于实时性要求不高的场景,可以推荐尝试使用。
step5:切流测试
改造代码预发测试(采集线上流量进行回放,多种case跑一下,切流开关等校验),没问题发布上线
step6:二次校验
确保安全,在正式切流前,再次全量进行校验&订正(数据追平)
step7:开启双写(增,删,改)切换
整体上分为下面4个步骤,通过配置动态进行切换,切换期间需要注意的问题如下:
- 对写新库操作需要进行日志埋点
- 新库不要求一定写成功(不影响服务,后期不一致数据通过增量任务兜底)
- 如果老库和新库都写,最终返回结果是老数据源
- 数据源回滚:开启了双写,新数据库中总积分值不对(新数据源回滚不了)
- 开启双写时机:由于已经开启增量,所以对于还没切流前,不需要开启双写。在准备进行切库时,开启双写。为什么这里还需要开启双写?
- 考虑极限情况下,增量同步任务会出现延迟(理论上是秒级)
- 实时同步数据到新数据库中
step8:开启灰度读切流
找准时间阶段操作,在低流量阶段(凌晨过后) 进行操作
操作的时候,进行灰度处理,逐步推进。
进行灰度切流userId%x
,进行验证,逐步流量打开,持续观察
读切流的流程:
- 对所有查询接口进行整理
- 对DAO层编写代理层
xxProxyDAO.class
- 对读接口在代理层进行开关控制
- 根据userId后4位取模进行灰度,动态获取查询时用的数据源
注意:对于没有路由字段userId,需要进行代码改造
当我们数据校验基本没有报错了之后,说明我们的迁移程序是比较稳定的了,那么我们就可以直接使用我们新的数据了吗?当然是不可以的,如果我们一把切换了,顺利的话当然是很好的,如果出现问题了,那么就会影响所有的用户。所以我们接下来就需要进行灰度,也就是切流。
本次切流方案是基于用户id取模的方式去进行切流,这个切流需要制定好一个切流计划,在什么时间段,放出多少的流量,并且切流的时候一定要选择流量比较少的时候进行切流,每一次切流都需要对日志做详细的观察,出现问题尽早修复,流量的一个放出过程是一个由慢到快的过程,比如最开始是以1%的量去不断叠加的,到后面的时候我们直接以10%,20%的量去快速放量。因为如果出现问题的话往往在小流量的时候就会发现,如果小流量没有问题那么后续就可以快速放量。
切换过程采用逐步放量的形式,灰度方式很多我们采用的是先白名单验证,然后用户ID取模10000逐步放量的方式。
灰度切流验证:万分之1-1%-5%-10%-50%-100%切流
灰度读切流完成之后, 读流量,全部落入到 新库。
step9:只写新库
双写开关切到新库,保证只写新库,完成数据迁移方案
前面的第7步的双写,已经变成了单写。
step10:完成迁移
直到切流到100%,迁移已经完成。
但是,老库还不能立即下线, 还得备用一段时间,以防万一出问题还能切回老库
并且,需要保证老库的数据,能是最新的。
所以,开启精卫新库到老库同步任务。
然后观察各个业务后续工单反馈情况和各个系统预警&日志;对新库进行性能压测,确保新库的稳定性
100亿级数据分库分表后,如何迁移:
最后简单来总结下这个套路,总结起来,其实就是四个步骤:
第1步:存量同步,
第2步:增量同步,
第3步:数据校验,
第4步:灰度切流
更细致一点,就是10个步骤,具体如上。
数据迁移的总结
周期很长:整个迁移过程从方案制定到最终的迁移完成持续约一个多月时间,最终完成迁移。
方案可靠:无论是利用数据库工具还是利用服务对数据进行迁移,目标都是一致的那就是数据无差异,用户无感知,异常可监控,方案可回滚。
充分演练:在迁移前尽可能进行演练,通过一些测试编写的自动化脚本能否高效发现一些潜在的问题。
尽早迁移:同时存储是有状态的,迁移难度比较大,开发者需要具备前瞻性,尽量在选型的时候慎重,选择合适的数据库,避免进行数据库迁移。发现数据库选型有潜在的问题时,需要当机立断,尽早迁移。不要以为出现问题的概率不大,就拖延了。否则一旦出现问题,就是重大故障,造成的损失难以估量。
参考资料
https://baijiahao.baidu.com/s?id=1711398612204958365&wfr=spider&for=pc
https://github.com/alibaba/tb_tddl
https://github.com/alibaba/yugong
https://www.aliyun.com/product/dts
结合 菜鸟积分系统的方案,回顾前面的面试题
- 数据库如何不停机迁移?
- 100亿级库表,如何不停机迁移?
以上的方案,可以作为大家的一个参考答案。保证面试官非常满意。
后续尼恩会给大家结合行业案例,分析出更多,更加劲爆的答案。
当然,如果大家遇到这类高并发的面试难题,可以找来尼恩的 【技术自由圈】 交流。
技术自由的实现路径 PDF:
实现你的 响应式 自由:
这是老版本 《Flux、Mono、Reactor 实战(史上最全)》
实现你的 spring cloud 自由:
《Spring cloud Alibaba 学习圣经》 PDF
《分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)》
《一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)》
实现你的 linux 自由:
实现你的 网络 自由:
《网络三张表:ARP表, MAC表, 路由表,实现你的网络自由!!》
实现你的 分布式锁 自由:
实现你的 王者组件 自由:
《队列之王: Disruptor 原理、架构、源码 一文穿透》
《缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)》
《Java Agent 探针、字节码增强 ByteBuddy(史上最全)》