文章目录

Toggle

- 什么是 RedisShake
- 架构图
- Sync Reader
- Scan Reader
- rdb_reader
- Scan Reader 实现异地灾备Kubernetes Redis哨兵部署
- Kubernetes部署RedisShake
- 模拟数据写入
常见问题
- RedisShake 运行状态日志说明
- 当redis-share出现read: connection reset by peer
- 断点续传
- 缓存日志及Log日志存储路径
- 注意事项

什么是 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 通过自定义脚本实现数据过滤和转换。

无标题-2025-07-23-0016.png

上图是SYNC模式下全量+增量的数据流图,第一次复制向源端发送了之后,源端给它发RDB文件,解析RDB文件放到Pipe中。

它可以通过并发Restore到目的端,同步完成之后就会自动启动增量。增量就是从源端拉取写命令,进行解析过滤,然后再放到目的端,同时还需要接收回复。

架构图


当源端和目的端为单实例节点(Standalone)时,同步架构图如下。

1753150971883.png

当源端和目的端都为集群(Cluster)时,同步架构图如下。

从架构图可以看到,数据从源端(Source)同步到目的端(Destination),主要经过 Cluster Reader、Main、Cluster Writer 三部分处理。

**Cluster Reader**

Cluster Reader 即集群读入类,其根据源端分片数量创建同等数量的 Standalone Reader,每个 Standalone Reader 开启一个协程(Goroutinue)并行的从每个源端分片进行读入,并将数据存入相应的管道(Reader Channel)交付给下一环节处理。

1753150996412.png

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 阶段是增量同步。

**全量数据**

1753202255580.png

DbSyncer维护了连接链路,它是一个结构体,源端是6379,目的端是一个集群,它代表了一个数据链路。

假如说原来配置的是一个三主三从的集群模式,那么就会开启三个DbSyncer,同时有ID对它进行标识。每个DbSyncer管理一个连接,如6379首先是向RDB文件发送过来,然后Loader会解析出一些信息,包括DB、Key、Type等,然后放到Pipe中。然后需要向目的端写入,写入的时候全量模式支持并发。

从Pipe出来后先进行过滤,因为RedisShake支持DB、Key、Slot这些级别的过滤,用户可以设置黑白名单。正常情况下就可以Restore到目的端,然后再接收回复。对于lua ,可以进行script load,也可以设置过滤lua。对于BigKey,需要根据编码形式进行拆分解析。

**增量数据**

1753202302877.png

全量同步结束之后会自动开启增量同步,增量同步主要是由四个协程完成。

- 第一个协程定期从源端获取RedisShake的偏移量。
- 第二个协程主要是从源端拉取写命令。因为原来是模拟源端的一个从,从执行写命令的时候会发送一条Binlog到RedisShake,RedisShake读到之后交给Decoder,然后会将Binlog解析成一个原生命令,同时还会计算一下偏移量。得到命令后有Key,然后就可以进行过滤,再放到Sendbuffer中,Sendbuffer就是最终要发送到目的端的一些写命令。
- 第三个协程就是Sender,它执行发送逻辑,从Sendbuffer中取出写命令,并不是立即发送过去,它是和Checkpoint绑成一个事务,一块写入目的端。断点续传的原理是会先放到cache里边,就像是一层缓存,然后触发一定条件之后就去执行sendFunc函数。这是一个事务,它会先去写这些增数据,然后再去修改Checkpoint值。

针对于Redis Cluster同步,可以参考下图

1753202438033.png

首先源客户发送了一个“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]


1753199051893.png

模拟数据写入


手动到源端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>


正常监听日志

1753199525869.png

常见问题


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无法检测灾备状态,短暂需要人为操作,用于迁移工具实际作用更大