【Redis技术探索】「数据迁移实战」手把手教你如何实现在线+离线模式进行迁移Redis数据实战指南(在线同步数据)

简介: 【Redis技术探索】「数据迁移实战」手把手教你如何实现在线+离线模式进行迁移Redis数据实战指南(在线同步数据)

RedisShake基本介绍


RedisShake是基于redis-port基础上进行改进的是一款开源的Redis迁移工具,支持Cluster集群的在线迁移与离线迁移(备份文件导入)。数据可平滑迁移,当部署在其他云厂商Redis服务上的Cluster集群数据,由于SYNC、PSYNC命令被云厂商禁用,无法在线迁移时,可以选择离线迁移。



RedisShake使用背景


RedisShake是一个用于在两个Redis实例之间同步数据的工具,满足非常灵活的同步与迁移需求。Redis实例之间的关系其中可能存在(standalone->standalone),(standalone->Cluster),(Cluster->Cluster)等。目前,比较常用的一个数据迁移工具是Redis-Shake ,这是阿里云Redis和MongoDB团队开发的一个用于 Redis 数据同步的工具。



RedisShake功能说明


RedisShake主要是支持Redis的RDB文件的解析、恢复、备份、同步四个功能:


  • 恢复(restore):将 RDB 文件恢复到目标Redis数据库。


  • 备份(dump):将源 Redis 的全量数据通过RDB文件备份起来。


  • 解析(decode):读取 RDB 文件,并以 JSON 格式解析存储。


  • 同步(sync):支持源redis和目的redis的数据同步,支持全量和增量数据的迁移,支持从云下到阿里云云上的同步,也支持云下到云下不同环境的同步,支持单节点、主从版、集群版之间的互相同步


  • 同步(rump):支持源 Redis 和目的 Redis 的数据同步,仅支持全量迁移。采用scan和restore命令进行迁移,支持不同云厂商不同redis版本的迁移。


注意:如果源端是集群版,可以启动一个RedisShake,从不同的db结点进行拉取,同时源端不能开启move slot功能;对于目的端,如果是集群版,写入可以是1个或者多个db结点。




Redis-Shake特性概览


  • 高性能:全量同步阶段并发执行,增量同步阶段异步执行,能够达到毫秒级别延迟(取决于网络延迟)。同时,我们还对大key同步进行分批拉取,优化同步性能。


  • 在 Redis 5.0、Redis 6.0 和 Redis 7.0 上测试
  • 支持使用lua自定义过滤规则
  • 支持大实例迁移
  • 支持restore模式和sync模式
  • 支持阿里云 Redis 和 ElastiCache
  • 监控体系:用户可以通过我们提供的restful拉取metric来对redis-shake进行实时监控:curl 127.0.0.1:9320/metric。


  • 数据校验:如何校验同步的正确性?可以采用我们开源的redis-full-check。


  • 支持版本:支持2.8-5.0版本的同步,此外还支持codis,支持云下到云上,云上到云上,云上到云下(阿里云目前支持主从版),其他云到阿里云等链路,帮助用户灵活构建混合云场景。


  • 断点续传。支持断开后按offset恢复,降低因主备切换、网络抖动造成链路断开重新同步拉取全量的性能影响。

image.png


RedisShake执行过程


  1. 启动Redis-shake进程,这个进程模拟了一个 Redis 实例,Redis-shake的基本原理就是模拟一个Slave从节点加入源Redis集群,然后进行增量的拉取(通过psync命令)。


  1. Redis-shake进程和数据迁出的源实例进行数据的全量拉取同步,并回放,这个过程和 Redis 主从实例的全量同步是类似的。如下图所示。

image.png


详细分析上述同步原理


  1. 源Redis服务实例相当于主库,Redis-shake相当于从库,它会发送psync指令给源Redis服务实例。


  1. 源Redis实例先把RDB文件传输给 Redis-shake ,Redis-shake 会把RDB文件发送给目的实例。


  1. 源实例会再把增量命令发送给 Redis-shake ,Redis-shake负责把这些增量命令再同步给目的实例。


如果源端是集群模式,只需要启动一个redis-shake进行拉取,同时不能开启源端的move slot操作。如果目的端是集群模式,可以写入到一个结点,然后再进行slot的迁移,当然也可以多对多写入。


目前,redis-shake到目的端采用单链路实现,对于正常情况下,这不会成为瓶颈,但对于极端情况,qps比较大的时候,此部分性能可能成为瓶颈,后续我们可能会计划对此进行优化。另外,redis-shake到目的端的数据同步采用异步的方式,读写分离在2个线程操作,降低因为网络时延带来的同步性能下降。




Redis-Shake安装使用


主要有两种方式:下载Release版本的可执行二进制包、下载源码文件进行编译操作这两种方式。




下载Release版本的可执行二进制包


Download from Release

image.png

点击下载就可以进行直接使用Redis-Shake服务。



下载源码文件进行编译操作


除了直接下载可执行包之外,还可以下载源码之后,可以进行运行build.sh文件执行进行编译源码,生成可执行包。可以根据上面的下载中source code进行下载。

image.png

或者可以针对于Git进行clone源码仓库,如下所示。

git clone https://github.com/alibaba/RedisShake
cd RedisShake
sh build.sh
复制代码





运行Redis-Shake服务


首先如果需要进行同步和重放,则需要进行编辑sync.toml文件以及编辑restore.toml.


  • redis-shake 支持三种数据迁移模式:sync、restore 和 scan:
  • 快速开始:数据迁移(使用 sync 模式)
  • 快速开始:从dump.rdb恢复数据(使用 restore 模式)
  • 快速开始:数据迁移(使用 scan 模式)
  • 使用 filters 做数据清洗
  • 运行日志
  • 运行监控

image.png




启动同步sync运行机制


我们打开或者编辑sync.toml

image.png

sync.toml文件内容


当我们编辑sync.toml文件之后,可以进行配置我们实际情况下的source源redis实例以及target目标redis实例。之后可以配置对应的cpu和相关性能的配置。下面针对于配置进行相关的配置介绍

type = "sync" # 同步机制实现
[source] # 源Redis服务实例
version = 5.0 # 填写Redis源服务版本, 例如:2.8, 4.0, 5.0, 6.0, 6.2, 7.0, ...。
address = "127.0.0.1:6379" # 源Redis服务实例 地址+端口
username = "" # 如果Redis没有配置ACL,则可以不填写,否则需要填写用户名 
password = "" # 如果Redis没有配置ACL,则可以不填写,否则需要填写密码
tls = false # 是否开启tls安全机制
elasticache_psync = "" # 是否支持AWS的elasticache
[target]
type = "standalone" # 选择Redis的类型:"standalone:单机模式" or "cluster:集群模式"
version = 5.0  # 填写Redis源服务版本, 例如:2.8, 4.0, 5.0, 6.0, 6.2, 7.0, ...。
# 如果目标Redis服务实例属于cluster集群模式, 那么可以写入其中一个节点的地址和端口.
# redis-shake 会通过`cluster nodes` 命令获取其他的节点地址和端口
address = "127.0.0.1:6380" # 填写的对应的ip加端口
username = "" # 如果Redis没有配置ACL,则可以不填写,否则需要填写用户名 
password = "" # 如果Redis没有配置ACL,则可以不填写,否则需要填写密码
tls = false # 是否开启tls安全机制
[advanced]
dir = "data" # 数据同步的存储目录
# 设置使用的最大CPU核心数, 如果设置了0 代表着 使用 runtime.NumCPU() 实际的cpu cores数量
ncpu = 4
# 开启pprof性能检测的port, 0代表着禁用
pprof_port = 0 
# 开启metric port端口, 0代表着禁用
metrics_port = 0
# log的相关设置
log_file = "redis-shake.log" # 设置对应的日志文件名称
log_level = "info" # debug, info or warn # 设置对应的日志级别
log_interval = 5 # in seconds # 日志打印频次
# redis-shake gets key and value from rdb file, and uses RESTORE command to
# create the key in target redis. Redis RESTORE will return a "Target key name
# is busy" error when key already exists. You can use this configuration item
# to change the default behavior of restore:
# panic:   redis-shake will stop when meet "Target key name is busy" error.
# rewrite: redis-shake will replace the key with new value.
# ignore:  redis-shake will skip restore the key when meet "Target key name is busy" error.
rdb_restore_command_behavior = "rewrite"  # restore的操作类型:panic, rewrite or skip
# pipeline的大小数量阈值
pipeline_count_limit = 1024
# Client query buffers accumulate new commands. They are limited to a fixed
# amount by default. This amount is normally 1gb.
target_redis_client_max_querybuf_len = 1024_000_000
# In the Redis protocol, bulk requests, that are, elements representing single
# strings, are normally limited to 512 mb.
target_redis_proto_max_bulk_len = 512_000_000
复制代码



Redis单机实例同步到Redis单机实例


修改sync.toml,改为如下配置。

[source]
address = "ip:6379"
password = ""
[target]
type = "standalone"
address = "ip:6379"
password = "r-bbbbb:xxxxx"
复制代码



启动 redis-shake:

./redis-shake sync.toml
复制代码



Redis单机实例同步到Redis集群实例

修改 sync.toml,改为如下配置:

[source]
address = "r-aaaaa.redis.zhangbei.rds.aliyuncs.com:6379"
password = "r-aaaaa:xxxxx"
[target]
type = "cluster"
address = "192.168.0.1:6379" # 这里写集群中的任意一个节点的地址即可
password = "r-ccccc:xxxxx"
复制代码



启动 redis-shake:
./redis-shake sync.toml
复制代码



Redis集群实例同步到Redis集群实例


方法1:手动起多个 redis-shake


集群C有四个节点:


  • 192.168.0.1:6379
  • 192.168.0.2:6379
  • 192.168.0.3:6379
  • 192.168.0.4:6379


把4个节点当成4个单机实例,参照单机到集群 部署 4 个 redis-shake 进行数据同步。不要在同一个目录启动多个 redis-shake,因为 redis-shake 会在本地存储临时文件,多个 redis-shake 之间的临时文件会干扰,正确做法是建立多个目录。


方法2:借助 cluster_helper.py 启动


脚本cluster_helper.py可以方便启动多个redis-shake从集群迁移数据,效果等同于方法1。

注意


源端有多少个分片,cluster_helper.py 就会起多少个 redis-shake 进程,所以如果源端分片数较多的时候,需要评估当前机器是否可以承担这么多进程。


cluster_helper.py 异常退出的时候,可能没有正常退出 redis-shake 进程,需要 ps aux | grep redis-shake 检查。


每个 redis-shake 进程的执行日志记录在 RedisShake/cluster_helper/data/xxxxx 中,反馈问题请提供相关日志。


依赖


Python 需要 python3.6 及以上版本,安装 Python依赖:

cd RedisShake/cluster_helper
pip3 install -r requirements.txt
复制代码



配置

修改 sync.toml:

type = "sync"
[source]
address = "192.168.0.1:6379" # 集群 C 中任意一个节点地址
password = "r-ccccc:xxxxx"
[target]
type = "cluster"
address = "192.168.1.1:6380" # 集群 D 中任意一个节点地址
password = "r-ddddd:xxxxx"
复制代码



运行
cd RedisShake/cluster_helper
python3 cluster_helper.py ../redis-shake ../sync.toml
复制代码
  • 参数 1 是 redis-shake 可执行程序的路径
  • 参数 2 是配置文件路径



查看redis-shake的日志信息
[root@redis ~]# redis-shake ./redis-shake.toml
2022-08-26 11:20:28 INF GOOS: linux, GOARCH: amd64
2022-08-26 11:20:28 INF Ncpu: 3, GOMAXPROCS: 3
2022-08-26 11:20:28 INF pid: 21504
2022-08-26 11:20:28 INF pprof_port: 0
2022-08-26 11:20:28 INF No lua file specified, will not filter any cmd.
2022-08-26 11:20:28 INF no password. address=[127.0.0.1:6380]
2022-08-26 11:20:28 INF redisWriter connected to redis successful. address=[127.0.0.1:6380]
2022-08-26 11:20:28 INF no password. address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF psyncReader connected to redis successful. address=[127.0.0.1:6379]
2022-08-26 11:20:28 WRN remove file. filename=[4200.aof]
2022-08-26 11:20:28 WRN remove file. filename=[dump.rdb]
2022-08-26 11:20:28 INF start save RDB. address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF send [replconf listening-port 10007]
2022-08-26 11:20:28 INF send [PSYNC ? -1]
2022-08-26 11:20:28 INF receive [FULLRESYNC 1db7c7618b6d0af25ffafb1645d4fba573624d02 0]
2022-08-26 11:20:28 INF source db is doing bgsave. address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF source db bgsave finished. timeUsed=[0.09]s, address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF received rdb length. length=[194]
2022-08-26 11:20:28 INF create dump.rdb file. filename_path=[dump.rdb]
2022-08-26 11:20:28 INF save RDB finished. address=[127.0.0.1:6379], total_bytes=[194]
2022-08-26 11:20:28 INF start send RDB. address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF RDB version: 8
2022-08-26 11:20:28 INF RDB AUX fields. key=[redis-ver], value=[4.0.14]
2022-08-26 11:20:28 INF RDB AUX fields. key=[redis-bits], value=[64]
2022-08-26 11:20:28 INF RDB AUX fields. key=[ctime], value=[1661484028]
2022-08-26 11:20:28 INF RDB AUX fields. key=[used-mem], value=[1897096]
2022-08-26 11:20:28 INF RDB repl-stream-db: 0
2022-08-26 11:20:28 INF RDB AUX fields. key=[repl-id], value=[1db7c7618b6d0af25ffafb1645d4fba573624d02]
2022-08-26 11:20:28 INF RDB AUX fields. key=[repl-offset], value=[0]
2022-08-26 11:20:28 INF RDB AUX fields. key=[aof-preamble], value=[0]
2022-08-26 11:20:28 INF RDB resize db. db_size=[1], expire_size=[0]
2022-08-26 11:20:28 INF send RDB finished. address=[127.0.0.1:6379], repl-stream-db=[0]
2022-08-26 11:20:28 INF start save AOF. address=[127.0.0.1:6379]
2022-08-26 11:20:28 INF AOFWriter open file. filename=[0.aof]
2022-08-26 11:20:29 INF AOFReader open file. aof_filename=[0.aof]
2022-08-26 11:20:33 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[0], aofAppliedOffset=[0]
2022-08-26 11:20:38 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[1], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[14], aofAppliedOffset=[14]
2022-08-26 11:20:43 INF syncing aof. allowOps=[0.00], disallowOps=[0.00], entryId=[1], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[14], aofAppliedOffset=[14]
2022-08-26 11:20:48 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[2], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[28], aofAppliedOffset=[28]




相关文章
|
8月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
858 6
|
9月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
368 1
Redis专题-实战篇二-商户查询缓存
|
9月前
|
存储 NoSQL 前端开发
Redis专题-实战篇一-基于Session和Redis实现登录业务
本项目基于SpringBoot实现黑马点评系统,涵盖Session与Redis两种登录方案。通过验证码登录、用户信息存储、拦截器校验等流程,解决集群环境下Session不共享问题,采用Redis替代Session实现数据共享与自动续期,提升系统可扩展性与安全性。
527 3
Redis专题-实战篇一-基于Session和Redis实现登录业务
|
9月前
|
存储 运维 NoSQL
Redis集群模式
Redis集群是一种分布式存储方案,旨在解决数据存储容量不足的问题。它通过将数据分片存储在多个节点上,实现数据的横向扩展。常见的分片算法包括哈希求余、一致性哈希和哈希槽分区。其中,Redis采用哈希槽分区算法,将数据均匀分配到16384个槽位中,每个分片负责一部分槽位。当节点故障时,集群通过故障检测和主从切换机制,确保服务的高可用性。集群还支持自动的数据迁移和负载均衡,保障系统稳定运行。
NoSQL 数据可视化 关系型数据库
211 0
|
11月前
|
NoSQL Redis UED
redis数据迁移、数据导出和导入用什么工具
用户体验好的客户端,我建议使用yunedit-redis来做数据迁移,因为它支持图形化,还支持多种导出方式。 yunedit-redis它支持全库导出,也支持选择部分key导出,还支持用*号表达式导出。
|
12月前
|
机器学习/深度学习 存储 NoSQL
基于 Flink + Redis 的实时特征工程实战:电商场景动态分桶计数实现
本文介绍了基于 Flink 与 Redis 构建的电商场景下实时特征工程解决方案,重点实现动态分桶计数等复杂特征计算。通过流处理引擎 Flink 实时加工用户行为数据,结合 Redis 高性能存储,满足推荐系统毫秒级特征更新需求。技术架构涵盖状态管理、窗口计算、Redis 数据模型设计及特征服务集成,有效提升模型预测效果与系统吞吐能力。
1291 10
|
12月前
|
缓存 监控 NoSQL
Redis 实操要点:Java 最新技术栈的实战解析
本文介绍了基于Spring Boot 3、Redis 7和Lettuce客户端的Redis高级应用实践。内容包括:1)现代Java项目集成Redis的配置方法;2)使用Redisson实现分布式可重入锁与公平锁;3)缓存模式解决方案,包括布隆过滤器防穿透和随机过期时间防雪崩;4)Redis数据结构的高级应用,如HyperLogLog统计UV和GeoHash处理地理位置。文章提供了详细的代码示例,涵盖Redis在分布式系统中的核心应用场景,特别适合需要处理高并发、分布式锁等问题的开发场景。
637 42
|
12月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
3292 7
|
8月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
816 25