自建 Redis 迁移到阿里云自建 Redis 方案

一、适用场景

本方案适用于将其他云厂商、本地数据中心 (IDC) 或其他环境下的自建 Redis 数据库,平滑、高效地迁移至阿里云 ECS 上部署的自建 Redis 数据库实例。

迁移类型涵盖:

  • 全量数据迁移: 将源 Redis 数据库中的全部存量数据迁移至目标 Redis 实例。

  • 增量数据迁移: 在全量数据迁移完成后,持续同步源 Redis 数据库中产生的实时增量数据,确保源和目标数据保持一致,为业务平滑切换做准备。

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

二、迁移相关工具介绍

本方案主要依赖以下工具完成 Redis 数据的迁移与校验:

1、Redis-shake

RedisShake 是一个由阿里巴巴开源的,专门用于处理和迁移 Redis 数据的强大工具。它具备以下关键特性,使其成为本方案的核心:

  • 数据迁移能力: 支持将 Redis 数据从一个实例迁移到另一个实例,实现全量及增量数据同步。

  • 广泛兼容性: 兼容 Redis 2.8 至 7.2 版本,并支持单机、主从、哨兵和集群等多种部署方式。

  • 云服务兼容性: 与阿里云云数据库 Redis 版、阿里云云原生内存数据库 Tair 等主流云 Redis 服务无缝工作。

  • 多种导出模式: 提供 PSync、RDB 和 Scan 等多种数据导出模式,以适应不同源端环境和迁移需求。

  • 数据处理能力: 支持通过自定义脚本实现数据过滤和转换,满足特定业务需求。

2、Redis-cli 或自定义脚本

Redis-cli 是 Redis 官方提供的命令行客户端工具,可用于连接 Redis 实例并执行各类 Redis 命令。在数据校验阶段,它将用于执行 INFO keyspace 等命令,获取数据库键空间信息,辅助进行数据量对比。 对于更复杂的数据内容校验或大规模键值的对比,可能需要开发自定义脚本来自动化此过程。

三、迁移方案

本章节将详细阐述迁移的整体流程、核心的数据迁移原理及方案,以及数据校验的策略。

1、迁移整体流程

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

  • 前置准备: 评估源和目标环境,包括网络连通性、资源规划、版本兼容性、安全认证等,并部署 RedisShake 工具。

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

  • 数据迁移: 利用 RedisShake 工具,分阶段进行全量数据迁移和增量数据同步。

    • 全量数据迁移: 将源 Redis 的存量数据一次性迁移到目标 Redis。

    • 增量数据迁移: 在全量迁移过程中及完成后,持续捕获源 Redis 的数据变更并同步到目标 Redis,保持两端数据一致。

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

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

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

2、数据迁移方案

本方案核心是利用 RedisShake 实现数据的高效、可靠迁移。

2.1、使用 Redis-shake 进行数据迁移

迁移原理:

RedisShake 支持多种迁移模式,其中:

  1. PSync 模式 (sync_reader):

    • 原理: 当源端 Redis 兼容 PSync 协议时,RedisShake 优先推荐使用此模式。RedisShake 模拟一个 Redis Slave 连接到源端 Redis Master。Master 会向 RedisShake 发送数据,包括一个 RDB 快照(用于全量数据同步)和一个 AOF 数据流(用于增量数据同步)。

      • 全量同步阶段: RedisShake 解析接收到的 RDB 文件,将其转换为一系列 Redis 命令,并发送至目标 Redis。

      • 增量同步阶段: RedisShake 持续接收并解析 AOF 数据流中的增量命令,实时同步至目标 Redis。

    • 优势: 数据一致性最佳,对源库影响小,可以实现不停机切换。这是本方案推荐的首选模式。

  2. SCAN 模式 (scan_reader):

    • 原理: 当源端不兼容 PSync 协议(或存在其他限制导致 PSync 无法使用)时,可考虑使用此模式。

      • 全量同步 (SCAN 阶段): RedisShake 通过 SCAN 命令遍历源端数据库中的所有 Key,然后使用 DUMP 命令获取每个 Key 对应的 Value,并通过 RESTORE 命令写入目标端。

      • 增量同步 (KSN 阶段): 可选择开启 KSN (Keyspace Notifications) 机制。RedisShake 订阅源端 Redis 的 Keyspace Notifications,当 Key 发生变化时,RedisShake 会收到通知,再使用 DUMPRESTORE 命令同步这些变更。

    • 劣势: DUMP 命令是 CPU 密集型操作,SCAN 模式会对源库造成较大压力,可能影响源库的可用性。且 KSN 模式不感知 FLUSHALLFLUSHDB 命令,在源端有此类操作时可能导致数据不一致。

前置条件:

为确保 RedisShake 顺利运行和数据迁移的成功,需要满足以下前置条件:

  1. 网络连通性:

    • 部署 RedisShake 的服务器需要与源 Redis 实例和目标 Redis 实例之间具备稳定的网络连通性。确保防火墙规则已放行相关端口(默认为 6379)。

  2. 源 Redis 实例:

    • 版本兼容性: 源 Redis 版本需在 RedisShake 支持范围内(2.8-7.2)。建议目标 Redis 版本大于等于源 Redis 版本。

    • 认证信息: 如果源 Redis 配置了密码或 ACL 用户,需提供正确的认证信息给 RedisShake。

    • PSync 相关配置(sync_reader 模式): 确保源 Redis Master 的 client-output-buffer-limit replica 参数设置足够大,以避免连接因缓冲区溢出而被断开。

    • Keyspace Notifications 配置(scan_reader + KSN 模式): 如果计划使用 scan_reader 的 KSN 增量同步,需在源 Redis 中手动开启 notify-keyspace-events 配置,并确保值中含有 AE

  3. 目标 Redis 实例:

    • 版本兼容性: 目标 Redis 版本应大于或等于源 Redis 版本,以避免新命令或编码方式不兼容的问题。

    • 资源充足: 目标 Redis 实例需要有足够的内存、CPU 和网络带宽来承载迁移后的数据和业务流量。

    • 认证信息: 如果目标 Redis 配置了密码或 ACL 用户,需提供正确的认证信息给 RedisShake。

  4. RedisShake 部署环境:

    • 部署 RedisShake 的 ECS 实例应具备足够的 CPU、内存和磁盘空间(用于暂存 RDB 文件),尤其是在处理大量数据时。

    • 操作系统环境应支持 Golang 运行(如果选择从源代码编译)或直接运行提供的二进制文件。

风险及注意项:
  1. 版本降级风险: 切勿将数据从高版本 Redis 迁移到低版本 Redis。RedisShake 明确指出,降低 Redis 版本可能导致不兼容,因为每个大版本都可能引入新的命令或编码方式。应始终保证目标 Redis 版本大于等于源 Redis 版本。

  2. SCAN 模式的性能影响: 如果采用 scan_reader 模式,DUMP 命令是 CPU 密集型操作,可能会对源 Redis 实例造成显著的 CPU 压力,影响其正常服务。在生产环境中需谨慎评估并选择在业务低峰期执行,或通过调整 count 参数逐步增加压力。

  3. RedisShake 资源占用: RedisShake 在运行时会产生临时文件,尤其是在 PSync 模式下暂存 RDB 文件。确保部署 RedisShake 的机器有足够的磁盘空间。同时,不建议在同一个目录下运行两个 RedisShake 进程,以免临时文件被覆盖导致异常行为。

  4. 网络稳定性: 迁移过程中,源 Redis、RedisShake 和目标 Redis 之间的网络连接必须稳定。网络波动或中断可能导致迁移失败或数据不一致。

  5. 过期键处理: Redis 的过期键机制具有随机性。源端和目标端各自独立的过期算法可能导致迁移后带有过期时间的 Key 数量不完全一致。在数据校验时,应特别注意区分带有过期时间和不带有过期时间的 Key 数量,通常认为带有过期时间的 Key 允许一定程度的不一致。

  6. PSync 模式与 Sentinel 的注意事项: 如果源 Redis 由 Sentinel 纳管,当使用 sync_reader 连接其 Master 节点时,RedisShake 可能被 Sentinel 当作 Slave 节点,引发非预期问题。建议此场景下尽量选择连接备用 Slave 节点作为源端进行同步。

  7. client-output-buffer-limit 参数: 对于 PSync 模式,若源端 RedisShark 连接被断开,多是因为源端 client-output-buffer-limit replica 参数设置过小,建议适当调高。对于 KSN 模式,若出现连接断开,可能需要调高 client-output-buffer-limit pubsub 的值。

3、数据校验方案

数据校验是迁移成功的关键步骤,它确保源端和目标端的数据在迁移后达到一致。

  1. 数量校验:

    • 目标: 验证源 Redis 和目标 Redis 中 Key 的总数量以及带有过期时间的 Key 数量是否一致。

    • 方法: 使用 INFO keyspace 命令获取每个数据库(db0, db1等)的键空间信息,比较 dbX:keysdbX:expires 的值。

    • 注意事项: 由于 Redis 过期算法的随机性,以及可能存在的已过期但未被删除的 Key,dbX:expires 的值在源和目标之间可能存在轻微差异。更准确的校验方法是比较 $keys - $expires 的值,即非过期 Key 的数量是否一致。

  2. 内容校验(抽样):

    • 目标: 随机抽取一部分 Key,比较它们在源 Redis 和目标 Redis 中的值是否完全一致。

    • 方法:

      • 使用 SCAN 命令在源端随机获取一定数量的 Key。

      • 对这些 Key,分别在源端和目标端使用 TYPETTLGET (String)、LRANGE (List)、SMEMBERS (Set)、HGETALL (Hash)、ZRANGE (ZSet) 等命令获取其类型、过期时间及内容。

      • 逐一比对获取到的信息。

    • 工具: 可以编写自定义脚本来自动化此过程,提高效率和准确性。对于海量数据,完全内容校验成本极高,通常采用抽样校验结合业务验证的方式。

  3. 业务侧校验:

    • 目标: 在切换流量前或小流量灰度期间,通过业务应用程序实际读写目标 Redis 实例,验证业务逻辑和数据操作的正确性。

    • 方法:

      • 部署一套测试应用,连接目标 Redis,模拟核心业务流程。

      • 观察应用日志和性能指标,确保无异常。

      • (可选)进行小范围灰度发布,将少量真实用户流量切换至目标 Redis,进一步观察。

四、实施迁移过程

本章节详细描述使用 RedisShake 进行数据迁移的具体操作步骤。

1、使用 Redis-shake 进行数据迁移

此步骤假设您已经完成了前置准备工作,包括阿里云 ECS 实例的创建、目标 Redis 的部署与配置,以及 RedisShake 工具的下载与部署。

1.1、部署 RedisShake 工具

  1. 下载二进制包: 访问 RedisShake 的 GitHub Release 页面 (https://github.com/alibaba/RedisShake/releases) 下载最新版本的 RedisShake 二进制包,选择适用于您的 ECS 实例操作系统的版本(如 redis-shake-linux-amd64.tar.gz)。

  2. 解压并放置: 将下载的压缩包上传到您的 ECS 实例,并解压到一个独立的目录,例如 /opt/redis-shake注意: 确保不要在同一个目录下运行两个 RedisShake 进程,这会导致运行时产生的临时文件被覆盖。

1.2、创建 RedisShake 配置文件

/opt/redis-shake 目录下创建一个名为 shake.toml 的配置文件,并根据您的源 Redis 和目标 Redis 配置进行修改。以下是一个典型的 shake.toml 示例,使用 sync_reader 模式。

# shake.toml

[sync_reader]
# 源 Redis 配置
cluster = false            # 如果源 Redis 是集群模式,设置为 true;单机或主从模式设置为 false
address = "源Redis_IP地址:端口" # 例如: "192.168.1.100:6379";集群模式下填写任意一个节点地址即可
username = ""              # 如果源 Redis 使用 ACL 账号,填写用户名;否则留空
password = "源Redis_密码" # 如果源 Redis 有密码,填写密码;否则留空
tls = false                # 如果源 Redis 开启了 TLS/SSL,设置为 true;否则设置为 false
sync_rdb = true            # 开启 RDB 全量同步
sync_aof = true            # 开启 AOF 增量同步

# [sync_reader.sentinel] # 如果源 Redis 受 Sentinel 监控且希望通过 Sentinel 获取 Master 地址
# master_name = "mymaster"
# address = "127.0.0.1:26380" # Sentinel 地址
# username = ""
# password = ""
# tls = false

[redis_writer]
# 目标 Redis 配置 (阿里云 ECS 自建 Redis)
cluster = false            # 如果目标 Redis 是集群模式,设置为 true;单机或主从模式设置为 false
address = "目标Redis_IP地址:端口" # 例如: "10.0.0.10:6379";集群模式下填写任意一个节点地址即可
username = ""              # 如果目标 Redis 使用 ACL 账号,填写用户名;否则留空
password = "目标Redis_密码" # 如果目标 Redis 有密码,填写密码;否则留空
tls = false                # 如果目标 Redis 开启了 TLS/SSL,设置为 true;否则设置为 false

[filter]
# 示例:过滤掉以 "test:" 开头的键
# type = "lua"
# args = """
# function filter(cmd)
#     if string.sub(cmd[2], 1, 5) == "test:" then
#         return false
#     end
#     return true
# end
# """

[advanced]
# max_commands_per_second = 0 # 限制每秒写入命令数,0表示不限制
# rps = 0 # 每秒同步的命令数量限制
# source_db = 0 # 源端 Redis 数据库索引,默认0,可指定
# target_db = 0 # 目标端 Redis 数据库索引,默认0,可指定
# network_timeout = 5 # 网络超时时间 (秒)
# temp_file_compaction = true # 压缩临时文件以节省磁盘空间

配置说明:

  • Redis_IP地址:端口Redis_密码 替换为您的源 Redis 实际连接信息。

  • 目标Redis_IP地址:端口目标Redis_密码 替换为您的阿里云 ECS 上目标 Redis 的实际连接信息。

  • 根据实际情况调整 clusterusernametls 等参数。

  • 如果源 Redis 由 Sentinel 纳管,且您希望通过 Sentinel 发现 Master 地址,可以取消 [sync_reader.sentinel] 段的注释并配置。但请注意,使用 sync_reader 连接被 Sentinel 接管的 Redis Master 时,RedisShake 可能被 Sentinel 当做 Slave,建议尽量选择连接备库作为源端。

  • filteradvanced 段提供了高级功能,可根据需求选择性配置。

1.3、启动 RedisShake 进行数据迁移

shake.toml 配置文件所在的目录,运行以下命令启动 RedisShake:

./redis-shake shake.toml

启动后,RedisShake 会开始执行数据迁移。您可以通过观察命令行输出的日志来监控迁移进度。

监控迁移进度:

  • 命令行输出: RedisShake 会实时打印日志,显示连接状态、RDB 同步进度(RDB dump finished 表示全量完成)、以及增量 AOF 同步的流量信息。

  • 文件日志: 默认情况下,RedisShake 也会将日志写入到当前目录下的 shake.log 文件。

  • 进程状态: 可以使用 ps -ef | grep redis-shake 查看 RedisShake 进程是否正常运行。

  • 目标 Redis 监控: 观察目标 Redis 实例的内存使用、Key 数量、QPS 等指标,以确认数据正在被写入。

当日志显示 RDB dump finished 后,表示全量数据已同步完成,RedisShake 将进入增量同步阶段。此时,您可以开始准备进行数据校验。

五、数据校验过程

在 RedisShake 完成全量数据同步并进入增量同步阶段后,应立即着手进行数据校验。

1、数量校验

使用 redis-cli 连接源 Redis 和目标 Redis,分别执行 INFO keyspace 命令,比较返回的键空间信息。

  1. 连接源 Redis 并获取信息:

redis-cli -h 源Redis_IP地址 -p 源Redis_端口 -a 源Redis_密码 INFO keyspace

示例输出:

# Keyspace
db0:keys=4463175,expires=2,avg_ttl=333486
db1:keys=1000,expires=0,avg_ttl=0

记录下每个 DB 的 keysexpires 值。

  1. 连接目标 Redis 并获取信息:

redis-cli -h 目标Redis_IP地址 -p 目标Redis_端口 -a 目标Redis_密码 INFO keyspace

记录下每个 DB 的 keysexpires 值。

  1. 比较分析:

    • 非过期键数量: 对于每个 DB,计算 keys - expires 的值。理论上,源和目标 Redis 的非过期键数量应该完全一致。

    • 过期键数量: expires 字段表示有过期时间的 Key 数量。由于 Redis 过期策略的随机性,这个值在源和目标之间可能存在细微差异。如果差异很小且业务允许,通常可以接受。如果差异较大,则需要进一步排查。

2、内容校验(抽样验证)

为了验证 Key 的内容是否一致,可以随机抽取 Key 进行详细对比。

  1. 从源 Redis 随机抽取 Key: 使用 SCAN 命令遍历源 Redis,并结合脚本随机选择一部分 Key。 例如,每次 SCAN 返回 100 个 Key,随机挑选其中 10 个。

# 示例:获取db0的Key
redis-cli -h 源Redis_IP -p 源Redis_端口 -a 源Redis_密码 SCAN 0 COUNT 100

重复执行 SCAN 命令,直到获取到足够数量的样本 Key。

  1. 逐一对比 Key 内容: 对于每个抽取的 Key:

    • 获取类型和 TTL:确认 Key 类型一致,且 TTL 接近(会有毫秒级误差)。

    • 获取值并对比: 根据 Key 的类型使用对应的命令获取其值,并在源和目标之间进行字节级或逻辑上的对比。

      • String: GET <key_name>

      • Hash: HGETALL <key_name>

      • List: LRANGE <key_name> 0 -1

      • Set: SMEMBERS <key_name>

      • ZSet: ZRANGE <key_name> 0 -1 WITHSCORES

建议: 编写一个简单的脚本(如 Python、Shell)来自动化抽样、获取数据和对比的过程,以提高效率和准确性。

3、业务侧校验

在确认数据一致性后,进行业务侧校验是最终和最重要的验证环节。

  1. 应用程序连接切换:

    • 将部分或全部业务应用程序的 Redis 连接配置从源 Redis 切换到目标 Redis 的连接地址和认证信息。

    • 建议先进行小流量或测试环境的切换,确保业务功能正常。

  2. 核心业务流程验证:

    • 执行业务系统的核心读写操作,模拟用户行为,例如用户登录、数据查询、数据写入、订单创建等。

    • 监控应用程序的错误日志和性能指标(如响应时间、吞吐量),确保在连接目标 Redis 后,业务功能正常且性能达标。

  3. 数据回写验证:

    • 如果有业务数据会写入 Redis,确保写入目标 Redis 的数据能够被正确存储和读取。

    • 在业务写入后,可以再次执行抽样校验,验证新写入的数据在目标 Redis 中是否正确。

六、迁移注意事项

在整个 Redis 迁移过程中,需要特别关注以下事项,以确保迁移的平稳和成功:

  • 版本兼容性: 始终确保目标 Redis 实例的版本大于或等于源 Redis 实例的版本。避免从高版本向低版本迁移数据,这可能导致数据编码或命令不兼容问题。

  • 资源规划:

    • RedisShake 机器: 预留足够的 CPU、内存和磁盘空间给 RedisShake 进程,特别是对于大型数据集的迁移。磁盘空间用于暂存 RDB 文件。

    • 目标 Redis 实例: 确保阿里云 ECS 上的目标 Redis 实例配置了足够的内存(能容纳全部数据并留有余量)、CPU 和网络带宽,以应对迁移期间和迁移后的峰值负载。

  • 网络带宽与延迟:

    • 源 Redis、RedisShake 和目标 Redis 之间的网络带宽是影响迁移速度的关键因素。确保足够的带宽来支持数据传输。

    • 低网络延迟有助于减少数据同步的延时,提高实时性。

  • 源库压力评估:

    • 使用 sync_reader (PSync) 模式对源库影响较小,但仍需监控源库的 CPU、内存和网络 I/O。

    • 如果不得不使用 scan_reader 模式,DUMP 操作会消耗大量 CPU。务必在业务低峰期进行全量同步,并通过调整 count 参数来控制对源库的压力。

  • 数据一致性:

    • sync_reader 模式在数据一致性方面表现最佳,可以最大限度保证数据完整性。

    • 注意带有过期时间的 Key 在源和目标之间可能出现数量上的微小差异,这是 Redis 过期策略的特性,通常可以接受。

  • 业务停机时间:

    • 采用 PSync 模式可以实现不停机或极短时间停机的迁移,将业务切换窗口控制在秒级。

    • 提前与业务方沟通,确定可接受的业务中断时长,并选择合适的切换时机(如业务低峰期)。

  • 监控与告警:

    • 在迁移全程,务必对源 Redis、RedisShake 进程、目标 Redis 以及相关的业务应用程序进行实时监控。

    • 配置关键指标的告警(如 CPU 利用率、内存使用、网络流量、Redis 连接数、QPS、错误日志),以便及时发现并处理异常。

  • 回滚计划:

    • 制定详细的回滚计划至关重要。包括但不限于:

      • 如何快速将业务流量切换回源 Redis。

      • 如何处理回滚过程中产生的新数据(可能需要逆向同步或重新同步)。

    • 在迁移前,确保回滚路径是可操作且经过验证的。

  • 配置文件管理: 妥善保管 RedisShake 的配置文件 shake.toml,避免敏感信息泄露。

  • 日志分析: 密切关注 RedisShake 的运行日志,它可以提供详细的迁移状态、潜在问题和错误信息,是排查故障的重要依据。