华为云 GeminiDB Redis 迁移到阿里云数据库 Tair(兼容Redis)方案

更新时间:
复制为 MD 格式

一、适用场景

本方案适用于将华为云 GeminiDB Redis 数据库平滑、高效地迁移至阿里云数据库Tair(兼容Redis)。

迁移类型涵盖:

  • 全量数据迁移: 将源 GeminiDB Redis 数据库中的全部存量数据迁移至目标 Tair(兼容Redis)实例。

  • 增量数据迁移: 在全量数据迁移完成后,持续同步源 GeminiDB Redis 数据库中产生的实时增量数据,确保源和目标数据保持一致。

此方案旨在帮助用户实现不停机或极短时间内停机的 GeminiDB Redis 数据库迁移,最大限度减少对业务的影响。

二、迁移相关工具介绍

1、阿里云数据传输服务 DTS

数据传输服务 DTS(Data Transmission Service)是阿里云提供的一站式数据传输与处理平台。它集成了数据迁移、数据同步、数据订阅、数据加工以及数据校验等核心能力,致力于在多种数据源之间,构建安全、可靠、高性能的数据流动链路,以满足业务上云、异地灾备和实时数仓等多样化场景需求。

2、华为云数据复制服务 DRS

数据复制服务 DRS(Data Replication Service)是华为云提供的一种易用、稳定、高效、用于数据库实时迁移和数据库实时同步的云服务。

3、RedisShake

RedisShake是由阿里云 NoSQL 团队开发的一款高性能的 Redis 数据迁移和同步工具。它主要用于在不同的 Redis 实例之间进行数据搬迁、在线流式同步、以及对 RDB 备份文件的解析与恢复。

4、Redis-full-check

Redis-full-check是由阿里云 NoSQL 团队开发的一款开源工具,用于比较两个 Redis 实例之间的数据是否一致。它通常用于数据迁移后的正确性校验,支持从 Redis 2.x 到 7.x 的多个版本(不支持 Redis Modules)。

5、compatibility-test

compatibility-test-suite-for-redis是一款开源工具,用来检测你的Redis-Like系统兼容到开源Redis的哪个版本(6.0还是7.0等)。

三、迁移方案

本章将系统解析迁移的全流程,深入探讨核心数据迁移与回滚的技术原理,并详细制定配套的数据校验策略。

1、迁移整体流程

整个 GeminiDB Redis 迁移过程将按照以下主要步骤进行,以确保数据完整性、业务连续性并最大程度降低风险:

  • 前置准备: 评估源和目标环境,包括网络连通性、资源规划、安全认证等,并部署 Redis-full-check 工具 和compatibility-test-suite-for-redis工具。

  • 版本选择与兼容性验证:在 Redis 核心版本选择时, Tair(兼容Redis)实例需要确保版本尽可能相同或更高 ,并利用 compatibility-test-suite-for-redis工具,验证 GeminiDB Redis 与 Tair(兼容Redis)实例之间的版本兼容性。

  • 数据库创建与配置: 在阿里云创建 Tair(兼容Redis)实例,确保其与源 GeminiDB Redis 实例版本兼容,并具有足够的资源承载迁移后的数据和流量。

  • 数据迁移:

    • 正向数据迁移: 将源 GeminiDB Redis 的全量和增量数据使用华为云数据传输服务 DRS 迁移至Tair(兼容Redis)实例。

    • 反向数据迁移: 在完成正向数据迁移后,将 Tair(兼容Redis)实例的增量数据使用阿里云数据传输服务 DTS 或 RedisShake 迁移至 GeminiDB Redis ,保持迁移后源数据的一致性,为回滚做好准备。

  • 数据校验: 在全量和增量数据同步稳定后,对源和目标 Redis 的数据一致性进行多维度校验,包括数据量、键值内容等。

  • 业务切换与验证: 将业务流量从源 GeminiDB Redis 平滑切换至目标 Tair(兼容Redis),并进行全面业务验证。

  • 旧环境清理与回滚计划: 确认新环境稳定运行后,逐步清理旧环境。同时,制定详细的回滚计划以应对可能出现的异常情况。

2、数据迁移方案

2.1、兼容性验证

验证原理:

compatibility-test-suite-for-redis 简称 ctsr 验证原理如下:

  • 模拟客户端行为: 模拟标准的 Redis 客户端,向被测系统(SUT)发送各种 Redis 命令。

  • 协议和命令验证: 验证 SUT 对 Redis 通信协议 (RESP) 的解析能力,以及对每个命令的响应是否符合预期。

  • 行为一致性对比: 将 SUT 的响应(返回值、数据类型、错误信息等)与一个已知行为正确的参考 Redis 实例的响应进行对比。

  • 数据结构和语义: 深入验证 SUT 对 Redis 各种数据结构(字符串、列表、哈希等)操作的正确性、命令的原子性、过期时间、事务、发布/订阅和 Lua 脚本等高级功能的行为是否与官方 Redis 一致。

  • 错误处理: 测试 SUT 在遇到无效命令、参数错误、类型错误等情况时,是否返回正确的错误信息。

前置条件:

ctsr使用 Python 编写, 测试机器上需要安装 Python 3.7+。

运行 ctsr 的机器需要能够通过网络连接到 GeminiDB Redis 和 Tair(兼容Redis)。

风险及注意项:

ctsr 会执行大量的写入操作(SETLPUSHHSET 等),并且通常会使用 FLUSHDB 或 FLUSHALL 命令来清理数据。如果在生产环境或包含重要数据的测试环境运行 ctsr,可能会导致生产数据被清空或覆盖。不应在生产环境或包含生产数据的测试环境直接运行 ctsr。 始终在隔离的、非生产的、一次性的测试环境(如开发机、CI/CD 管道中的临时容器、专用的测试虚拟机)中进行测试。

2.2、正向数据迁移

迁移原理:

使用华为云的数据复制工具 DRS 中的实时迁移功能,该功能支持将 GeminiDB Redis 的数据迁移至其他 Redis 服务中,实现数据从华为云 GeminiDB Redis 迁移至阿里云 Tair(兼容Redis)中。

前置条件:

GeminiDB Redis 内核版本需保证为 4.2.0 及以上。

使用迁移功能,需关闭通知过期事件的功能。

风险及注意项:

DRS 会在 GeminiDB Redis 中插入一个前缀为 DRS_REDIS_TIMESTAMP_HEARTBEAT 的 key 记录更新时间点,如果 GeminiDB Redis 为集群架构,DRS 会在源库各个 shard 上均插入该 key ,同步过程中会过滤该 key 。同步任务结束后,该 key 就会过期。增量过程中,该 key 值在源库存在,在目标库不存在,对比时应忽略此 key 。若实际业务中也存在前缀为 DRS_REDIS_TIMESTAMP_HEARTBEAT 的 key 值,可能导致数据不一致。

2.3、反向数据迁移

使用数据传输服务 DTS
迁移原理:

使用阿里云的数据迁移工具 DTS 中的数据迁移功能,该功能支持将 Tair(兼容Redis) 的数据迁移至其他 Redis 服务中,实现数据从阿里云 Tair(兼容Redis)迁移至华为云 GeminiDB Redis 中。但 DTS 无法直接开启增量模式,需要在源端新启动一个 GeminiDB Redis 来作为回滚实例,并使用 DTS 全量+增量进行反向数据迁移。

风险及注意项:

DTS 会在 Tair(兼容Redis) 中插入一个前缀为 DTS_REDIS_TIMESTAMP_HEARTBEAT 的 key 记录更新时间点,如果 Tair(兼容Redis)为集群架构,DRS 会在源库各个 shard 上均插入该 key ,同步过程中会过滤该 key 。同步任务结束后,该 key 就会过期。增量过程中,该 key 值在源库存在,在目标库不存在,对比时应忽略此 key 。若实际业务中也存在前缀为 DTS_REDIS_TIMESTAMP_HEARTBEAT 的 key 值,可能导致数据不一致。

使用RedisShake
迁移原理:

RedisShake 使用 Redis keyspace notifications 能力来订阅 Key 的变化。RedisShake 使用psubscribe命令订阅__keyevent@*__:* ,当 Key 发生变化时,使用 DUMPRESTORE 命令来从源端读取 Key 的内容,并写入目标端。

RedisShake介绍

风险及注意项:

Redis 中对于 RESTORE 命令有严格的限制,必须保证 Redis 版本一致。

DUMP 命令是 CPU 密集命令,会对源端造成较高压力。此阶段无法对 RedisShake 进行限速处理,需要小心使用,避免影响源端实例的可用性。

3、数据校验方案

3.1、使用 Redis-full-check 进行数据校验

Redis-full-check 通过全量对比源端和目的端的 Redis 中的数据的方式来进行数据校验,其比较方式通过多轮次比较:每次都会抓取源端和目的端的数据进行差异化比较,记录不一致的数据进入下轮对比(记录在sqlite3 db中)。然后通过多轮比较不断收敛,减少因数据增量同步导致的源库和目的库的数据不一致。最后 SQLite 中存在的数据就是最终的差异结果。

Redis-full-check对比的方向是单向:抓取源库 A 的数据,然后检测是否位于 B 中,反向不会检测,也就是说,它检测的是源库是否是目的库的子集。如果希望对比双向,则需要对比2次,第一次以 A 为源库,B 为目的库,第二次以 B 为源库,A 为目的库。

3.2、使用数据传输服务 DTS 进行数据校验

数据校验是数据传输服务 DTS 提供的用于监控源库与目标库数据差异的功能,支持在不停服的情况下对源库和目标库进行校验。任务运行过程中如果有不一致的数据,DTS会在一定时间之后对异常数据再次校验,确保该异常不是增量延迟所导致。

4、割接方案

本割接方案中使用华为云 DRS 进行正向同步,使用阿里云 DTS 进行反向同步和校验,使用Redis-full-check进行正向校验。

4.1、数据同步

阿里云 Tair(兼容Redis)设置白名单只允许华为云 DRS 同步链路 、阿里云 DTS 同步链路 和Redis-full-check 工具访问。建立华为云 GeminiDB Redis 到阿里云 Tair(兼容Redis)全量和增量的 DRS 同步链路。建立阿里云 Tair(兼容Redis)到华为云 GeminiDB Redis 回滚实例全量和增量的 DTS 同步链路。完成全量同步,并保持增量同步直至割接窗口。在割接窗口到来前使用Redis-full-check进行全量数据校验, 验证数据一致性。

4.2、数据割接

停止华为云 GeminiDB Redis 数据写入,观察华为云 DRS 同步链路无新增数据写入。使用Redis-full-check进行抽样数据校验,验证增量数据一致性。恢复阿里云 Tair(兼容Redis)白名单允许业务访问。业务切换至阿里云 Tair(兼容Redis,验证业务功能正常后,割接完成。阿里云 Tair(兼容Redis)到华为云 GeminiDB Redis 的 DTS 同步链路保持一段时间后,停止同步。

4.3、数据回滚

若验证业务功能异常,且无法短时间内修复时,停止阿里云 Tair(兼容Redis)数据写入, 观察 DTS 同步链路无新增数据写入。停止 DTS 同步链路,业务重新切换至华为云 GeminiDB Redis 运行。

四、迁移实施

1、兼容性验证

1.1、部署 compatibility-test 工具

获取工具工程。

git clone https://github.com/tair-opensource/compatibility-test-suite-for-redis.git
cd compatibility-test-suite-for-redis

安装依赖,要求Python 3.7及以上版本。

pip3 install -r requirements.txt

测试的命令及其对应的版本信息可参考此表

1.2、运行 compatibility-test 工具

测试参数说明如下:

optional arguments:
  -h, --help            show this help message and exit
  --host HOST           the redis host
  --port PORT           the redis port
  --password PASSWORD   the redis password
  --testfile TESTFILE   the redis compatibility test cases
  --specific-version {1.0.0,2.8.0,3.2.0,4.0.0,5.0.0,6.0.0,6.2.0,7.0.0,7.2.0}
                        the redis version
  --show-failed         show details of failed tests
  --cluster             server is a node of the Redis cluster
  --ssl                 open ssl connection
  --genhtml             generate test report in html format

命令示例:

python3 redis_compatibility_test.py --host 192.168.XX.XX --port 6379 --password Qwer***** --testfile cts.json --specific-version 6.2.0 

2、正向数据迁移

可参考华为云 DRS 操作文档。

3、反向数据迁移

可参考阿里云 DTS 操作文档。

迁移方案概览

4、数据校验

4.1、 使用 Redis-full-check 进行数据校验

部署 Redis-full-check 工具
wget https://github.com/tair-opensource/RedisFullCheck/releases/download/release-v1.4.8-20200212/redis-full-check-1.4.8.tar.gz
tar -zxcf redis-full-check-1.4.8.tar.gz 
cd redis-full-check-1.4.8/
运行 Redis-full-check 工具

参数说明

  -s, --source=SOURCE               源redis库地址(ip:port),如果是集群版,那么需要以分号(;)分割不同的db,只需要配置主或者从的其中之一。例如:10.1.1.1:1000;10.2.2.2:2000;10.3.3.3:3000。
  -p, --sourcepassword=Password     源redis库密码
      --sourceauthtype=AUTH-TYPE    源库管理权限,开源reids下此参数无用。
      --sourcedbtype=               源库的类别,0:db(standalone单节点、主从),1: cluster(集群版),2: 阿里云
      --sourcedbfilterlist=         源库需要抓取的逻辑db白名单,以分号(;)分割,例如:0;5;15表示db0,db5和db15都会被抓取
  -t, --target=TARGET               目的redis库地址(ip:port)
  -a, --targetpassword=Password     目的redis库密码
      --targetauthtype=AUTH-TYPE    目的库管理权限,开源reids下此参数无用。
      --targetdbtype=               参考sourcedbtype
      --targetdbfilterlist=         参考sourcedbfilterlist
  -d, --db=Sqlite3-DB-FILE          对于差异的key存储的sqlite3 db的位置,默认result.db
      --comparetimes=COUNT          比较轮数
  -m, --comparemode=                比较模式,1表示全量比较,2表示只对比value的长度,3只对比key是否存在,4全量比较的情况下,忽略大key的比较
      --id=                         用于打metric
      --jobid=                      用于打metric
      --taskid=                     用于打metric
  -q, --qps=                        qps限速阈值
      --interval=Second             每轮之间的时间间隔
      --batchcount=COUNT            批量聚合的数量
      --parallel=COUNT              比较的并发协程数,默认5
      --log=FILE                    log文件
      --result=FILE                 不一致结果记录到result文件中,格式:'db    diff-type    key    field'
      --metric=FILE                 metric文件
      --bigkeythreshold=COUNT       大key拆分的阈值,用于comparemode=4
  -f, --filterlist=FILTER           需要比较的key列表,以分号(;)分割。例如:"abc*|efg|m*"表示对比'abc', 'abc1', 'efg', 'm', 'mxyz',不对比'efgh', 'p'。
  -v, --version

运行示例

例如:源 Redis 库是 113.47.XX.XX:6379 ,目标库是 r-bp1dql854dakxxxxxx.redis.rds.aliyuncs.com:6379

./redis-full-check -s 113.47.XX.XX:6379 -p mock_source_password -t r-bp1dql854dakxxxxxx.redis.rds.aliyuncs.com:6379 -a mock_target_password --comparemode=1 --comparetimes=1 --log log --result result

执行结果将持久化至 SQLite3 数据库文件中。若未指定路径,系统默认在当前工作目录生成 result.db.<N> 文件(N 代表比较轮次)。
数据库内部设计包含:

  • 主表 (key):汇总不一致的键名。

  • 详情表 (field):详细记录 Hash、Set、ZSet 的成员或 List 索引的不一致信息,并使用 key_id 外键与主表关联。

  • 过程表(key_<N>field_<N>):用于存放各迭代轮次的中间比对状态,便于追溯。

结果示例

[ecs-assist-user@iZbp1daxq5tl4bibxxxxxx redis-full-check-1.4.8]$ sqlite3 result.db.1
SQLite version 3.26.0 2018-12-01 12:34:55
Enter ".help" for usage hints.
sqlite> .headers on
sqlite> .mode column
sqlite> select * from key;
id          key         type        conflict_type  db          source_len  target_len
----------  ----------  ----------  -------------  ----------  ----------  ----------
1           user:1006   string      value          0           11          9         
2           user:1001   string      value          0           11          9         
3           user:1010   string      value          0           11          9         
4           user:1008   string      value          0           11          9         
5           user:1009   string      value          0           11          9         
6           user:1004   string      value          0           11          9         
7           user:1005   string      value          0           11          9         
8           user:1007   string      value          0           11          9         
9           user:1002   string      value          0           11          9         
10          user:1011   string      lack_target    0           11          0         
11          user:1003   string      value          0           11          9         
12          user:1002   string      lack_target    1           11          0         
13          user:1008   string      lack_target    1           11          0         
14          user:1003   string      lack_target    1           11          0         
15          user:1006   string      lack_target    1           11          0         
16          user:1007   string      lack_target    1           11          0         
17          user:1004   string      lack_target    1           11          0         
18          user:1005   string      lack_target    1           11          0         
19          user:1009   string      lack_target    1           11          0         
20          user:1011   string      lack_target    1           11          0         
21          user:1010   string      lack_target    1           11          0         
22          user:1001   string      lack_target    1           11          0         
23          user:1006   string      lack_target    2           11          0         
24          user:1003   string      lack_target    2           11          0         
25          user:1010   string      lack_target    2           11          0         
26          user:1011   string      lack_target    2           11          0         
27          user:1007   string      lack_target    2           11          0         
28          user:1002   string      lack_target    2           11          0         
29          user:1001   string      lack_target    2           11          0         
30          user:1004   string      lack_target    2           11          0         
31          user:1005   string      lack_target    2           11          0         
32          user:1009   string      lack_target    2           11          0         
33          user:1008   string      lack_target    2           11          0         
sqlite> .exit 

4.2、使用阿里云数据传输服务 DTS 进行数据校验

在使用阿里云数据传输服务 DTS 进行数据迁移时, 我们已经勾选数据校验任务,之后在数据迁移任务中查询数据校验结果即可。

五、迁移注意事项

1、存储类型

华为云 GeminiDB Redis 使用内存和 SSD 混合存储类型,Tair(兼容Redis)已逐步放弃此方案。选用内存存储类型,可能会带来成本的上升。

2、Bitmap 使用方式

华为云 GeminiDB Redis 对于 Bitmap 进行了特殊优化,可以使其作为普通 String 进行快速 APPEND 操作。若您使用了此特性,迁移到 Tair(兼容Redis) 前必须修改代码,改用 SETBIT 等标准命令。