zoukankan      html  css  js  c++  java
  • Redis Cluster 剔除节点失败

    Redis Cluster 剔除节点失败

    Redis Cluster 采用无中心的集群模式,集群中所有节点通过互相交换消息来维持一致性。当有新节点需要加入集群时,只需要将它与集群中的一个节点建立联系即可,通过集群间节点互相交换消息所有节点都会互相认识。所以当需要剔除节点的时候,需要向所有节点发送 cluster forget 命令。

    而向集群所有节点发送命令需要一段时间,在这段时间内已经接收到 cluster forget 命令的节点与没有接收的节点会发生信息交换,从而导致 cluster forget 命令失效。

    为了应对这个问题 Redis 设计了一个黑名单机制。当节点接收到 cluster forget 命令后,不仅会将被踢节点从自身的节点列表中移除,还会将被剔除的节点添加入到自身的黑名单中。当与其它节点进行消息交换的时候,节点会忽略掉黑名单内的节点。所以通过向所有节点发送 cluster forget 命令就能顺利地剔除节点。

    但是黑名单内的节点不应该永远存在于黑名单中,那样会导致被踢掉的节点不能再次加入到集群中,同时也可能导致不可预期的内存膨胀问题。所以黑名单是需要有时效性的,Redis 设置的时间为一分钟。

    所以当剔除节点的时候,在一分钟内没能向所有节点发出 cluster forget 命令,会导致剔除失败,尤其在集群规模较大的时候会经常发生。

    解决方案:
    1、多个进程发送 cluster forget 命令
    2、每次只forget一个节点(适用于节点数较少时)

    批量清理失效节点脚本:

    #!/bin/bash 
    
    for i in `cat test`
    do
      host=`echo $i | awk -F ':' '{print $1}'`
      port=`echo $i | awk -F ':' '{print $2}'`
      # 获取指定单节点的node id。主要用于集群节点过多时,forget多个节点时,花费时间过长,导致已被删除的节点又从其他节点同步过来,导致forget失败
      # del_nodeids=$(redis-cli -h $host -p $port cluster nodes|grep -E 'handshake|fail'| grep '127.0.0.1:6379' | awk '{print $1}')
      del_nodeids=$(redis-cli -h $host -p $port cluster nodes|grep -E 'handshake|fail' | awk '{print $1}')
      if [ -n "$del_nodeids" ];then
        for nodeid in ${del_nodeids[@]}; do
            echo $host $port $nodeid
            redis-cli -h $host -p $port cluster forget $nodeid
        done
      fi
    done
  • 相关阅读:
    WINCE6.0+S3C6410睡眠和唤醒的实现
    WINCE6.0+S3C6410的触摸屏驱动
    S3C6410的Bootloader的两个阶段BL1和BL2编译相关学习
    amix vim vimrc 3.6 [_vimrc x64 vim (WorkPlace)]配置
    异常的开销
    A C# Reading List by Eric Lippert (ZZ)
    SQL SERVER 2008中定时备份数据库任务的创建与删除
    ASP.NET26个常用性能优化方法
    如何使用四个语句来提高 SQL Server 的伸缩性
    Cookies揭秘 [Asp.Net, Javascript]
  • 原文地址:https://www.cnblogs.com/MacoLee/p/13897888.html
Copyright © 2011-2022 走看看