0

0

万亿级数据应该迁移的方法

coldplay.xixi

coldplay.xixi

发布时间:2020-10-23 17:20:41

|

2803人浏览过

|

来源于juejin

转载

java基础教程栏目介绍万亿级数据应该迁移的方法。

万亿级数据应该迁移的方法

背景

在星爷的《大话西游》中有一句非常出名的台词:“曾经有一份真挚的感情摆在我的面前我没有珍惜,等我失去的时候才追悔莫及,人间最痛苦的事莫过于此,如果上天能给我一次再来一次的机会,我会对哪个女孩说三个字:我爱你,如果非要在这份爱上加一个期限,我希望是一万年!”在我们开发人员的眼中,这个感情就和我们数据库中的数据一样,我们多希望他一万年都不改变,但是往往事与愿违,随着公司的不断发展,业务的不断变更,我们对数据的要求也在不断的变化,大概有下面的几种情况:

  • 分库分表:业务发展越来越快,导致单机数据库承受的压力越来越大,数据量也越来越多,这个时候通常会使用分库的方法去解决这个问题,将数据库的流量均分到不同的机器上。从单机数据库到分库这个过程,我们就需要完整的迁移我们的数据,我们才能成功的分库的方式上使用我们的数据。
  • 更换存储介质:上面介绍的分库,一般来说我们迁移完之后,存储介质依然是同样的,比如说之前使用的是单机Mysql,分库之后就变成了多台机器的Mysql,我们的数据库表的字段都没有发生变化,迁移来说相对比较简单。有时候我们分库分表并不能解决所有的问题,如果我们需要很多复杂的查询,这个时候使用Mysql可能就不是一个靠谱的方案,那么我们就需要替换查询的存储介质,比如使用elasticsearch,这种的迁移就会稍微要复杂一些,涉及到不同存储介质的数据转换。
  • 切换新系统:一般公司在高速发展中,一定会出现很多为了速度快然后重复建设的项目,当公司再一定时间段的时候,往往这部分项目会被合并,变成一个平台或者中台,比如我们一些会员系统,电商系统等等。这个时候往往就会面临一个问题,将老的系统中的数据需要迁移到新的系统中,这个时候就更加复杂了,有可能不仅是存储介质有变动,有可能项目语言也不同,从更上层的角度来看,部门有可能也不同,所以这种数据迁移的难度是比较高,风险也更加的大。

在实际业务开发中,我们会根据不同的情况来做出不同的迁移方案,接下来我们来讨论一下到底应该怎么迁移数据。

数据迁移

数据迁移其实不是一蹴而就的,每一次数据迁移都需要一段漫长的时间,有可能是一周,有可能是几个月,通常来说我们迁移数据的过程基本都和下图差不多:万亿级数据应该迁移的方法‘ 首先我们需要将我们数据库已经存在的数据进行批量的迁移,然后需要处理新增的这部分数据,需要实时的把这部分数据在写完原本的数据库之后然后写到我们的新的存储,在这一过程中我们需要不断的进行数据校验。当我们校验基本问题不大的时候,然后进行切流操作,直到完全切流之后,我们就可以不用再进行数据校验和增量数据迁移。

存量数据迁移

首先我们来说一下存量数据迁移应该怎么做,存量数据迁移在开源社区中搜索了一圈发现没有太好用的工具,目前来说阿里云的DTS提供了存量数据迁移,DTS支持同构和异构不同数据源之间的迁移,基本支持业界常见的数据库比如Mysql,Orcale,SQL Server等等。DTS比较适合我们之前说的前两个场景,一个是分库的场景,如果使用的是阿里云的DRDS那么就可以直接将数据通过DTS迁移到DRDS,另外一个是数据异构的场景,无论是Redis还是ES,DTS都支持直接进行迁移。

那么DTS的存量迁移怎么做的呢?其实比较简单大概就是下面几个步骤:

  1. 当存量迁移任务启动的时候,我们获取当前需要迁移的最大的id和最小id
  2. 设置一个分段,比如1万,从最小id开始每次查询1万的数据给DTS服务器,交给DTS处理。sql如下:
select * from table_name where id > curId and id < curId + 10000;复制代码

3.当id大于等于maxId之后,存量数据迁移任务结束

当然我们在实际的迁移过程中可能不会去使用阿里云,或者说在我们的第三个场景下,我们的数据库字段之间需要做很多转换,DTS不支持,那么我们就可以模仿DTS的做法,通过分段批量读取数据的方式来迁移数据,这里需要注意的是我们批量迁移数据的时候需要控制分段的大小,以及频率,防止影响我们线上的正常运行。

增量数据迁移

存量数据的迁移方案比较有限,但是增量的数据迁移方法就是百花齐放了,一般来说我们有下面的几种方法:

  • DTS: 阿里云的DTS算是一条龙服务了,在提供存量数据迁移的同时也提供了增量数据迁移,只不过需要按量收费。
  • 服务双写:比较适合于系统没有切换的迁移,也就是只换了存储但是系统还是同一个,比如说分库分表,redis数据同步等,这个的做法比较简单直接在代码里面同步的去写入需要迁移的数据,但是由于不是同一个数据库就不能保证事务,有可能导致迁移数据的时候会出现数据丢失,这个过程通过后续的数据校验会进行解决。
  • MQ异步写入:这个可以适用于所有的场景,当有数据修改的时候发送一个MQ消息,消费者收到这个消息之后再进行数据更新。这个和上面的双写有点类似,但是他把数据库的操作变成了MQ异步了出问题的概率就会小很多
  • 监听binlog: 我们可以使用之前说过的canal或者其他的一些开源的如databus去进行binlog监听,监听binlog的方式 就和上面的消息MQ方式一样,只是发送消息的这一步被我们省略了。这个方式的一个开发量来说基本是最小的。

这么多种方式我们应该使用哪种呢?我个人来说是比较推荐监听binlog的做法的,监听binlog减少开发成本,我们只需要实现consumer逻辑即可,数据能保证一致性,因为是监听的binlog这里不需要担心之前双写的时候不是一个事务的问题。

数据校验

前面所说的所有方案,虽然有很多是成熟的云服务(dts)或者中间件(canal),但是他们都有可能出现一些数据丢失,出现数据丢失的情况整体来说还是比较少,但是非常难排查,有可能是dts或者canal不小心抖了一下,又或者是接收数据的时候不小心导致的丢失。既然我们没有办法避免我们的数据在迁移的过程中丢失,那么我们应该通过其他手段来进行校正。

Chromox
Chromox

Chromox是一款领先的AI在线生成平台,专为喜欢AI生成技术的爱好者制作的多种图像、视频生成方式的内容型工具平台。

下载

通常来说我们迁移数据的时候都会有数据校验这一个步骤,但是在不同团队可能会选取不同的数据校验方案:

  • 之前在美团的时候,我们会做一个双读,也就是我们所有的读取都会从新的里面读取一份,但是返回的还是老的,这个时候我们需要做这部分数据的校验,如果有问题可以发出报警人工修复或者自动修复。通过这种方式,我们常用的数据就能很快的进行一个修复,当然也会不定时的去跑一个全量的数据check,只是这种check出来修复数据的时间就比较滞后。
  • 现在在猿辅导之后,我们没有采用之前的那种方式,因为双读check虽然能很快发现数据的不对,但是我们并没有对这部分数据有那么高的一个实时性校验并且双读的一个代码开发量还是稍微比较大的,但是又不能依靠不定时全量check去保证,这样就会导致我们的数据校验时间会非常的延长。我们采取了一个折中的方法,我们借鉴了对账里面的T+1的一个思路,我们每天凌晨获取老数据库中昨天更新的数据,然后和我们新数据库中的数据做一一比对,如果有数据不一样或者数据缺失,我们都可以立马进行一个修复。

当然在实际开发过程中我们也需要注意下面几点:

  • 数据校验任务的一个正确性如何保证,校验任务本来就是去校正其他数据的,但是如果他自身出现了问题,就失去了校验的意义,这里目前来说只能靠review代码这种方式去保证校验任务的正确性。
  • 校验任务的时候需要注意日志的打印,有时候出现问题可能是直接所有数据出现问题,那么校验任务就有可能会打出大量的错误日志,然后进行报警,有可能会将系统打挂,或者说影响其他人的服务。这里如果要简单一点搞,可以将一些非人工处理的报警搞成warn,复杂一点搞得话,可以封装一个工具,某个error打印再某个时间段超过一定量然后就不用再打印了。
  • 校验任务注意不要影响线上运行的服务,通常校验任务会写很多批查询的语句,会出现批量扫表的情况,如果代码没有写好很容易导致数据库挂掉。

切流

当我们数据校验基本没有报错了之后,说明我们的迁移程序是比较稳定的了,那么我们就可以直接使用我们新的数据了吗?当然是不可以的,如果我们一把切换了,顺利的话当然是很好的,如果出现问题了,那么就会影响所有的用户。

所以我们接下来就需要进行灰度,也就是切流。 对于不同的业务切流的的维度会不一样,对于用户维度的切流,我们通常会以userId的取模的方式去进行切流,对于租户或者商家维度的业务,就需要按照租户id取模的方式去切流。这个切流需要制定好一个切流计划,在什么时间段,放出多少的流量,并且切流的时候一定要选择流量比较少的时候进行切流,每一次切流都需要对日志做详细的观察,出现问题尽早修复,流量的一个放出过程是一个由慢到快的过程,比如最开始是以1%的量去不断叠加的,到后面的时候我们直接以10%,20%的量去快速放量。因为如果出现问题的话往往在小流量的时候就会发现,如果小流量没有问题那么后续就可以快速放量。

注意主键ID

在迁移数据的过程中特别要注意的是主键ID,在上面双写的方案中也提到过主键ID需要双写的时候手动的去指定,防止ID生成顺序错误。

如果我们是因为分库分表而进行迁移,就需要考虑我们以后的主键Id就不能是自增id,需要使用分布式id,这里比较推荐的是美团开源的leaf,他支持两种模式一种是雪花算法趋势递增,但是所有的id都是Long型,适合于一些支持Long为id的应用。还有一种是号段模式,这种会根据你设置的一个基础id,从这个上面不断的增加。并且基本都走的是内存生成,性能也是非常的快。

当然我们还有种情况是我们需要迁移系统,之前系统的主键id在新系统中已经有了,那么我们的id就需要做一些映射。如果我们在迁移系统的时候已经知道未来大概有哪些系统会迁移进来,我们就可以采用预留的方式,比如A系统现在的数据是1到1亿,B系统的数据也是1到1亿,我们现在需要将A,B两个系统合并成新系统,那么我们可以稍微预估一些Buffer,比如给A系统留1到1.5亿,这样A就不需要进行映射,B系统是1.5亿到3亿,那么我们转换成老系统Id的时候就需要减去1.5亿,最后我们新系统的新的Id就从3亿开始递增。 但是如果系统中没有做规划的预留段怎么办呢?可以通过下面两种方式:

  • 需要新增一个表,将老系统的id和新系统的id做一个映射记录,这个工作量还是比较大的,因为我们一般迁移都会涉及几十上百张表,记录的成本还是非常的高。
  • 如果id是Long型的话,我们可以好好利用long是64位这个因素,我们可以制定一个规则,我们新系统的id都是从一个比较大的数开始,比如从大于Int的数开始,将小Int的那部分数都可以留给我们的老系统做Id迁移,比如我们上面的1.5亿的数据量,其实只用了28位,我们的Int是32位,那么还有4位可以使用,这个4位可以代表16个系统做迁移,当然如果规划中有更多的系统做迁移,可以将新系统的id起始点设置得更大一点。如下图所示:万亿级数据应该迁移的方法

总结

最后简单来总结下这个套路,其实就是四个步骤,一个注意:存量,增量,校验,切流,最后再注意一下id。不管是多大量级的数据,基本上按照这个套路来迁移就不会出现大的问题。希望能在大家的后续迁移数据工作中,这篇文章能帮助到你。

如果大家觉得这篇文章对你有帮助,你的关注和转发是对我最大的支持,O(∩_∩)O:

相关免费学习推荐:java基础教程

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

223

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

458

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

169

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

246

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

34

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号