Kubernetes部署RedisShake实现Redis哨兵异地灾备
- 系统运维
- 13小时前
- 15热度
- 0评论
什么是 RedisShake
RedisShake 是一个用于处理和迁移 Redis 数据的工具,它提供以下特性:
- Redis 兼容性:RedisShake 兼容从 2.8 到 7.2 的 Redis 版本,并支持各种部署方式,包括单机,主从,哨兵和集群。
- 云服务兼容性:RedisShake 与主流云服务提供商提供的流行 Redis-like 数据库无缝工作,包括但不限于:
阿里云-云数据库 Redis 版
阿里云-云原生内存数据库Tair
AWS - ElastiCache
AWS - MemoryDB - Module 兼容:RedisShake 与 TairString,TairZSet 和 TairHash 模块兼容。
- 多种导出模式:RedisShake 支持 PSync,RDB 和 Scan 导出模式。
- 数据处理:RedisShake 通过自定义脚本实现数据过滤和转换。
上图是SYNC模式下全量+增量的数据流图,第一次复制向源端发送了之后,源端给它发RDB文件,解析RDB文件放到Pipe中。
它可以通过并发Restore到目的端,同步完成之后就会自动启动增量。增量就是从源端拉取写命令,进行解析过滤,然后再放到目的端,同时还需要接收回复。
架构图
当源端和目的端为单实例节点(Standalone)时,同步架构图如下。
当源端和目的端都为集群(Cluster)时,同步架构图如下。
从架构图可以看到,数据从源端(Source)同步到目的端(Destination),主要经过 Cluster Reader、Main、Cluster Writer 三部分处理。
Cluster Reader
Cluster Reader 即集群读入类,其根据源端分片数量创建同等数量的 Standalone Reader,每个 Standalone Reader 开启一个协程(Goroutinue)并行的从每个源端分片进行读入,并将数据存入相应的管道(Reader Channel)交付给下一环节处理。
Sync Reader
优势:数据一致性最佳,对源库影响小,可以实现不停机的切换
原理:RedisShake 模拟 Slave 连接到 Master 节点,Master 会向 RedisShake 发送数据,数据包含全量与增量两部分。全量是一个 RDB 文件,增量是 AOF 数据流,RedisShake 会接受全量与增量将其暂存到硬盘上。全量同步阶段:RedisShake 首先会将 RDB 文件解析为一条条的 Redis 命令,然后将这些命令发送至目的端。增量同步阶段:RedisShake 会持续将 AOF 数据流同步至目的端。
常见问题
连接断开:如果遇到 RedisShake 至源端节点的连接被断开,可通过源端对应节点的运行日志确认,多是因为源端 client-output-buffer-limit replica 参数设置过小,建议适当调高。
Scan Reader
原理介绍
Scan Reader 有 SCAN 和 KSN 两个阶段,SCAN 阶段是全量同步,KSN 阶段是增量同步。
全量数据
DbSyncer维护了连接链路,它是一个结构体,源端是6379,目的端是一个集群,它代表了一个数据链路。
假如说原来配置的是一个三主三从的集群模式,那么就会开启三个DbSyncer,同时有ID对它进行标识。每个DbSyncer管理一个连接,如6379首先是向RDB文件发送过来,然后Loader会解析出一些信息,包括DB、Key、Type等,然后放到Pipe中。然后需要向目的端写入,写入的时候全量模式支持并发。
从Pipe出来后先进行过滤,因为RedisShake支持DB、Key、Slot这些级别的过滤,用户可以设置黑白名单。正常情况下就可以Restore到目的端,然后再接收回复。对于lua ,可以进行script load,也可以设置过滤lua。对于BigKey,需要根据编码形式进行拆分解析。
增量数据
全量同步结束之后会自动开启增量同步,增量同步主要是由四个协程完成。
-
第一个协程定期从源端获取RedisShake的偏移量。
-
第二个协程主要是从源端拉取写命令。因为原来是模拟源端的一个从,从执行写命令的时候会发送一条Binlog到RedisShake,RedisShake读到之后交给Decoder,然后会将Binlog解析成一个原生命令,同时还会计算一下偏移量。得到命令后有Key,然后就可以进行过滤,再放到Sendbuffer中,Sendbuffer就是最终要发送到目的端的一些写命令。
-
第三个协程就是Sender,它执行发送逻辑,从Sendbuffer中取出写命令,并不是立即发送过去,它是和Checkpoint绑成一个事务,一块写入目的端。断点续传的原理是会先放到cache里边,就像是一层缓存,然后触发一定条件之后就去执行sendFunc函数。这是一个事务,它会先去写这些增数据,然后再去修改Checkpoint值。
针对于Redis Cluster同步,可以参考下图
首先源客户发送了一个“SET msg hello”,然后源端会以一个Binlog的形式写入到RedisShake。RedisShake读到之后先解析出原生的写命令,就会调用Send函数。Send函数目的端是一个集群,它需要知道自己应该发送到哪个节点上。
因为集群方式有槽概念,RedisShake还维护了 Slot数组,它的 index就是槽的ID,它对应的值就是槽所在的节点上。Node是一个结构体,里边有一个字段address,就是节点的地址。
调用Send函数的时候,首先需要获取到这个Key是应该发送到哪个节点上,会调用getNodeByKey,实际上就是对Key进行一次Hash,调用的是crc16算法。Key会算到它在哪个槽上,然后再通过下面 Slots数组,就知道这个槽是在哪个节点上,然后再调用do把它写入到 node上,写入之后会Receive目的端的回复。然后我们就需要去检查这个回复是什么,如果是有异常的话,就会直接将这个结果返回过去,再由上一层去进行判断。
假如说是move或者是ask,可能会调用回调函数handleMove或handleAsk两个重定向。
KSN 阶段:默认关闭,可通过 ksn 开启,可以解决 SCAN` 阶段期间遗漏 Key 问题。增量数据同步并不是在 SCAN 阶段结束后才开始,而是与其一同进行,并在 SCAN 阶段结束后持续进行,直到退出 RedisShake。
ksn 使用 Redis keyspace notifications 能力来订阅 Key 的变化。具体来说,RedisShake 会使用 psubscribe 命令订阅 keyevent@*:*,当 Key 发生变化时,RedisShake 会收到发生修改的 Key,之后使用 DUMP 与 RESTORE 命令来从源端读取 Key 的内容,并写入目标端。
- Redis 在默认情况下不会开启 notify-keyspace-events 配置,需要手动开启,保证值中含有 AE。
- 如果在 KSN 阶段出现源端将连接断开,考虑适当调高
client-output-buffer-limit pubsub
的值。802 - Redis keyspace notifications 不会感知到 FLUSHALL 与 FLUSHDB 命令,因此在使用 ksn 参数时,需要确保源端数据库不会执行这两个命令。
性能影响
SCAN 与 KSN 阶段均使用 DUMP 命令来获取数据,DUMP 命令是 CPU 密集命令,会对源端造成较高压力。需要小心使用,避免影响源端实例的可用性。
- 对于 SCAN 阶段,可以通过调整 count 参数来减轻源端压力,建议从 1 开始,逐步增加。
- 对于 KSN 阶段,暂无参数可调整,需要根据源端写请求量来评估是否开启。
性能影响参考数据:源端实例写 QPS 为 15 万左右时,源端 CPU 使用率为 47%,开启 RedisShake 后,源端 CPU 使用率为 91%。
rdb_reader
可以使用 rdb_reader 来从 RDB 文件中读取数据,然后写入目标端。常见于从备份文件中恢复数据。
Scan Reader 实现异地灾备
- Redis哨兵7.4.3
- Helm Redis 20.13.4
- Kubernetes 1.29.0
Kubernetes Redis哨兵部署
Redis部署可以采用容器,虚拟机,阿里云等。对于Redis部署方式没有要求
添加helm源
helm repo add bitnami https://charts.bitnami.com/bitnami
将redis包下载本地
helm pull bitnami/redis --version 20.13.4 --debug
安装redis哨兵
#源端Redis
helm install redis-sentinel -n tools .
#目标端Redis
helm install redis-sentinel-bak -n tools .
修改密码以及storageClass配置,这里我有默认的,我这里就只修改密码
vim redis-sentinel/values.yaml
## 全局配置
global:
imageRegistry: ""
imagePullSecrets: []
defaultStorageClass: ""
storageClass: ""
security:
allowInsecureImages: false
redis:
password: "123321.."
当源端Redis和目标Redis安装完毕后,我们这里看下Redis Pod和SVC状态
- redis-sentinel-node 为源端
- redis-sentinel-bak-node 为目标端
root@k8s-master-01:~/redis/helm/redis-sentinel# kubectl get pod,svc -n tools|grep redis
pod/redis-sentinel-bak-node-0 3/3 Running 0 113s
pod/redis-sentinel-bak-node-1 3/3 Running 0 85s
pod/redis-sentinel-bak-node-2 3/3 Running 0 62s
pod/redis-sentinel-node-0 3/3 Running 3 (21h ago) 4d1h
pod/redis-sentinel-node-1 3/3 Running 3 (21h ago) 4d1h
pod/redis-sentinel-node-2 3/3 Running 0 21h
service/redis-sentinel NodePort 10.96.1.143 <none> 6379:31803/TCP,26379:30295/TCP 4d1h
service/redis-sentinel-bak ClusterIP 10.96.1.220 <none> 6379/TCP,26379/TCP 113s
service/redis-sentinel-bak-headless ClusterIP None <none> 6379/TCP,26379/TCP 113s
service/redis-sentinel-bak-metrics ClusterIP 10.96.0.189 <none> 9121/TCP 113s
service/redis-sentinel-headless ClusterIP None <none> 6379/TCP,26379/TCP 4d1h
service/redis-sentinel-metrics ClusterIP 10.96.3.148 <none> 9121/TCP 4d1h
镜像如果出现问题,可以尝试使用代理加速dockerproxy.frps.fun
修改configmap配置文件
只需要修改Redis源端的缓冲区配置
client-output-buffer-limit replica 0 0 0
- replica
该配置项针对复制缓冲区 - 512mb
将缓冲区大小的上限设为512M - 128mb和60
若连续60s内写入量>128M,也会触发缓冲区溢出
这设置何用?
假设一条写命令数据是1KB,则复制缓冲区可积压512K条(512MB/1KB = 512K)写命令。
M在全量复制期间,可承受写命令速率上限=2000条/s(128MB/1KB/60≈2000)。
这就得到一种方案,设置复制缓冲区大小时: - 根据写命令数据的大小 && 实际负载情况(即写命令速率),估计缓冲区中会积压的写命令数据量
- 再和所设置的复制缓冲区大小比较,判断设置的缓冲区是否够支撑积压的写命令数据量
由于M复制缓冲区的内存开销,会是每个R客户端输出缓冲区占用内存的总和。若集群中的R很多,M内存开销就很大。所以还得控制和M连接的R个数,不要使用大规模主从集群。
这里我直接不限制,设置为0 0 0。生产环境需要根据业务实际情况填写
root@k8s-master-01:~# kubectl get cm -n tools|grep configuration
redis-sentinel-bak-configuration 5 16m
redis-sentinel-configuration 5 4d1h
编辑configmap
root@k8s-master-01:~# kubectl edit cm -n tools redis-sentinel-configuration
在replica.conf下添加
replica.conf: |-
dir /data
# User-supplied replica configuration:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
# End of replica configuration
client-output-buffer-limit replica 0 0 0
重启Redis
root@k8s-master-01:~# kubectl get pod -n tools|grep sentinel|grep -v bak|awk -F "[ ]+" '{print $1}'|xargs kubectl delete pod -n tools
#输出日志
pod "redis-sentinel-node-0" deleted
pod "redis-sentinel-node-1" deleted
pod "redis-sentinel-node-2" deleted
进入容器查看Redis哨兵状态
root@k8s-master-01:~# kubectl exec -it -n tools redis-sentinel-node-0 bash
执行info replication
127.0.0.1:6379> auth 123321 #根据我们设置的密码登录
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=redis-sentinel-node-1.redis-sentinel-headless.tools.svc.cluster.local,port=6379,state=online,offset=268257,lag=1
slave1:ip=redis-sentinel-node-2.redis-sentinel-headless.tools.svc.cluster.local,port=6379,state=online,offset=268257,lag=0
master_failover_state:no-failover
master_replid:b3528d84ce8f64492822540e1d314cb3ce513735
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:268257
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:268257
Kubernetes部署RedisShake
官方作者没有出Docker镜像,我们这边直接使用作者的Dockerfile自行打包
git clone https://github.com/tair-opensource/RedisShake.git
cd RedisShake/
打包镜像
docker build -t test:v1 .
设置标签
docker tag test:v1 abcdocker9/redisshake:4.4.1
推送Docker hub
docker push abcdocker9/redisshake:tagname
配置文件说明
sync_reader 配置(源端Redis同步设置)
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
cluster | bool | false | 源端是否为Redis集群模式 |
address | string | "127.0.0.1:6379" | 集群模式下可指定任意节点地址;主从模式需使用主/从节点地址 |
username | string | "" | ACL未启用时留空 |
password | string | "" | 认证需求时留空 |
tls | bool | false | 启用TLS加密传输 |
sync_rdb | bool | true | 是否同步RDB快照数据 |
sync_aof | bool | true | 是否同步AOF日志数据 |
prefer_replica | bool | false 优先从副本节点同步 | |
try_diskless | bool | false | 源端启用repl-diskless-sync时设为true |
redis_writer 配置(目标端写入设置)
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
cluster | bool | false | 目标端是否为Redis集群 |
address | string | "127.0.0.1:6380" | 集群模式下可指定任意节点地址 |
username | string | "" | ACL未启用时留空 |
password | string | "" | 无认证需求时留空 |
tls bool | false | 启用TLS加密传输 | |
off_reply | bool | false | 关闭服务端响应(提升性能) |
filter 配置(数据过滤规则)
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
allow_keys | list | [] | 白名单键名列表 |
allow_key_prefix | list | [] | 键名前缀白名单 |
block_keys | list | [] | 黑名单键名列表 |
block_key_prefix | list | [] | 键名前缀黑名单 |
function | string | "" | 自定义过滤脚本路径 |
advanced 配置(高级参数)
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
ncpu | int | 0 | 使用CPU核心数(0=自动检测) |
log_level | string | "info" | 日志级别(debug/info/warn) |
pipeline_count_limit | int | 1024 | 流水线操作最大并发数 |
aws_psync | string | "" | AWS特殊同步协议配置 |
module 配置(模块兼容性)
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
target_mbbloom_version | int | 20603 | Tair模块兼容版本号 |
创建ConfigMap
ConfigMap里面需要配置源端地址以及目标地址
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-shake-config
namespace: tools
data:
shake_sync_env.toml: |
[sync_reader]
sync_mode = true
cluster = false
address = "127.0.0.1:6379" #修改为redis-sentinel.tools.svc.cluster.local
username = ""
password = "123321" #设置Redis密码
tls = false
sync_rdb = true
sync_aof = true
prefer_replica = false
try_diskless = false
[redis_writer]
cluster = false
address = "127.0.0.1:6380" #修改为redis-sentinel-bak.tools.svc.cluster.local
username = ""
password = "123321" #设置Redis密码
tls = false
off_reply = false
[filter]
allow_keys = []
allow_key_prefix = []
allow_key_suffix = []
allow_key_regex = []
block_keys = []
block_key_prefix = []
block_key_suffix = []
block_key_regex = []
allow_db = []
block_db = []
allow_command = []
block_command = []
allow_command_group = []
block_command_group = []
function = ""
[advanced]
dir = "data"
ncpu = 0
pprof_port = 0
status_port = 0
log_file = "shake.log"
log_level = "info"
log_interval = 5
log_rotation = true
log_max_size = 512
log_max_age = 7
log_max_backups = 3
log_compress = true
rdb_restore_command_behavior = "panic"
pipeline_count_limit = 1024
target_redis_client_max_querybuf_len = 1073741824
target_redis_proto_max_bulk_len = 512000000
aws_psync = ""
empty_db_before_sync = false
[module]
target_mbbloom_version = 20603
创建Deployment
代理地址docker pull dockerproxy.frps.fun/abcdocker9/redisshake:4.4.1
官方地址abcdocker9/redisshake:4.4.1
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-shake
namespace: tools
spec:
selector:
matchLabels:
app: redis-shake # 必须与template中的labels完全匹配
template:
metadata:
labels:
app: redis-shake # 必须包含selector中定义的所有标签
spec:
containers:
- name: redis-shake
image: dockerproxy.frps.fun/abcdocker9/redisshake:4.4.1
env:
- name: SYNC
value: "true" # 必须设置为true或false
volumeMounts:
- name: config-volume
mountPath: /app/shake_sync_env.toml
subPath: shake_sync_env.toml
volumes:
- name: config-volume
configMap:
name: redis-shake-config
创建完毕后,我们查看Pod状态以及启动日志
root@k8s-master-01:~/redis/redis-shake# kubectl get pod -n tools
NAME READY STATUS RESTARTS AGE
blackbox-exporter-7b5545fd5-h6k29 1/1 Running 3 (27h ago) 7d16h
categraf-snmp-69f6d68bc7-trjt8 1/1 Running 3 (27h ago) 7d16h
dnsmgr-web-76f6b675fc-xjnxl 1/1 Running 0 27h
excalidraw-9587f9469-b6srm 1/1 Running 1 (27h ago) 4d11h
grafana-6bd875d986-28ndq 1/1 Running 1 (27h ago) 27h
node-exporter-b2q6c 1/1 Running 5 (27h ago) 14d
node-exporter-d2qdv 1/1 Running 7 (27h ago) 14d
node-exporter-mjlxr 1/1 Running 6 (27h ago) 14d
node-exporter-nhktv 1/1 Running 5 (27h ago) 14d
node-exporter-s67cl 1/1 Running 7 (27h ago) 14d
node-exporter-t4jh6 1/1 Running 6 (27h ago) 14d
prometheus-58d5674548-nzmqd 1/1 Running 0 27h
redis-sentinel-bak-node-0 3/3 Running 0 6h36m
redis-sentinel-bak-node-1 3/3 Running 0 6h35m
redis-sentinel-bak-node-2 3/3 Running 0 6h35m
redis-sentinel-node-0 3/3 Running 0 6h16m
redis-sentinel-node-1 3/3 Running 0 6h15m
redis-sentinel-node-2 3/3 Running 0 6h15m
redis-shake-7dc486f775-zl4fm 1/1 Running 2 (36s ago) 40s
root@k8s-master-01:~/redis/redis-shake# kubectl logs -f -n tools redis-shake-7dc486f775-zl4fm
2025-07-22 15:42:21 INF load config from file: shake_sync_env.toml
2025-07-22 15:42:21 INF log_level: [info], log_file: [/app/data/shake.log]
2025-07-22 15:42:21 INF changed work dir. dir=[/app/data]
2025-07-22 15:42:21 INF GOMAXPROCS defaults to the value of runtime.NumCPU [8]
2025-07-22 15:42:21 INF not set pprof port
2025-07-22 15:42:21 INF create SyncStandaloneReader
2025-07-22 15:42:21 INF * address: redis-sentinel.tools.svc.cluster.local:6379
2025-07-22 15:42:21 INF * username:
2025-07-22 15:42:21 INF * password: ********
2025-07-22 15:42:21 INF * tls: false
2025-07-22 15:42:21 INF create RedisStandaloneWriter
2025-07-22 15:42:21 INF * address: redis-sentinel-bak.tools.svc.cluster.local:6379
2025-07-22 15:42:21 INF * username:
2025-07-22 15:42:21 INF * password: ********
2025-07-22 15:42:21 INF * tls: false
2025-07-22 15:42:21 INF start syncing...
2025-07-22 15:42:21 INF [reader_redis-sentinel.tools.svc.cluster.local_6379] source db is not doing bgsave! continue.
2025-07-22 15:42:26 INF read_count=[2788], read_ops=[0.00], write_count=[2788], write_ops=[0.00], syncing aof, diff=[0]
2025-07-22 15:42:31 INF read_count=[2788], read_ops=[557.55], write_count=[2788], write_ops=[557.55], syncing aof, diff=[0]
2025-07-22 15:42:36 INF read_count=[2788], read_ops=[0.00], write_count=[2788], write_ops=[0.00], syncing aof, diff=[0]
2025-07-22 15:42:41 INF read_count=[2788], read_ops=[0.00], write_count=[2788], write_ops=[0.00], syncing aof, diff=[0]
2025-07-22 15:42:46 INF read_count=[2788], read_ops=[0.00], write_count=[2788], write_ops=[0.00], syncing aof, diff=[0]
2025-07-22 15:42:51 INF read_count=[2788], read_ops=[0.00], write_count=[2788], write_ops=[0.00], syncing aof, diff=[0]
模拟数据写入
手动到源端Redis写入数据
root@k8s-master-01:~/redis/redis-shake# kubectl exec -it -n tools redis-sentinel-node-0 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "redis" out of: redis, sentinel, metrics
$ redis-cli
127.0.0.1:6379> auth [密码]
OK
127.0.0.1:6379> set abcdocker i4t
OK
127.0.0.1:6379>
接下来到目标端查看数据
root@k8s-master-01:~/redis/redis-shake# kubectl exec -it -n tools redis-sentinel-bak-node-0 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "redis" out of: redis, sentinel, metrics
$ redis-cli
127.0.0.1:6379> auth [密码]
OK
127.0.0.1:6379> get abcdocker
"i4t"
127.0.0.1:6379>
正常监听日志
常见问题
RedisShake 运行状态日志说明
开启同步时,输出Debug日志,对应参数解释如下
- read_count # 读取数量
- read_ops # 读取qps
- write_count # 写入数量
- wirte_ops # 写入qps
- diff # 已读取数据还未写入
- syncing aof # 使用aof同步
全量是RDB文件,增量是aof数据流,RedisShake会接受全量和增量将其暂存到磁盘上。
当redis-share出现read: connection reset by peer
#完整日志如下
ERR read tcp 192.168.1.1:52646->10.1.1.1:6379: read: connection reset by peer
RedisShake/internal/reader/sync_standalone_reader.go:457 -> (*syncStandaloneReader).receiveAOF()
runtime/asm_amd64.s:1650 -> goexit()
解决办法
#将平台参数值调大,具体大小还是要根据实际业务情况
client-output-buffer-limit replica 0 0 0
- replica
该配置项针对复制缓冲区 - 512mb
将缓冲区大小的上限设为512M - 128mb和60
若连续60s内写入量>128M,也会触发缓冲区溢出
这设置何用?
假设一条写命令数据是1KB,则复制缓冲区可积压512K条(512MB/1KB = 512K)写命令。
M在全量复制期间,可承受写命令速率上限=2000条/s(128MB/1KB/60≈2000)。
这就得到一种方案,设置复制缓冲区大小时: - 根据写命令数据的大小 && 实际负载情况(即写命令速率),估计缓冲区中会积压的写命令数据量
- 再和所设置的复制缓冲区大小比较,判断设置的缓冲区是否够支撑积压的写命令数据量
由于M复制缓冲区的内存开销,会是每个R客户端输出缓冲区占用内存的总和。若集群中的R很多,M内存开销就很大。所以还得控制和M连接的R个数,不要使用大规模主从集群。
断点续传
支持断开后按offset恢复,无需额外配置
缓存日志及Log日志存储路径
- redis-shake 默认目录为/apps
- data 存储日志以及AOF文件
- data/shake.log 运行状态一直,可以看到redis-shake运行状态
root@k8s-master-01:~/redis/redis-shake# kubectl exec -it -n tools redis-shake-7dc486f775-zl4fm sh
/app # ls
data entrypoint.sh redis-shake shake_scan_env.toml shake_sync_env.toml
/app # ls data/
pid.lockfile shake.log
reader_redis-sentinel.tools.svc.cluster.local_6379
/app # ls data/reader_redis-sentinel.tools.svc.cluster.local_6379/
0.aof
/app # tail data/shake.log
{"level":"info","time":"2025-07-22T16:00:56Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:01Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:06Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:11Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:16Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:21Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:26Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:31Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:36Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
{"level":"info","time":"2025-07-22T16:01:41Z","message":"read_count=[2790], read_ops=[0.00], write_count=[2790], write_ops=[0.00], syncing aof, diff=[0]"}
注意事项
- 长时间无同步流量导致的,Shake 确实缺乏保活机制,在长时间无同步是可能会被杀掉 (Pod不存在此问题)
- 集群的writer速度太快。可能存在超时导致失败情况,需要定时日志监控
- 目前Redis-Shake无法检测灾备状态,短暂需要人为操作,用于迁移工具实际作用更大