使用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:812127.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:0127.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数量少

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

04 —— Webpack打包CSS代码

加载器css-loader :解析css代码 webpack 中文文档 | webpack中文文档 | webpack中文网 加载器style-loader:把解析后的css代码插入到DOM style-loader | webpack 中文文档 | webpack中文文档 | webpack中文网 准备css代码,放到src/login目…

Nacos实现IP动态黑白名单过滤

一些恶意用户(可能是黑客、爬虫、DDoS 攻击者)可能频繁请求服务器资源,导致资源占用过高。因此我们需要一定的手段实时阻止可疑或恶意的用户,减少攻击风险。 本次练习使用到的是Nacos配合布隆过滤器实现动态IP黑白名单过滤 文章…

SAP PI/PO Proxy2JDBC SQL_QUERY动态接口示例

目录 背景: 完整demo步骤: IR: ID: SPROXY: 测试代码: 注意点: 背景: 中途临时帮客户项目做其他功能,项目上有部分开发项需要通过PO去第三方数据库取数,项目上的开发对PO不太熟&#xf…

如何使用本地大模型做数据分析

工具:interpreter --local 样本数据: 1、启动分析工具 2、显示数据文件内容 输入: 显示/Users/wxl/work/example_label.csv 输出:(每次输出的结果可能会不一样) 3、相关性分析 输入: 分析客户类型与成…

中间件--laravel进阶篇

laravel版本11.31,这中间件只有3种,分别是全局中间件,路由中间件,控制器中间件。相比thinkphp8,少了一个应用中间件。 一、创建中间件 laravel创建中间件可以使用命令的方式创建,非常方便。比如php artisan make:middleware EnsureTokenIsValid。EnsureTokenIsValid是中间…

一维卷积神经网络(1D-CNN)

一维卷积神经网络(1D Convolutional Neural Network, 1D CNN)是卷积神经网络的一种变体,专门用于处理序列数据,如时间序列、文本等。 一、基本结构 一维卷积神经网络的基本结构与二维卷积神经网络(2D CNN)类…

Java中的TreeSet集合解析

记一下java流处理的操作 1.去重&#xff0c;按照billTypeCode去重 list list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getBillTypeCode()))), ArrayList::new)); 排序&#x…

vue中mixin(混入)的使用

目录 mixin(混入) 使用方式 第一步定义混合 ​编辑 第二步使用混入 局部混入 全局混合 mixin(混入) 功能&#xff1a;可以把多个组件共用的配置提取成一个混入对象 使用方式 第一步定义混合 { data(){....}, methods:{....} .... } 第二步使用混入 …

vue中路由缓存

vue中路由缓存 问题描述及截图解决思路关键代码及打印信息截图 问题描述及截图 在使用某一平台时发现当列表页码切换后点击某一卡片进入详情页后&#xff0c;再返回列表页时页面刷新了。这样用户每次看完详情回到列表页都得再重新输入自己的查询条件&#xff0c;或者切换分页到…

Easyexcel(1-注解使用)

相关文章链接&#xff1a; Easyexcel&#xff08;1-注解使用&#xff09; 版本依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version> </dependency>ExcelProperty…

Vue3 -- mock数据完整配置并调试【项目集成6】

引言&#xff1a; ‌Mock在前端开发中的作用主要是模拟后端接口数据&#xff0c;以便前端开发者能够提前进行页面和功能的开发、调试&#xff0c;而无需等待后端提供真实的接口数据‌。Mock数据可以加速前后端开发的协同&#xff0c;避免因数据延迟导致的开发阻塞‌。【摘自百…

开源许可协议

何同学推动了开源协议的认识&#xff0c;功不可没&#xff0c;第一次对开源有了清晰的认识&#xff0c;最宽松的MIT开源协议 源自OSC开源社区&#xff1a;何同学使用开源软件“翻车”&#xff0c;都别吵了&#xff01;扯什么违反MIT

数据结构(顺序栈——c语言实现)

栈的基本概念&#xff1a; 栈是限制在一端进行插入操作和删除操作的线性表&#xff08;俗称堆栈&#xff09;&#xff0c;允许进行操作的一端称为“栈顶”&#xff0c;另一固定端称为“栈底”&#xff0c;当栈中没有元素时称为“空栈” 特点&#xff1a;先进后出&#xff08;FI…

【智谱清言-注册_登录安全分析报告】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

[Realtek sdk-3.4.14b] RTL8197FH-VG新增jffs2分区操作说明

sdk说明 ** Gateway/AP firmware v3.4.14b – Aug 26, 2019**  Wireless LAN driver changes as:  Refine WiFi Stability and Performance  Add 8812F MU-MIMO  Add 97G/8812F multiple mac-clone  Add 97G 2T3R antenna diversity  Fix 97G/8812F/8814B MP issu…

Cesium 加载B3DM模型

一、引入Cesium&#xff0c;可以使用该链接下载cesium 链接: https://pan.baidu.com/s/1BRQyaFCkxO2xQQT5RzFUCw?pwdkcv9 提取码: kcv9 在index.html文件中引入cesium <script type"text/javascript" src"/Cesium/Cesium.js"></script> …

掌握移动端性能测试利器:深入JMeter手机录制功能

引言 在当今移动互联网时代&#xff0c;应用程序的性能和用户体验至关重要。为了确保应用程序在不同设备和网络环境下都能稳定运行&#xff0c;性能测试成为了不可或缺的一环。Apache JMeter作为一款强大的开源性能测试工具&#xff0c;不仅支持传统的PC端性能测试&#xff0c…

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

MySQL - 数据库基础 | 数据库操作 | 表操作

文章目录 1、数据库基础1.1为什么要有数据库1.2主流的数据库1.3连接MySQL1.4服务器、数据库、表的关系1.5 MySQL框架1.6 SQL分类1.7储存引擎 2.数据库操作2.1创建数据库2.2字符集和校验规则2.3删除数据库2.4修改数据库2.5备份与恢复2.6查看连接情况 3.表的操作3.1创建表3.2查看…