Redis Cluster的noaddr标记

某业务Redis Cluster中一个节点的负载较高,要将其负责的部分slot迁移到另一个节点。查看集群状态时,出现了flags字段为noaddr的标记。

 

192.168.1.4:2008> cluster nodes

78641a9cf0098e1c5c07821266dcd1feae21bcd3 :0 slave,noaddr - 1530942381678 1530942361875 0 disconnected

2122990aa0f8b5fae63b36d1a598e5194c72c0d0 :0 master,noaddr - 1530943527689 1530943524090 0 disconnected

...

 

cluster nodes显示的每一行信息,由下面的字段组成。

<id> <ip:port> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>

 

每个字段的含义如下:

1. id: 节点ID,一个40字节的随机字符串,节点创建时生成,且不会变化(除非使用CLUSTER RESET HARD命令)。

2. ip:port: 客户端访问的地址。

3. flags: 逗号分隔的标记位,可能值有:myself, master, slave, fail?, fail, handshake, noaddr, noflags。

4. master: 若是已知master节点的slave,这里出现的是master的节点ID,否则是"-"。

5. ping-sent: 最近一次发送ping的unix毫秒时间戳,0代表没有发送过。

6. pong-recv: 最近一次收到pong的unix毫秒时间戳。

7. config-epoch: 该节点或其master节点的epoch值。每次故障转移都会生成一个新的,唯一的,递增的epoch值。若多个节点竞争相同的slot,epoch值大的获胜。

8. link-state: 节点和集群总线间的连接状态,可以是connected或disconnected。

9. slot: 该节点负责的slot。

 

flags字段各标记含义如下:

myself: 当前连接的节点。

master: 节点是master。

slave: 节点是slave。

fail?: 节点处于pfail状态,当前节点无法和其联系,但其它节点可以。

fail: 节点处于fail状态,大多数节点都无法和其联系,将其由pfail升级到fail状态。

handshake: 还没完全加入集群,正在握手阶段。

noaddr: 不知道节点地址。

noflags: 没有任何标记。

 

 

根据noaddr的含义,可知有此标记的节点属于无用节点,需将这些信息清除。由于无法连接节点,命令redis-trib.rb del-node host:port node_id无能为力了,只能使用CLUSTER FORGET node-id。

 

当节点接收到CLUSTER FORGET node-id命令后,会把node-id指定的节点加入到禁用列表中,在禁用列表内的节点不再发送Gossip消息。禁用列表有效期为60秒,超过60秒节点会再次参与消息交换。也就是说第一次forget命令发出后,需60秒内在集群各节点上执行forget命令。可借助脚本完成整个过程,实现思路如下:

 

1. 手动找到noaddr标记对应的node-id。

 

2. 脚本内容。

#!/bin/bash

 

flags_noaddr_node_id="f2c9d6445359372bc7efbe16e53cdaa2d7b38923"

 

ip_port=$(redis-cli -h 192.168.1.4 -p 2008 cluster nodes | egrep -v 'noaddr|handshake|fail' | awk '{print $2}')

 

for i in $ip_port

do

  eval $(echo $i | awk -F: '{printf("ip=%s;port=%s",$1,$2)}')

  redis-cli -h $ip -p $port cluster forget $flags_noaddr_node_id

 

  #flags_noaddr_node_id=$(redis-cli -h $ip -p $port cluster nodes | grep 'noaddr' | awk '{print $1; exit; }')

  #test -n "$flags_noaddr_node_id" && echo $ip, $port, $flags_noaddr_node_id

 

done

 

 

另,此组集群同时还遇到了handshake标记,若按上述思路处理是不行的,发现node-id会变化。

a7cdf970443175c75d53106ddbaec7c23876d66e 192.168.1.6:2008 handshake - 1533610367224 0 0 disconnected

011f3b9f9459c74cea0da37632bfc10ff99b426c 192.168.1.6:2008 handshake - 1533610420268 0 0 disconnected

 

其实,此处handshake是由fail?引起的,按上述思路处理了fail?,handshake会稍后消失,至此整个集群的状态正常了。

f2c9d6445359372bc7efbe16e53cdaa2d7b38923 192.168.1.6:2008 slave,fail? c274d9bbea72ca627b2e4795317af46c81755f9c 1531106329711 1531106032261 37 disconnected

 

至于node-id发生变化的原因,可参考这两个链接。

https://github.com/antirez/redis/issues/2965

https://githubmota.github.io/2018/06/15/TODO/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值