写点什么

伴鱼数据库之 MongoDB 数据在线迁移到 TiDB

  • 2022 年 7 月 11 日
  • 本文字数:2989 字

    阅读完需:约 10 分钟

作者: Hacker_ubN7WXjw 原文来源:https://tidb.net/blog/7d413579

1. 背景

伴鱼在发展初期,数据存储选择了 MongoDB 数据库,Mongodb 数据库同时也支撑了伴鱼很长一段时间的业务发展。随着伴鱼业务场景的丰富以及数据量的增长,MongoDB 在有些方面开始出现问题,比如业务对事务的要求、单表性能问题、单机的容量瓶颈和从节点请求不均衡等问题。基于以上问题,数据存储,我们选择了业界比较火的分布式 TiDB 数据库,详细介绍可见 < 我们为什么放弃 MongoDB 和 MySQL,选择 TiDB> 一文。


2019 年,伴鱼的新业务 All In TiDB,但是历史前 5 年的数据都积攒在 MongoDB 数据库 (集群 20+,单个集群数据最大 1T+,数据都是经过 zlib 压缩的),而且数据还在不断增长,这时 MongoDB 集群主要存在以下 2 个主要问题:


  • 由于我们的服务器数据盘都是 1.5T 的 nvme,某些集群很快会达到容量瓶颈

  • 随着数据量的增长,某些集群大表,由于索引不是最优,性能问题越发明显


对于 MongoDB 集群数据容量问题,TiDB 无限水平扩展特性对于我们来说,无疑是比较好的选择;对于大表索引不是最优导致的性能问题,我们觉得推动研发重新梳理业务和索引,比 DBA 单纯在大表上添加索引效果会更好。基于这些考虑,我们踏上了 MongoDB 数据在线迁移到 TiDB 之路。下面从数据迁移架构及方案的选择,配套建设等方面,详细介绍下我们是如何将 MongoDB 的数据在线迁移到 TiDB 的。

2. 数据迁移架构及方案

2.1 数据迁移架构

异构数据库的数据迁移,在业界其实都能找到参考案例,我们的迁移架构如下图所示,主要流程步骤如下:


  1. 中间件获取 MongoDB oplog,将获取的 oplog 进行解析,写入到 kafka

  2. 分段将 MongoDB 的数据全量迁移到 TiDB

  3. 数据全量迁移完后,消费 kafka 数据,将增量数据同步到 TiDB

  4. 对异构数据库两侧数据进行抽样校验

  5. 将 MongoDB 的读流量迁移到 TiDB

  6. 将 MongoDB 的写流量迁移到 TiDB



当然这个数据迁移架构也存在一些缺点:


  • 写流量不能回滚

  • 数据链路较长,存在读延时

2.2 数据迁移方案

不同的业务场景,我们可以采用不同的数据迁移方案。在伴鱼的异构数据库数据迁移过程中,我们主要经历了以下几种场景,下面对以下几种场景进行介绍。

2.2.1 场景一

业务表只有写入和查询,没有更新和删除操作。我们可以不采用中间件迁移的模式,这时迁移的主要流程步骤如下:


  1. 设计 TiDB 表结构,梳理原表的使用场景,优化索引

  2. 业务代码实现数据库双写

  3. 分段将 MongoDB 的数据全量迁移到 TiDB

  4. 对异构数据库两侧数据进行抽样校验

  5. 业务将 MongoDB 的读流量迁移到 TiDB

  6. 业务将 MongoDB 的写流量迁移到 TiDB

2.2.2 场景二

业务表存在增删改查操作,同时业务表有数据创建时间和更新时间索引。针对这种场景,我们也可以不采用中间件迁移的模式,这时迁移的主要流程步骤如下:


  1. 设计 TiDB 表结构,梳理原表的使用场景,优化索引

  2. 根据 objectID 或者创建时间索引分段将 MongoDB 的数据全量迁移到 TiDB

  3. 根据更新时间,将增量数据同步到 TiDB

  4. 对异构数据库两侧数据进行抽样校验

  5. 业务在低峰期将 MongoDB 的读写流量迁移到 TiDB

2.2.3 场景三

业务表存在增删改查操作,同时业务表没有时间索引。针对这种场景,我们采用中间件模式进行迁移,这时迁移的主要流程步骤如下:


  1. 设计 TiDB 表结构,梳理原表的使用场景,优化索引

  2. 开启中间件获取最新 MongoDB oplog,将解析的数据写入到 kafka

  3. 分段将 MongoDB 的数据全量迁移到 TiDB

  4. 数据全量迁移完后,消费 kafka 中的数据,将增量数据同步到 TiDB

  5. 对异构数据库两侧数据进行抽样校验

  6. 将 MongoDB 的读流量迁移到 TiDB

  7. 将 MongoDB 的写流量迁移到 TiDB

2.3 迁移方案优劣

上述 3 种场景,数据迁移过程都有其共同点,也有不同的地方,有其优势的地方,也有需要改进的地方。

2.3.1 方案共同点

对于以上 3 种场景,迁移过程中相同点主要表现在以下几个方面:


  • TiDB 表结构设计。这一步做的事情包括:业务需要梳理表上的所有功能 (主要是查询),哪些可以优化,哪些可以废弃,哪些索引必须加上等等;同时业务可以优化代码,收拢写入口。最终的目标保证迁移到 TiDB 的表,在很长一段时间内不会出现性能问题。

  • 数据迁移。这一步做的事情包括:业务代码需要兼容数据迁移过程中可能发生冲突的地方 (我们参考了在线改表工具的做法);迁移脚本需要做到可以随时启停,灵活控制速度,避免迁移对线上造成压力。

  • 对异构数据库两侧数据进行抽样校验。我们把 objectID 带入到 TiDB,同时给该字段加上索引,这样抽样校验会比较方便,等抽样校验完毕后,会把索引清理掉;我们从 MongoDB 的 objectID 中解析出机器码时间戳等信息组合出来的一个整形 id,作为 TiDB 表的主键,这样也便于我们做抽样校验;如果 MongoDB 表中有唯一键,我们不需要做任何变换,直接通过唯一键对两侧数据进行校验。

  • 业务读流量迁移到 TiDB。业务需要加开关实现快速切换,有问题可以快速回滚。

  • 业务写流量迁移到 TiDB。读取通常需要观察一周左右,没有问题,切写流量。

2.3.2 方案优缺点

在场景一中,数据迁移全程,DBA 参与的工作比较少,只需要配合研发审核 sql 质量以及数据迁移过程中可能导致的数据库压力问题。缺点是,数据迁移只局限于只有写入的场景。


在场景二中,增量数据通过脚本将满足更新时间的数据查出来进行同步,数据过大或者查询时间过长,都会导致 TiDB 数据延迟较大。如果业务读请求对数据延时有要求,那么读请求不能切换到 TiDB。


在场景三中,由于数据链路较长,对延时要求特别高的场景,也同样存在延时导致两侧数据不一致的问题。

2.3.3 方案改进点

由于方案三可以适用上述的所有场景,所在伴鱼的后续数据迁移中,我们都采用中间件迁移的模式。为了加快数据迁移的速度,同时满足业务对延时敏感的要求,我们对方案三进行了以下改进:


  • 原先从 MongoDB 批量查询一批数据,逐条插入到 TiDB,改为每次组装一批数据插入到 TiDB。

  • 在表数据量增长比较快的场景下,由于中间件这条链路的存在,数据同步延时不可避免。之前的做法是消费 kafka 并拼装数据后同步到 TiDB,后面改为从 kafka 拿到 objectID 后,去 MongoDB 主库查询数据,然后再更新到 TiDB。我们这样做的目的是,假如源端 mongoDB 一条数据频繁更新,同时中间件同步到 kafka 或者消费 kafka 数据存在延时,我们也能通过 objectID 拿到的最新的数据,进一步降低数据迁移延时的问题。

  • 原先先迁移全量数据,再消费增量数据,后面改为全量和增量数据同时迁移,迁移速度进一步提高。我们做过一个统计,在 raft_store cpu 维持在 30% 左右时,全量和增量同时进行,一天大概可以迁移 4~5 亿数据。

3. 配套建设

数据通过中间件同步,我们通常需要部署同步 MonogDB 集群对应的中间件实例,然后确认增量数据是否同步到 kafka,最后把 kafka 地址和对应的 topic 交付给研发。由于这套部署过程还是比较繁琐的,我们也将其沉淀为平台,如下图所示。



数据迁移涉及数据的全量迁移和增量同步,我们刚开始在绘本业务线迁移了 5 张亿级大表,同时发现其他业务线也会有类似的迁移需求。由于整个迁移流程已经趋于稳定,同时也我们积累了一些经验,我们把这套代码抽取出来,可以供其他业务线复用。这样当我们推动其他业务线进行数据迁移时,研发只需要一份简单的说明文档,就能轻松搞定了。

4. 总结

目前,我们已经将近 3T 的 MongoDB 数据迁移到 TiDB,解决了线上部分 mongoDB 集群存在的性能风险。现有 MongoDB 集群,还承担着历史众多业务,我们会时刻监测表的性能,如果发现性能风险,我们就会迁移到 TiDB。


发布于: 刚刚阅读数: 3
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
伴鱼数据库之MongoDB数据在线迁移到TiDB_TiDB 社区干货传送门_InfoQ写作社区