一、适用场景
本方案适用于将其他云厂商、本地数据中心 (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 支持多种迁移模式,其中:
PSync 模式 (sync_reader):
原理: 当源端 Redis 兼容 PSync 协议时,RedisShake 优先推荐使用此模式。RedisShake 模拟一个 Redis Slave 连接到源端 Redis Master。Master 会向 RedisShake 发送数据,包括一个 RDB 快照(用于全量数据同步)和一个 AOF 数据流(用于增量数据同步)。
全量同步阶段: RedisShake 解析接收到的 RDB 文件,将其转换为一系列 Redis 命令,并发送至目标 Redis。
增量同步阶段: RedisShake 持续接收并解析 AOF 数据流中的增量命令,实时同步至目标 Redis。
优势: 数据一致性最佳,对源库影响小,可以实现不停机切换。这是本方案推荐的首选模式。
SCAN 模式 (scan_reader):
原理: 当源端不兼容 PSync 协议(或存在其他限制导致 PSync 无法使用)时,可考虑使用此模式。
全量同步 (SCAN 阶段): RedisShake 通过
SCAN
命令遍历源端数据库中的所有 Key,然后使用DUMP
命令获取每个 Key 对应的 Value,并通过RESTORE
命令写入目标端。增量同步 (KSN 阶段): 可选择开启
KSN
(Keyspace Notifications) 机制。RedisShake 订阅源端 Redis 的 Keyspace Notifications,当 Key 发生变化时,RedisShake 会收到通知,再使用DUMP
和RESTORE
命令同步这些变更。
劣势:
DUMP
命令是 CPU 密集型操作,SCAN
模式会对源库造成较大压力,可能影响源库的可用性。且KSN
模式不感知FLUSHALL
和FLUSHDB
命令,在源端有此类操作时可能导致数据不一致。
前置条件:
为确保 RedisShake 顺利运行和数据迁移的成功,需要满足以下前置条件:
网络连通性:
部署 RedisShake 的服务器需要与源 Redis 实例和目标 Redis 实例之间具备稳定的网络连通性。确保防火墙规则已放行相关端口(默认为 6379)。
源 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
。
目标 Redis 实例:
版本兼容性: 目标 Redis 版本应大于或等于源 Redis 版本,以避免新命令或编码方式不兼容的问题。
资源充足: 目标 Redis 实例需要有足够的内存、CPU 和网络带宽来承载迁移后的数据和业务流量。
认证信息: 如果目标 Redis 配置了密码或 ACL 用户,需提供正确的认证信息给 RedisShake。
RedisShake 部署环境:
部署 RedisShake 的 ECS 实例应具备足够的 CPU、内存和磁盘空间(用于暂存 RDB 文件),尤其是在处理大量数据时。
操作系统环境应支持 Golang 运行(如果选择从源代码编译)或直接运行提供的二进制文件。
风险及注意项:
版本降级风险: 切勿将数据从高版本 Redis 迁移到低版本 Redis。RedisShake 明确指出,降低 Redis 版本可能导致不兼容,因为每个大版本都可能引入新的命令或编码方式。应始终保证目标 Redis 版本大于等于源 Redis 版本。
SCAN 模式的性能影响: 如果采用
scan_reader
模式,DUMP
命令是 CPU 密集型操作,可能会对源 Redis 实例造成显著的 CPU 压力,影响其正常服务。在生产环境中需谨慎评估并选择在业务低峰期执行,或通过调整count
参数逐步增加压力。RedisShake 资源占用: RedisShake 在运行时会产生临时文件,尤其是在 PSync 模式下暂存 RDB 文件。确保部署 RedisShake 的机器有足够的磁盘空间。同时,不建议在同一个目录下运行两个 RedisShake 进程,以免临时文件被覆盖导致异常行为。
网络稳定性: 迁移过程中,源 Redis、RedisShake 和目标 Redis 之间的网络连接必须稳定。网络波动或中断可能导致迁移失败或数据不一致。
过期键处理: Redis 的过期键机制具有随机性。源端和目标端各自独立的过期算法可能导致迁移后带有过期时间的 Key 数量不完全一致。在数据校验时,应特别注意区分带有过期时间和不带有过期时间的 Key 数量,通常认为带有过期时间的 Key 允许一定程度的不一致。
PSync 模式与 Sentinel 的注意事项: 如果源 Redis 由 Sentinel 纳管,当使用
sync_reader
连接其 Master 节点时,RedisShake 可能被 Sentinel 当作 Slave 节点,引发非预期问题。建议此场景下尽量选择连接备用 Slave 节点作为源端进行同步。client-output-buffer-limit
参数: 对于 PSync 模式,若源端 RedisShark 连接被断开,多是因为源端client-output-buffer-limit replica
参数设置过小,建议适当调高。对于 KSN 模式,若出现连接断开,可能需要调高client-output-buffer-limit pubsub
的值。
3、数据校验方案
数据校验是迁移成功的关键步骤,它确保源端和目标端的数据在迁移后达到一致。
数量校验:
目标: 验证源 Redis 和目标 Redis 中 Key 的总数量以及带有过期时间的 Key 数量是否一致。
方法: 使用
INFO keyspace
命令获取每个数据库(db0, db1等)的键空间信息,比较dbX:keys
和dbX:expires
的值。注意事项: 由于 Redis 过期算法的随机性,以及可能存在的已过期但未被删除的 Key,
dbX:expires
的值在源和目标之间可能存在轻微差异。更准确的校验方法是比较$keys - $expires
的值,即非过期 Key 的数量是否一致。
内容校验(抽样):
目标: 随机抽取一部分 Key,比较它们在源 Redis 和目标 Redis 中的值是否完全一致。
方法:
使用
SCAN
命令在源端随机获取一定数量的 Key。对这些 Key,分别在源端和目标端使用
TYPE
、TTL
、GET
(String)、LRANGE
(List)、SMEMBERS
(Set)、HGETALL
(Hash)、ZRANGE
(ZSet) 等命令获取其类型、过期时间及内容。逐一比对获取到的信息。
工具: 可以编写自定义脚本来自动化此过程,提高效率和准确性。对于海量数据,完全内容校验成本极高,通常采用抽样校验结合业务验证的方式。
业务侧校验:
目标: 在切换流量前或小流量灰度期间,通过业务应用程序实际读写目标 Redis 实例,验证业务逻辑和数据操作的正确性。
方法:
部署一套测试应用,连接目标 Redis,模拟核心业务流程。
观察应用日志和性能指标,确保无异常。
(可选)进行小范围灰度发布,将少量真实用户流量切换至目标 Redis,进一步观察。
四、实施迁移过程
本章节详细描述使用 RedisShake 进行数据迁移的具体操作步骤。
1、使用 Redis-shake 进行数据迁移
此步骤假设您已经完成了前置准备工作,包括阿里云 ECS 实例的创建、目标 Redis 的部署与配置,以及 RedisShake 工具的下载与部署。
1.1、部署 RedisShake 工具
下载二进制包: 访问 RedisShake 的 GitHub Release 页面 (https://github.com/alibaba/RedisShake/releases) 下载最新版本的 RedisShake 二进制包,选择适用于您的 ECS 实例操作系统的版本(如
redis-shake-linux-amd64.tar.gz
)。解压并放置: 将下载的压缩包上传到您的 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 的实际连接信息。根据实际情况调整
cluster
、username
、tls
等参数。如果源 Redis 由 Sentinel 纳管,且您希望通过 Sentinel 发现 Master 地址,可以取消
[sync_reader.sentinel]
段的注释并配置。但请注意,使用sync_reader
连接被 Sentinel 接管的 Redis Master 时,RedisShake 可能被 Sentinel 当做 Slave,建议尽量选择连接备库作为源端。filter
和advanced
段提供了高级功能,可根据需求选择性配置。
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
命令,比较返回的键空间信息。
连接源 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 的 keys
和 expires
值。
连接目标 Redis 并获取信息:
redis-cli -h 目标Redis_IP地址 -p 目标Redis_端口 -a 目标Redis_密码 INFO keyspace
记录下每个 DB 的 keys
和 expires
值。
比较分析:
非过期键数量: 对于每个 DB,计算
keys - expires
的值。理论上,源和目标 Redis 的非过期键数量应该完全一致。过期键数量:
expires
字段表示有过期时间的 Key 数量。由于 Redis 过期策略的随机性,这个值在源和目标之间可能存在细微差异。如果差异很小且业务允许,通常可以接受。如果差异较大,则需要进一步排查。
2、内容校验(抽样验证)
为了验证 Key 的内容是否一致,可以随机抽取 Key 进行详细对比。
从源 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。
逐一对比 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、业务侧校验
在确认数据一致性后,进行业务侧校验是最终和最重要的验证环节。
应用程序连接切换:
将部分或全部业务应用程序的 Redis 连接配置从源 Redis 切换到目标 Redis 的连接地址和认证信息。
建议先进行小流量或测试环境的切换,确保业务功能正常。
核心业务流程验证:
执行业务系统的核心读写操作,模拟用户行为,例如用户登录、数据查询、数据写入、订单创建等。
监控应用程序的错误日志和性能指标(如响应时间、吞吐量),确保在连接目标 Redis 后,业务功能正常且性能达标。
数据回写验证:
如果有业务数据会写入 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 的运行日志,它可以提供详细的迁移状态、潜在问题和错误信息,是排查故障的重要依据。