使用redis-shake工具进行redis的数据同步

前言:

工作中将常遇到测试环境和正式环境的数据同步或者需要进行数据迁移,对于mysql数据库的方案倒是不少,但是redis中如何快速便捷的迁移呢?答案是阿里云提供的:redis-shake

RedisShake是阿里云基于豌豆荚开源的redis-port进行二次开发的一个支持Redis异构集群实时同步的工具,它和redis-migrate-tool相比较,我觉得它的优点在于支持前缀key的同步,支持多DB同步,而redis-migrate-tool 只能全量同步,并且如果源做了分库,同步到目标Redis的时候都同步到了db0一个库里面了,这对于做了分库场景的业务是不可行的。

基本功能

redis-shake它支持解析、恢复、备份、同步四个功能

  1. 恢复restore:将RDB文件恢复到目的redis数据库。
  2. 备份dump:将源redis的全量数据通过RDB文件备份起来。
  3. 解析decode:对RDB文件进行读取,并以json格式解析存储。
  4. 同步sync:支持源redis和目的redis的数据同步,支持全量和增量数据的迁移,支持单节点、主从版、集群版之间的互相同步。
  5. 同步rump:支持源redis和目的redis的数据同步,仅支持全量的迁移,采用scan和restore命令进行迁移,支持不同云厂商不同redis版本的迁移。

参考官方文档: https://github.com/alibaba/RedisShake 

基本原理

RedisShake同步原理

  1. 源Redis服务实例相当于主库,Redis-shake相当于从库,它会发送psync指令给源Redis服务实例。
  2. 源Redis实例先把RDB文件传输给 Redis-shake ,Redis-shake 会把RDB文件发送给目的实例。
  3. 源实例会再把增量命令发送给 Redis-shake ,Redis-shake负责把这些增量命令再同步给目的实例。


RedisShake执行过程

  1. 启动Redis-shake进程,这个进程模拟了一个 Redis 实例,Redis-shake的基本原理就是模拟一个Slave从节点加入源Redis集群,然后进行增量的拉取(通过psync命令)。
  2. Redis-shake进程和数据迁出的源实例进行数据的全量拉取同步,并回放,这个过程和 Redis 主从实例的全量同步是类似的

版本迭代特性

现在 redis-shake 有两个主版本:
redis-shake 2.x:持续更新 3 年,目前停止更新与答疑,遇到问题推荐尝试 3.x 版本
redis-shake 3.x:基于 redis-shake 2.x 重写,代码可读性高,性能较佳 

部署和使用 

1、部署安装redis-shake

1.1源端创建测试数据也可以可视化工具自行添加一些测试数据

[root@localhost ~]# for line in {1..10000};do /opt/redis6/bin/redis-cli -h 192.168.1.191 -p 7001 -c -a 1UEJjjGfYZU7dCWy set ops_${line} ${line}; done

 2、下载解压redis-shake文件

[root@localhost ~]# mkdir redis-shake && cd redis-shake
[root@localhost redis-shake]# wget https://github.com/alibaba/RedisShake/releases/download/v3.1.7/redis-shake-linux-amd64.tar.gz
[root@localhost redis-shake]# tar axf redis-shake-linux-amd64.tar.gz

一、数据迁移实操

迁移环境信息如下:

主机IP操作系统Redis版本CPU架构端口角色
192.168.1.191Centos7.66.2.8x86_647001源主机
192.168.1.192Centos7.66.2.8x86_647001目标主机

3、修改配置文件(sync.toml)

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

同步日志注释
当打印的日志出现send RDB finished,表示完成全量数据迁移,接下来进入增量数据迁移阶段。

日志信息中各参数说明如下:

  • allowOps:表示每秒向目标库发送多少条命令。 说明 通常当allowOps为0时,表示数据迁移完成,可以停止redis-shake。但源库会定时发送PING命令,所以allowOps偶尔不为0。
  • disallowOps:表示每秒过滤的命令数。
  • entryId:从1开始计数,表示redis-shake共处理多少条命令。
  • InQueueEntriesCount:表示还剩余多少条命令待发送。 暂停向源库写入数据,等待返回日志中allowOps对应值连续多次为0时,使用Ctrl+C组合键停止运行redis-shake。 此时目标库的数据与源库完全一致,您可以将业务的数据库服务由自建Redis数据库切换至Tair或Redis实例。

 toml文件的编写方式
单机 -> 单机 配置格式:

type = "sync"
[source]  
address = "127.0.0.1:6379"
password = "123456"  ## 根据自身密码填写

[target]  
type = "standalone" #这里type属性设置一定为standalone
address = "127.0.0.1:6379" 
password = "123456" ## 根据自身密码填写

启动 redis-shake:
root@ubuntu20-171:RedisShake# ./redis-shake sync.toml

单机->集群 配置格式:

type = "sync"
[source]  #数据源配置
address = "127.0.0.1:6379"
password = "1234566"

[target]  #目的源配置
type = "cluster"   #这里type属性设置一定为cluster
address = "127.0.0.1:6379" # 这里写集群中的任意一个节点的地址即可
password = "1234566"

启动 redis-shake:
root@ubuntu20-171:RedisShake# ./redis-shake sync.toml

 集群 -> 集群 配置格式:
在 RedisShake V3系列版本,也就是当前使用最多的版本中,集群与集群之间的redis数据同步,统一在单机到集群的基础上,为每一个数据源端的redis master节点建立一个shake进程

⚠️注意:不要在同一个目录启动多个 redis-shake,因为 redis-shake 会在本地存储临时文件,多个 redis-shake 之间的临时文件会干扰,正确做法是建立多个目录。

配置
修改 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"

启动 redis-shake:
root@ubuntu20-171:RedisShake# cd bin/cluster_helper
root@ubuntu20-171:cluster_helper# python3 cluster_helper.py ../redis-shake ../sync.toml 

参数 1 是 redis-shake 可执行程序的路径
参数 2 是配置文件路径

 2.3、redis-shake执行数据迁移

1、执行下述命令启动redis-shake,redis-shake将开始执行数据迁移

[root@localhost redis-shake]# ./redis-shake sync.toml

日志信息

同步分为三个阶段:

等待源端save rdb完毕,日志如下:

[root@localhost redis-shake]# ./redis-shake sync.toml
2024-11-20 23:16:45 INF GOOS: linux, GOARCH: amd64
2024-11-20 23:16:45 INF Ncpu: 4, GOMAXPROCS: 4
2024-11-20 23:16:45 INF pid: 5493
2024-11-20 23:16:45 INF pprof_port: 0
2024-11-20 23:16:45 INF No lua file specified, will not filter any cmd.
2024-11-20 23:16:45 INF no password. address=[192.168.48.131:6319]
2024-11-20 23:16:45 INF redisClusterWriter load cluster nodes. line=b4cc6c47038acb2a5f1198f23473d757d0991b24 127.0.0.1:6319@16319 myself,master - 0 1732173403000 1 connected 0-5460
2024-11-20 23:16:45 INF no password. address=[127.0.0.1:6319]
2024-11-20 23:16:45 INF redisWriter connected to redis successful. address=[127.0.0.1:6319]
2024-11-20 23:16:45 INF redisClusterWriter load cluster nodes. line=61cdca1ce4f7524e7278081474168361f2036d39 127.0.0.1:6339@16339 master - 0 1732173404370 3 connected 10923-16383
2024-11-20 23:16:45 INF no password. address=[127.0.0.1:6339]
2024-11-20 23:16:45 INF redisWriter connected to redis successful. address=[127.0.0.1:6339]
2024-11-20 23:16:45 INF redisClusterWriter load cluster nodes. line=ef3dd5f8304d590eb730b7a9900a7d5a2ccbab02 127.0.0.1:6329@16329 master - 0 1732173401171 2 connected 5461-10922
2024-11-20 23:16:45 INF no password. address=[127.0.0.1:6329]
2024-11-20 23:16:45 INF redisWriter connected to redis successful. address=[127.0.0.1:6329]
2024-11-20 23:16:45 INF redisClusterWriter connected to redis cluster successful. addresses=[127.0.0.1:6319 127.0.0.1:6339 127.0.0.1:6329]
2024-11-20 23:16:45 INF no password. address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF psyncReader connected to redis successful. address=[192.168.0.111:7005]
2024-11-20 23:16:45 WRN remove file. filename=[133117.aof]
2024-11-20 23:16:45 WRN remove file. filename=[dump.rdb]
2024-11-20 23:16:45 INF start save RDB. address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF send [replconf listening-port 10007]
2024-11-20 23:16:45 INF send [PSYNC ? -1]
2024-11-20 23:16:45 INF receive [FULLRESYNC 2f2ce402b674be6aa3df35b1a9a27073bd67275c 135609]
2024-11-20 23:16:45 INF source db is doing bgsave. address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF source db bgsave finished. timeUsed=[0.12]s, address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF received rdb length. length=[1094]
2024-11-20 23:16:45 INF create dump.rdb file. filename_path=[dump.rdb]
2024-11-20 23:16:45 INF save RDB finished. address=[192.168.0.111:7005], total_bytes=[1094]

全量同步阶段
数据量大的话会显示进度百分比:(我dev环境数据量小)日志如下:


2024-11-20 23:16:45 INF start send RDB. address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF RDB version: 7
2024-11-20 23:16:45 INF RDB AUX fields. key=[redis-ver], value=[3.2.100]
2024-11-20 23:16:45 INF RDB AUX fields. key=[redis-bits], value=[64]
2024-11-20 23:16:45 INF RDB AUX fields. key=[ctime], value=[1732173405]
2024-11-20 23:16:45 INF RDB AUX fields. key=[used-mem], value=[0]
2024-11-20 23:16:45 INF RDB resize db. db_size=[10], expire_size=[0]
2024-11-20 23:16:45 INF send RDB finished. address=[192.168.0.111:7005], repl-stream-db=[0]
2024-11-20 23:16:45 INF start save AOF. address=[192.168.0.111:7005]
2024-11-20 23:16:45 INF AOFWriter open file. filename=[135609.aof]
2024-11-20 23:16:46 INF AOFReader open file. aof_filename=[135609.aof]
   ## 全量完成

## 显示 send RDB finished 说明全量完成

 增量同步
日志如下:

2024-11-20 23:16:50 INF syncing aof. allowOps=[2.00], disallowOps=[0.00], entryId=[9], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[0], aofAppliedOffset=[0]
2024-11-20 23:16:55 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[10], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[135623], aofAppliedOffset=[135623]
2024-11-20 23:17:00 INF syncing aof. allowOps=[0.00], disallowOps=[0.00], entryId=[10], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[135623], aofAppliedOffset=[135623]
2024-11-20 23:17:05 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[11], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[135637], aofAppliedOffset=[135637]
2024-11-20 23:17:10 INF syncing aof. allowOps=[0.00], disallowOps=[0.00], entryId=[11], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[135637], aofAppliedOffset=[135637]
2024-11-20 23:17:15 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[12], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[135651], aofAppliedOffset=[135651]

 出现字样syncing aof. allowOps=[0.00] 或者出现syncing aof. allowOps=[0.00]的频率很高 说明 当前增量同步完成 可以ctrl+c停止redis-shake 进程,但是 一般不会为0 或者 因为有client在一直连接

查看源端和目标端的情况
源端

127.0.0.1:6379> info Replication
# Replication
role:master
connected_slaves:1  ### 源端会启动一个redis-shake的从节点
slave0:ip=127.0.0.1,port=10007,state=online,offset=1040,lag=0 ###shake进程
master_failover_state:no-failover
master_replid:b20dfd6f617c867cfaf0910c08be627fe7b922d7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1040
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:104857600
repl_backlog_first_byte_offset:229
repl_backlog_histlen:812

127.0.0.1:6379> info  Keyspace   ## 查看比对key数量
# Keyspace
db0:keys=6,expires=0,avg_ttl=0
db2:keys=3,expires=0,avg_ttl=0
db10:keys=3,expires=0,avg_ttl=0

目标端

127.0.0.1:7000> info Replication
# Replication
role:master   ### 目标端 还是master角色
connected_slaves:0
master_failover_state:no-failover
master_replid:1017a92f7fd8447d304172796ea6044a1f801e26
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:104857600
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

127.0.0.1:7000> info  Keyspace  ## 对比key数量
# Keyspace
db0:keys=6,expires=0,avg_ttl=0
db2:keys=3,expires=0,avg_ttl=0
db10:keys=3,expires=0,avg_ttl=0

注意事项
如果目标库的数据淘汰策略(maxmemory-policy)配置为noeviction以外的值,可能导致目标库的数据与源库不一致
如果源库中的某些Key使用了过期(expire)机制,由于可能存在Key已过期但未被及时删除的情形,所以在目标库中查看(如通过info命令)到的Key数量会比源库的Key数量少

以上就是这期全部内容,感谢观看 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/922984.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能之数学基础:向量的基本知识

本文重点 向量的基本性质是线性代数和向量空间理论的核心,它们为向量运算提供了坚实的基础,并在物理、工程、计算机图形学等领域有着广泛的应用。本文对向量的一些基本知识进行介绍,帮助大家快速理解向量。 向量的定义与表示 向量是一个既有大小又有方向的量,通常用带箭…

《数据结构》学习系列——图(中)

系列文章目录 目录 图的遍历深度优先遍历递归算法堆栈算法 广度优先搜索 拓扑排序定义定理算法思想伪代码 关键路径基本概念关键活动有关量数学公式伪代码时间复杂性 图的遍历 从给定连通图的某一顶点出发,沿着一些边访问遍图中所有的顶点,且使每个顶点…

STM32编程小工具FlyMcu和STLINK Utility 《通俗易懂》破解

FlyMcu FlyMcu 模拟仿真软件是一款用于 STM32 芯片 ISP 串口烧录程序的专用工具,免费,且较为非常容易下手,好用便捷。 注意:STM32 芯片的 ISP 下载,只能使用串口1(USART1),对应的串口…

非递归遍历二叉树(数据结构)

我的博客主页 非递归遍历二叉树 前序遍历(迭代)中序遍历(迭代)后续遍历(迭代) 二叉树的遍历方式有:前序遍历、中序遍历、后续遍历,层序遍历,而树的大部分情况下都是通过递…

对于某些原型或UI软件的个人看法(2024/11)

由于我这几天,一边敲代码,一边进行页面布局设计与编码,发现可能就一个卡片,我都得调很久样式,觉得这样改很累也没效率,页面也不是很美观。所以我想到了ui设计,我可以先进行ui设计,然…

Rocky DEM tutorial4_SAG mill 半自磨机 -后处理

文章目录 3. 后处理3.1 磨损分析 - 3D3.2 磨损分析 - 2D3.3 导出磨损后的几何3.4颗粒轨迹3.5欧拉统计3.6 能谱分析介绍Enjoy!案例链接注:案例来自于Rocky官方教程3. 后处理 3.1 磨损分析 - 3D 点击Geometries --> Mill,点击Properties,选择 add new custom property …

目标检测指标-以及YOLOv1简介

一、物体检测评估指标 1.1 IOU IOU就是交并比,交集和并集之比,GT就是Ground-Truth真实值,红色的就是预测值。 我们希望预测值与真实值越接近越好,IOU越大越好。 1.2 MAP 如上图,右上角Actual是真实值,左边…

C++:用红黑树封装map与set-2

文章目录 前言一、红黑树封装map与set中const迭代器1. 框架的搭建2. set实现const迭代器3. map实现const迭代器 二、operator[ ]1. operator[ ]要达成的样子2. insert的改变 三. 解决insert里set中的问题四. 解决map中的operator[ ]总结用红黑树封装map与set代码 前言 前面我们…

jmeter5.6.3安装教程

一、官网下载 需要提前配置好jdk的环境变量 jmeter官网:https://jmeter.apache.org/download_jmeter.cgi 选择点击二进制的zip文件 下载成功后,默认解压下一步,更改安装路径就行(我安装在D盘) 实用jmeter的bin目录作为系统变量 然后把这…

你最擅长使用哪个异步编程模式?

前言 异步编程模式指的是在进行异步编程时所采用的一种编程模式,主要包括TAP、EAP和APM三种模式。 TAP(Task-based Asynchronous Pattern)模式是.NET 4.0中引入的一种异步编程模式,它基于Task类实现,通过Task类的实例…

Linux高阶——1117—TCP客户端服务端

目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…

1.5万字长文Java集合与数据结构面试题(注:该篇博客将会持续维护 最新维护时间:2024年11月25日)

🧸本篇博客重在讲解Java集合与数据结构面试题,将会实时更新,欢迎大家添加作者文末联系方式交流 📜JAVA面试题专栏:JAVA崭新面试题——2024版_dream_ready的博客-CSDN博客 📜作者首页: dream_rea…

[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式

T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求: 编译硬件需求:做多系统测试,磁盘500GB起步(固态)(机械会卡死),内存3…

40分钟学 Go 语言高并发:【实战】并发安全的配置管理器

【实战】并发安全的配置管理器 一、课程概述 学习要点重要程度掌握目标配置热更新★★★★★理解配置热更新原理,实现动态加载配置并发读写控制★★★★★掌握并发安全的读写控制机制观察者模式★★★★☆理解并实现配置变更通知机制版本管理★★★★☆实现配置版…

游戏陪玩系统开发功能需求分析

电竞游戏陪玩系统是一种专门为游戏玩家提供陪伴、指导和互动服务的平台。这类系统通常通过专业的陪玩师(也称为陪练师)为玩家提供一对一或多对一的游戏陪伴服务,帮助玩家提升游戏技能、享受游戏乐趣,甚至解决游戏中的各种问题。电…

Idea修改Commit Changes模式、idea使用git缺少部分Commit Changes

文章目录 一、模式一1、页面效果如下2、如何打开为这种样式? 二、模式二1、页面效果如下2、如何打开为这种样式? 三、总结 前言:Idea中代码提交到git库时的commit Change有两种模式,每种模式的界面及功能都不太一样。 Commit Cha…

飞书会话消息左右排列

飞书会话消息左右排列 1. 飞书登录后,点击头像,弹出菜单有个按钮设置 2. 3.

VUE3项目 关于金额:分转化为元 ;元转化为分;

1.在components 文件夹下新建moneyHandle.ts 文件 2.ts文件中写如下代码(保留两位小数) //分转化为元 - 正则解决精度 export const regFenToYuan (fen:any) >{var num fen;numfen*0.01;num;var reg num.indexOf(.) >-1 ? /(\d{1,3})(?(?:…

【linux学习指南】初识Linux进程信号与使用

文章目录 📝信号快速认识📶⽣活⻆度的信号📶 技术应⽤⻆度的信号🌉 前台进程(键盘)🌉⼀个系统函数 📶信号概念📶查看信号 🌠 信号处理🌉 忽略此信…

蒙特卡洛方法(Monte Carlo,MC)

目录 1 序言 2 Monte Carlo法计算积分 3 最优化计算Monte Carlo法 1 序言 蒙特卡罗方法(Monte Carlo)是由冯诺依曼和乌拉姆等人发明的,“蒙特卡罗”这个名字是出自摩纳哥的蒙特卡罗赌场,这个方法是一类基于概率的方法的统称。是一种应用随机数来进行…