惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
G
Google Developers Blog
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
P
Proofpoint News Feed
V
Visual Studio Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 叶小钗
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
博客园 - 聂微东
H
Help Net Security
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
量子位
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

i4T

OpenClaw在Macmini下网络HTTPS_Proxy代理配置 | i4T 容器化部署OpenClaw授权View权限对Kubernetes集群进行巡检故障排查 | i4T 初试VictoriaLogs集群采集Kubernetes Pod日志 | i4T Kubernetes 部署Elasticsearch为WordPress提供文章搜索 | i4T Kubernetes使用Prometheus监控爱快路由器iKuai_Exporter | i4T RustDesk API集成Authentik ODIC单点登录 | i4T Kubernetes 部署RustDesk API实现专业版功能及管理Web UI | i4T 使用Kubernetes 快速部署RustDesk替换向日葵toDesk进行远程连接 | i4T Authentik 集成群晖Synology DSM 实现单点登录 | i4T Authentik 集成Kubernetes Grafana 实现SSO单点登录 | i4T Authentik 集成接入VMware vCenter 8.0.3实现ldP身份提供商登录 | i4T Kubernetes v1.29.9部署Authentik 统一认证平台并接入Harbor | i4T 二进制Kafka_2.13-3.9.0集群开启并配置ACL用户授权 | i4T R730 ESXI 8.0平台PCI直通2080Ti 实现Windows远程游戏以及AI模型 | i4T Dell R730虚拟化ESXI8.0.3平台使用丽台Tesla V100配置vGPU | i4T Kubernetes使用HostAliases手动为容器Pod添加hosts解析 | i4T Nginx 使用resolver变量实现动态DNS解析配置 | i4T Kubernetes LoadBalancer负载均衡外部访问方案MetalLB | i4T Kubernetes 1.29.0 部署配置Ingress-nginx-controller | i4T Ubuntu环境下Docker Compose配置Harbor开机自启 | i4T Dell PowerEdge R730更新iDRAC8版本 | i4T Kubernetes部署开源Excalidraw实现在线绘图 | i4T Kubernetes部署DNSmgr聚合公网DNS多平台域名解析系统及SSL自续签 | i4T Kubernetes Grafana数据从Sqlite3迁移到MySQL | i4T 宝塔内网Nginx获取公网宝塔Nginx用户真实IP | i4T 基于Kubernetes Categraf SNMP插件采集Dell R730服务器硬件并使用Grafana监控 | i4T Kubernetes v1.29.9安装Grafana 12并开启匿名访问 | i4T Containerd 配置免费镜像加速源 | i4T Docker集成Containerd实现容器管理 | i4T
Kubernetes部署RedisShake实现Redis哨兵异地灾备 | i4T
https://i4t.com/users/auuAwtzuk · 2025-07-23 · via i4T

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

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

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

架构图

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

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

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

Cluster Reader

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

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

全量数据

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

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

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

增量数据

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

  • 第一个协程定期从源端获取RedisShake的偏移量。

  • 第二个协程主要是从源端拉取写命令。因为原来是模拟源端的一个从,从执行写命令的时候会发送一条Binlog到RedisShake,RedisShake读到之后交给Decoder,然后会将Binlog解析成一个原生命令,同时还会计算一下偏移量。得到命令后有Key,然后就可以进行过滤,再放到Sendbuffer中,Sendbuffer就是最终要发送到目的端的一些写命令。

  • 第三个协程就是Sender,它执行发送逻辑,从Sendbuffer中取出写命令,并不是立即发送过去,它是和Checkpoint绑成一个事务,一块写入目的端。断点续传的原理是会先放到cache里边,就像是一层缓存,然后触发一定条件之后就去执行sendFunc函数。这是一个事务,它会先去写这些增数据,然后再去修改Checkpoint值。

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

Kubernetes部署RedisShake实现Redis哨兵异地灾备

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

Kubernetes部署RedisShake实现Redis哨兵异地灾备

模拟数据写入

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

正常监听日志
Kubernetes部署RedisShake实现Redis哨兵异地灾备

常见问题

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