分享一次海量数据平滑迁移实战

京东云开发者
• 阅读 72

背景

采购系统(BIP)在经历多年演进后,系统整体复杂度和数据量俨然已经极具规模,本文着重讨论海量数据的治理

存储现状:工程端实时订单库采用MySQL 5.5集群,其中主库配置为32C/48G/6000G,无法归档的订单热数据占磁盘空间85%(5.1T)

痛点:6T磁盘已经单容器最大,无法继续扩容,剩余磁盘余量过小,难适应未来发展

目标

降低磁盘容量,优化数据模型,提升系统稳定性

调研

首先,既然是要解决存储容量的问题,就要对详细的容量情况有个更加清楚的了解。总结下当前存储容量问题,最大的表是订单操作日志表lifecycle共1.3T,大于500G的表2张共1.5T;100G~500G的表10张共2.6T。以下是优化前库里大表(大于100G)的详细空间占用情况:

序号 表名 空间大小(行数|总大小|数据大小|索引大小)
1 lifecycle **46亿
2 cgfenpei 5.8亿
3 cgtable 5.8亿
4 cgdetail 5.5亿
5 po_asn_receipt_detail 4.5亿
6 po_data 2.5亿
7 purchase_order_extension 4.2亿
8 po_stock_detail 7.3亿
9 po_channel 6.1亿
10 cgtablesubtable 6亿
11 unduprecord 4.2亿
12 po_stock 2.8亿
合计 4.6T

其次,确认当前最高效的优化思路是将lifecycle表迁移到其他库,原因有二:1.lifecycle表的含义是操作日志,在业务上不算订单域内最核心的模型,风险可控;2.占用空间大,单表46亿行数据,空间占用1.3T,一张表占了磁盘空间的22%,优化的ROI高

最后,想说明下,为什么没有直接将整个库,从传统MySQL切换到JED,原因也有二:1.JED和MySQL的查询语法还是有一定差异,直接切换,成本和风险极高;2.切换存储中间件,获取分布式架构下更大的存储空间并不是银弹,理智告诉我们要结合系统现状,不可盲目下定论

挑战

保障海量数据(存量46亿行,增量600w+行/天,TPS峰值:500+,QPS峰值:200+)迁移期间读、写稳定和准确。 需要补充一下:lifecycle虽然不算订单最核心业务模型,但依旧是辅助业务决策的关键数据,也非常重要

例子:



分享一次海量数据平滑迁移实战



方案

整体方案

数据同步 -> 双读 -> 双写 -> 离线验证 -> 数据清理



分享一次海量数据平滑迁移实战



详细设计

数据同步,通过DRC实现,历史全量+增量,其中有以下几点使用心得:

◦同步速度问题,本次是使用传统MySQL5.5 -> JED 底层MySQL 8.0 单表同步,效率大概是4M/S,一共花了3天半左右

◦数据同步过程中不要操作暂停,否则任务重启后,会重新同步历史数据,导致数据同步周期变长。详情参考: 关于全量任务暂停重启之后数据同步慢的原因

◦字段兼容问题,老库历史时间字段类型是datetime,新库需要改为datetime(3),这种数据同步是可以兼容的(下文会讲为什么要优化时间字段精度)

◦数据验证问题,当时在历史数据全量同步完毕后开启了DRC数据验证,但是许久未执行完成,收到DRC运维告知出现大量报错,最终结论是暂时不支持这两个版本的数据比对(5.5->8.0),这也是为什么整体架构上采用BDP抽数比对数据的主要原因

数据验证,业务程序完成双写、双读改造

双写

分享一次海量数据平滑迁移实战



为什么采用双写?答:控制风险。 1.团队内还没有应用直接写入多分片JED的先例,而且新、老库的底层MySQL版本也差异比较大(5.5 vs 8.0),当时通过分批次灰度上线完成逐步切量验证;2.方便进行数据验证,lifecycle是业务操作日志,基本涵盖了所有的写入场景,其中因为历史问题,不乏一部分逻辑和订单更新在同一事务中,现在迁移到新库,本地事务会存在不生效的场景

▪具体改造方案:

新增【验证开关】 ,开启后新/老库双写,另外需要要引入vitess驱动,目前只支持JDK8及以上

新增【上线开关】 ,开启后只写新库,此开关是在验证逻辑无问题后,最终切换的开关,代表迁移完成

▪注意,开关改造完成上线后,“全量+增量DRC任务”在验证期间是一直启用的,也就是说验证期间,增量数据会写两份到新库

▪一部分是实际的生产数据,一部分是待验证的测试数据。那么就带来另一个问题,如何识别和区分这两部分数据,我们采用的方案是:JED建表指定趋势自增的最小id(200亿)+【验证开关】开启的时间戳进行区分

▪如下图,其中A和A'都是【验证开关】切换后的增量数据,由于老库的id已经自增写到了70亿,并且DRC同步任务也是指定id写入,所以建表时指定新增数据id是200亿(详情参考: 数据库自增ID列设置 ),和老数据之间存在一定gap方便识别。BDP脚本数据比对的也是:老库.A和新库.A'(这里默认DRC增量同步的数据是准确的)

▪清除测试数据,真正完成【上线开关】切换,需要提前清除测试数据,只需指定id>200亿的物理删除即可。注意:针对多分片的JED物理删除delete语句,我们程序上如果为了防止大事务,而采用“for循环+limit n”的方式执行,实际的每次SQL语句执行结果是多个分片的n的聚合,而不是n,如果程序上对结果有判断逻辑,需要额外注意

分享一次海量数据平滑迁移实战



双读

分享一次海量数据平滑迁移实战



整体逻辑基本复用写入期间已有开关,其中针对新库当中DRC实时同步的数据(上图:新库.A)会根据开关开启时间进行过滤

▪其中,在验证期间,新、老库都会根据采购单号进行查询并实际返回老库的查询结果,其中还会进行结果比对,出现数据不一致会输出异常日志关键字

▪另外,因为lifecycle操作日志数据是有先后顺序的,老库的处理方式是根据自增id进行倒排,到了新库以后,由于采用的是JED分片(分布式存储的磁盘空间更大),考虑到开发成本,数据id采用的是趋势递增的自增主键(详情参考: Vitess全局唯一ID生成的实现方案 ),这时多集群并行写入无法继续使用基于id倒排的方式返回结果(后写入的数据可能id较小,可以参考sequece发号器的ID生成),所以将原始的数据写入时间戳从datetime提高精度到datetime(3),通过数据写入时间进行倒排,这里也解释了上文,新库DRC数据同步为什么要考虑字段兼容的问题

▪补充1:这里基于时间倒排在业务上是准确的,因为lifecycle数据是根据订单号进行分片的,所以同一订单一定落在单分片上,也就是说不存在不同分片时钟偏移的问题,单订单的操作日志的时间序列一定是按照写入顺序逐渐增加的

▪补充2:新库字段类型变更(datetime->datetime(3)),32分片,共46亿行数据,执行了大概1小时,期间主从延迟最高30分钟,容器负载正常

▪补充3:应用的关键字告警配置,日志文件仅支持以error.log、err.log、exception.log结尾,并开启历史日志的路径

▪最后,双读期间共通过业务的实际查询流量发现数据不一致问题2个+,在并未影响到业务使用的前提下及时发现了系统异常

离线验证

▪lifecycle归根结底还是写多读少的业务场景,为了防止出现上文数据比对验证的遗漏,我们会采用BDP离线任务会分别开启增量数据+历史全量数据验证。通过对新、老库的全量数据字段相互sql inner join的方式完成比对,其中会忽略id和写入时间,因为新库的id不是单调递增、时间精确到了毫秒。期间共发现有效数据问题3个+,均是因为本地事务回滚导致的数据不一致的场景

收尾工作

◦完成【上线开关】切换,只读、写新库,完成整体平滑迁移。在无QA参与前提下,验证期间未出现过数据丢失、重复、错误等异常

◦切换完成后,老库老表和DRC同步任务依旧保留了一周的时间,防止出现场景遗漏,产生数据丢失

◦46亿行大表清理,采用drop+create的方式实现效率、稳定性更高,在业务低峰期完成脚本执行,大概花费10秒的时间,容器负载、内存等指标正常。但是当时碰上了DBA的备份任务,导致有一个从库主从延迟升高,这个后续需要注意

点赞
收藏
评论区
推荐文章
TiDB 底层存储结构 LSM 树原理介绍
随着数据量的增大,传统关系型数据库越来越不能满足对于海量数据存储的需求。对于分布式关系型数据库,我们了解其底层存储结构是非常重要的。本文将介绍下分布式关系型数据库TiDB所采用的底层存储结构LSM树的原理。
Wesley13 Wesley13
2年前
vivo 云服务海量数据存储架构演进与实践
一、写在开头vivo云服务提供给用户备份手机上的联系人、短信、便签、书签等数据的能力,底层存储采用MySQL数据库进行数据存储。随着vivo云服务业务发展,云服务用户量增长迅速,存储在云端的数据量越来越大,海量数据给后端存储带来了巨大的挑战。云服务业务这几年最大的痛点,就是如何解决用户海量数据的存储问题。二、面临挑战
Wesley13 Wesley13
2年前
MongoDB 安装及文档的基本操作
!(https://oscimg.oschina.net/oscnet/upd8eda6ee91df47c0b9dc9005b1f5b85acd1.JPEG)前言MongoDB是一个基于分布式文件存储的半结构化的非关系型数据库。在海量数据中,可以较高性能的处理存取操作。它是以BSON格式进行数据存储(类似JSON格式,但类型更为
Stella981 Stella981
2年前
Node.js一次处理10万条数据
电话销售大家一定都经历过,许多公司都有电销的团队,相信看过华尔街之狼的人肯定会理解的更加深刻。我们今天不讨论那些公司是如何通过各种渠道获取到大众的电话号码的。我有幸开发了一个需要处理海量电话号码的系统,这个系统的功能包括:1.一次导入10万条Excel数据2.对数据进行筛选去重写入数据库3.可对复杂查询条件筛选出数据4.导出数据到E
火眼金睛,天翼云助力打造城市视觉中枢
实时录像,高清监视,多方位视角……随着企事业单位、学校、医院、社区等各行各业对视频监控的需求持续增加,国内视频监控系统规模越建越大,并由此产生了海量、多维的数据,随后问题接踵而至,实现海量数据存储,快速检索价值数据成为行业痛点。那么,如何解决这一难题,实现监控数据更安全可靠,一起来看看天翼云为此做了哪些努力吧~传统视频监控管理模式存在诸多问题,无法将设备,环
一朵云 一朵云
1年前
一文教会你如何快速实现操作系统迁移
为应对CentOS停服带来的安全风险和降低系统迁移成本,解决客户升级操作系统过程中人工投入大、准确率低、无法批量化处理导致整体效率低下的痛点,超聚变自主研发的操作系统迁移工具Safe2FusionOS上线。
基于ClickHouse解决活动海量数据问题 | 京东云技术团队
魔笛活动平台要记录每个活动的用户行为数据,帮助客服、运营、产品、研发等快速处理客诉、解决线上问题并进行相关数据分析和报警。可以预见到需要存储和分析海量数据,预估至少几十亿甚至上百亿的数据量,所以需要选择一款能存储海量数据的数据库。由于是通过接收MQ存储或者API方式存储,所以对实时写入性能也有一定要求。同时可能后续还需要一些实时数据分析等
京东云开发者 京东云开发者
1个月前
HBase集群数据在线迁移方案探索
一、背景订单本地化系统目前一个月的订单的读写已经切至jimkv存储,对应的HBase集群已下线。但存储全量数据的HBase集群仍在使用,计划将这个HBase集群中的数据全部迁到jimkv,彻底下线这个HBase集群。由于这个集群目前仍在线上读写,本文从原理