Redis-Cluster模式基操篇

Redis-Cluster故障转移与模式转换实战教程

在这里插入图片描述

一、场景

1、搞一套6个主节点的Cluster集群
2、模拟数据正常读写
3、模拟单点故障
4、在不停服务的情况下将集群架构改为3主3从

二、环境规划

6台独立的服务器,端口18001~18006

192.169.14.121
192.169.14.122
192.169.14.123
192.169.14.124
192.169.14.125
192.169.14.126

Redis–6.2.14版本
CentOS Linux release 7.6.1810

三、Redis-Cluster部署(6主模式)

1、Redis安装(6节点分别执行)

# 上传软件到/opt下
tar -zxvf redis-6.2.14.tar.gz 
cd redis-6.2.14
make & make install

2、创建目录(6节点分别创建对应目录)

mkdir -p /data/redis-cluster-18001

3、准备配置文件(6节点分别创建对应配置)

vim /data/redis-cluster-18001/redis.conf
######测试环境就写最基础的配置了
port 18001
dir /data/redis-cluster-18001/
cluster-enabled yes
cluster-config-file nodes-18001.conf
cluster-node-timeout 5000
bind 0.0.0.0
protected-mode no
appendonly yes
maxmemory 10G
daemonize yes

4、启动Redis(6节点分别执行)

cd /opt
./redis-6.2.14/src/redis-server /data/redis-cluster-18001/redis.conf

由于配置文件中声明了是集群模式,所以启动后看进程是有集群标识的
在这里插入图片描述

5、初始化集群(任意节点执行)

cd /opt
/usr/local/redis-5.0.4/src/redis-cli --cluster create --cluster-replicas 1 192.168.5.100:8001 192.168.5.100:8002 192.168.5.100:8003 192.168.5.100:8004 192.168.5.100:8005 192.168.5.100:8006

在这里插入图片描述
非常方便哈,Redis从3.0版本开始支持Cluster模式,但是最开始需要借助ruby来安装。
从5.0版本开始,可以直接通过redis-cli --cluster的方式操作集群。

6、集群验证

cd /opt
./redis-6.2.14/src/redis-cli -c -h 192.168.14.121 -p 18001
192.168.14.121:18001> cluster nodes

在这里插入图片描述
可以看到16384个槽位均匀分配在各个节点上。

不过

这种全主架构在Redis-Cluster中是有单点故障问题的,如果其中任意一台服务器挂掉,整个Redis集群将不可读写

四、模拟单点故障并验证

在这里插入图片描述
同时查看cluster nodes
在这里插入图片描述

五、转为3主3从模式

因为Redis-Cluster模式下当有槽位不可用(不管槽位内是否有数据)时会导致整个集群不可用。
所以我们现在将6主模式改为3主3从模式

1、先将node4、5、6的槽位转移到node1、2、3上
在这里插入图片描述

redis-cli --cluster reshard 集群任意节点IP:端口 --cluster-from 源node-id --cluster-to 目标node-id --cluster-slots 转移的槽位数量 --cluster-yes

cd /opt
./redis-6.2.14/src/redis-cli --cluster reshard 192.168.14.121:18001 --cluster-from 3c01c7397471f52c1df4f05223de1bab80ac2b0f --cluster-to bcdb37c781a80ee7bf1c962917649b5a44ddec2f --cluster-slots 2701 --cluster-yes

最终效果
在这里插入图片描述

2、节点下线

redis-cli --cluster del-node 集群任意节点IP:端口 下线节点node-id

redis-cli  --cluster del-node 192.168.14.121:18001 b494529c8a6cea6a47d8f058ab43df220b30815c

在这里插入图片描述

3、下线节点以从节点身份重新加入集群

redis-cli --cluster add-node 新加节点IP:端口 集群任意节点IP:端口 --cluster-slave --cluster-master-id 主节点node-id

cd /opt
./redis-6.2.14/src/redis-cli --cluster add-node 192.168.14.124:18004 192.168.14.121:18001 --cluster-slave --cluster-master-id 1dbc5115472fd6b64a537b6d862f6ec5b9892340

在这里插入图片描述

最终效果
在这里插入图片描述

现在任意节点宕机会自动切换主从,也不会影响集群的正常使用。

彩蛋

如果在生产环境是否也可以做槽位迁移呢?,当然是可以的,因为Redis-Cluster提供ask重定向处理功能(应对操作的key正在发生迁移),不过还是需要在业务顶峰期操作。

在这里插入图片描述

<think> 我们遇到了一个新的错误信息:`Node redis-cluster-1.redis-cluster.middleware.svc.cluster.local:6380 replied with error: ERR Invalid node address specified: redis-cluster-0.redis-cluster.middleware.svc.cluster.local:6380`。这个错误发生在Redis集群初始化过程中,当我们尝试使用`redis-cli --cluster create`命令创建集群时。让我们分析可能的原因和解决方案。 ### 错误分析 1. **DNS解析问题**:节点名称(如`redis-cluster-0.redis-cluster.middleware.svc.cluster.local`)可能无法被正确解析为IP地址。每个节点在加入集群时都需要能够解析其他节点的域名。 2. **节点未准备好**:在执行初始化命令时,某些节点可能还未完全启动,导致无法识别其他节点地址。 3. **Redis版本兼容性问题**:不同节点可能运行不同版本的Redis,导致协议不兼容。 4. **网络策略限制**:Kubernetes网络策略可能阻止了节点之间的通信,特别是跨节点的通信。 5. **节点配置错误**:Redis节点的配置文件(如`cluster-enabled`)可能未正确设置为集群模式,导致节点拒绝加入集群。 ### 解决方案 #### 1. 验证DNS解析 在初始化Job的容器中,添加DNS解析检查命令,确保每个节点域名都能解析为正确的IP地址。修改Job的command部分: ```yaml command: - /bin/bash - -c - | set -e echo "开始Redis集群初始化..." # 验证节点DNS解析 for i in {0..5}; do echo "解析节点 redis-cluster-$i:" nslookup redis-cluster-$i.redis-cluster.middleware.svc.cluster.local done # 生成节点列表 NODES="" for i in {0..5}; do NODES="${NODES} redis-cluster-$i.redis-cluster.middleware.svc.cluster.local:6380" done # ... 其余部分保持不变 ``` #### 2. 确保节点已启动 在尝试初始化集群之前,等待所有节点准备好。我们可以使用循环检查每个节点是否响应`PING`命令。 ```yaml command: - /bin/bash - -c - | set -e echo "开始Redis集群初始化..." # 等待所有节点启动 for i in {0..5}; do until redis-cli -h redis-cluster-$i.redis-cluster.middleware.svc.cluster.local -p 6380 ping; do echo "节点 redis-cluster-$i 未就绪,等待10秒..." sleep 10 done echo "节点 redis-cluster-$i 已就绪." done # 生成节点列表 # ... (同上) ``` #### 3. 检查Redis集群配置文件 确保每个Redis节点都正确配置了集群模式。在Redis的配置文件中,必须包含: ```conf cluster-enabled yes cluster-node-timeout 15000 cluster-config-file nodes.conf ``` #### 4. 使用IP地址代替域名 如果DNS解析问题持续存在,可以考虑使用Pod的IP地址来初始化集群。但注意,在Kubernetes StatefulSet中,Pod重启后IP可能会变化,因此不推荐长期使用。但作为初始化Job的临时方案,可以尝试: ```yaml command: - /bin/bash - -c - | set -e echo "开始Redis集群初始化..." # 获取当前Pod的IP(仅用于调试,不推荐) # 注意:集群节点应该使用稳定的网络标识(如域名),所以这只是一个备选方案 # 等待节点并获取IP nodes=() for i in {0..5}; do until ip=$(dig +short redis-cluster-$i.redis-cluster.middleware.svc.cluster.local); do echo "等待解析 redis-cluster-$i ..." sleep 5 done echo "节点 redis-cluster-$i 的IP: $ip" nodes+=("$ip:6380") done # 初始化集群 echo "初始化节点: ${nodes[*]}" redis-cli --cluster create "${nodes[@]}" --cluster-replicas 1 --cluster-yes # ... 其余部分 ``` #### 5. 检查网络策略 确保在`middleware`命名空间中,Redis Pod之间允许通信。检查NetworkPolicy是否允许6380端口的TCP通信。 ### 完整修复后的Job配置示例 ```yaml apiVersion: batch/v1 kind: Job metadata: name: redis-cluster-init namespace: middleware spec: backoffLimit: 2 template: spec: restartPolicy: OnFailure containers: - name: cluster-init image: 192.168.3.183:8001/library/redis:6.2.14 command: - /bin/bash - -c - | set -ex echo "===== 开始Redis集群初始化 =====" # 等待所有节点就绪(逐个检查) for i in {0..5}; do node_addr="redis-cluster-$i.redis-cluster.middleware.svc.cluster.local:6380" echo "等待节点 $node_addr 就绪..." until redis-cli -h redis-cluster-$i.redis-cluster.middleware.svc.cluster.local -p 6380 ping; do sleep 10 done echo "节点 $node_addr 已响应." done # 生成节点列表(使用数组避免空格问题) nodes=() for i in {0..5}; do nodes+=("redis-cluster-$i.redis-cluster.middleware.svc.cluster.local:6380") done # 初始化集群 echo "创建集群: ${nodes[*]}" redis-cli --cluster create "${nodes[@]}" \ --cluster-replicas 1 \ --cluster-yes # 验证集群状态 echo "验证集群状态..." redis-cli --cluster check ${nodes[0]} echo "===== Redis集群初始化成功! =====" ``` ### 关键点说明 - **`set -ex`**:开启详细执行日志,出错自动退出。 - **节点等待循环**:确保所有节点启动完成后再初始化。 - **数组存储节点地址**:避免字符串拼接造成空格问题。 - **`--cluster-yes`**:自动确认集群配置变更。 ### 相关问题 1. Kubernetes中StatefulSet的DNS解析机制是什么? 2. Redis集群初始化阶段如何避免节点地址解析失败? 3. 如何诊断Kubernetes中的网络策略问题? 4. Redis集群模式下节点间通信需要哪些端口? 5. 如何为Redis集群配置持久化存储以避免数据丢失?[^1] </think> ### Redis集群初始化错误分析:无效节点地址 在Redis集群初始化job中遇到`ERR Invalid node address specified`错误的主要原因如下: #### 错误原因分析 1. **DNS解析问题**(核心原因): - Kubernetes集群内DNS解析未完成时尝试创建集群[^1] - 域名`redis-cluster-X.redis-cluster.middleware.svc.cluster.local`尚未被集群DNS系统正确注册 - Job容器尝试连接尚未完全就绪的Redis节点 2. **节点启动顺序问题**: - StatefulSet中的Redis节点未完全启动就开始初始化 - 各节点启动速度不一致导致部分节点无法识别其他节点 3. **网络策略限制**: - Kubernetes网络策略可能阻止了节点间的通信 - Redis集群需要的端口(6380)未完全开放 4. **Redis配置问题**: - `cluster-enabled`配置未正确设置 - 节点未以集群模式启动 --- ### 完整解决方案 #### 修复后的Job配置(redis-cluster-job.yaml) ```yaml apiVersion: batch/v1 kind: Job metadata: name: redis-cluster-init namespace: middleware spec: backoffLimit: 3 # 增加重试次数 template: spec: restartPolicy: OnFailure containers: - name: cluster-init image: 192.168.3.183:8001/library/redis:6.2.14 command: - /bin/bash - -c - | set -ex # 启用详细日志和出错退出 echo "===== Redis集群初始化开始 =====" # 1. 确保DNS解析就绪 echo "验证DNS解析..." for i in {0..5}; do until nslookup redis-cluster-$i.redis-cluster.middleware.svc.cluster.local >/dev/null 2>&1; do echo "等待 redis-cluster-$i DNS解析..." sleep 10 done done # 2. 等待所有Redis节点就绪 echo "等待节点启动..." for i in {0..5}; do until redis-cli -h redis-cluster-$i.redis-cluster.middleware.svc.cluster.local -p 6380 ping >/dev/null 2>&1; do echo "节点 $i 未就绪,等待..." sleep 15 done done sleep 20 # 额外缓冲时间 # 3. 使用IP地址代替域名(备选方案) echo "获取节点IP地址..." nodes=() for i in {0..5}; do ip=$(getent hosts redis-cluster-$i.redis-cluster.middleware.svc.cluster.local | awk '{ print $1 }') nodes+=("$ip:6380") done # 4. 创建集群(双保险方案) echo "初始化集群..." if ! redis-cli --cluster create "${nodes[@]}" \ --cluster-replicas 1 \ --cluster-yes; then # 回退到域名方式(某些环境IP可能变化) echo "使用IP方式失败,尝试域名方式..." redis-cli --cluster create \ redis-cluster-0.redis-cluster.middleware.svc.cluster.local:6380 \ redis-cluster-1.redis-cluster.middleware.svc.cluster.local:6380 \ redis-cluster-2.redis-cluster.middleware.svc.cluster.local:6380 \ redis-cluster-3.redis-cluster.middleware.svc.cluster.local:6380 \ redis-cluster-4.redis-cluster.middleware.svc.cluster.local:6380 \ redis-cluster-5.redis-cluster.middleware.svc.cluster.local:6380 \ --cluster-replicas 1 \ --cluster-yes fi # 5. 最终验证 echo "验证集群状态..." redis-cli --cluster check redis-cluster-0.redis-cluster.middleware.svc.cluster.local:6380 redis-cli -h redis-cluster-0 -p 6380 cluster info | grep -E 'cluster_state|cluster_slots_covered' echo "===== Redis集群初始化成功! =====" ``` #### 关键修复点说明 1. **DNS等待机制**: ```bash until nslookup redis-cluster-$i...; do sleep 10; done ``` 确保所有节点域名可解析[^1] 2. **节点就绪检查**: ```bash until redis-cli -h redis-cluster-$i ping; do sleep 15; done ``` 确认Redis进程已启动并响应 3. **双保险连接方式**: - 优先使用IP地址连接(避免DNS未刷新) - 域名方式作为备选方案(防止IP变化) 4. **延长等待时间**: `sleep 20` 确保所有节点完成握手和配置同步 --- ### 验证成功指标 1. **集群状态**: ```bash cluster_state:ok ``` 2. **槽位覆盖**: ```bash cluster_slots_covered:16384 ``` 3. **节点角色**: ```bash 3 master(s) | 3 slave(s) ``` --- ### 相关问题 1. Kubernetes StatefulSet中如何确保DNS解析顺序? 2. Redis集群初始化时需要开放哪些网络端口?[^1] 3. 如何诊断Kubernetes中的DNS解析问题? 4. Redis集群节点无法互通的常见网络策略配置有哪些? 5. 为什么Redis集群需要精确分配16384个槽位?[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值