Post

Redis Cluster

Redis Cluster

Redis Cluster

  • redis提供了3中分布式方案
    • 主从模式、哨兵模式、集群模式
  • 主从和哨兵模式只是解决单点故障问题, 提高读并发性能
  • 集群模式则可以做到扩展redis的内存
    • 多组主从节点构成一个集群

集群节点初始化

  • 每个集群节点通过配置项开启集群功能
  • 启动redis-server, 进入clusterInit()
    • 此时节点生成了, 但是集群间是没有通信的
  • 每个开启集群的节点都有关于集群的信息(clusterState) (刚开始是默认值)
    • redis集群是去中心化的, 每个节点都存一份clusterState

配置文件

1
2
3
cluster-enabled yes # 打开集群模式
cluster-config-file nodes-6379.conf # 设定节点配置文件名
cluster-node-timeout 15000 # 设定节点失联时间, 超过该时间(毫秒), 集群自动进行主从切换

clusterState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct clusterNode {
    char name[REDIS_CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */
    int flags;      /* REDIS_NODE_... */
    unsigned char slots[REDIS_CLUSTER_SLOTS/8]; /* slots handled by this node */
    int numslots;   /* Number of slots handled by this node */
    int numslaves;  /* Number of slave nodes, if this is a master */
    struct clusterNode **slaves; /* pointers to slave nodes */
    struct clusterNode *slaveof; /* pointer to the master node */
} clusterNode;

typedef struct clusterState {
    clusterNode *myself;  /* This node */
    dict *nodes;          /* Hash table of name -> clusterNode structures */
    zskiplist *slots_to_keys;
} clusterState;

集群建立连接

  • redis-cli --cluster create --cluster-replicas {x} addr1 addr2 ...
    • --cluster-replicas用于指定有多少个备份节点(就是从节点, 用于故障切换)
    • 例如有addr1-addr4, 然后指定x=1(一个master有一个从节点)
      • addr1, addr2就会被设置成master
      • addr3, addr4分别是其从节点
  • 建立连接的过程就是每个节点将clusterState完善的过程
  • 除了nodes外, 主要要对master节点进行slot的分配

集群slot & 读写数据

  • slot的范围是[0 - 16*1024-1]
    • crc16(key) belongs [0 - 16*1024-1]
  • slot被划分给master节点
    • key会通过crc16(hash算法)计算应该落在哪个slot中
    • 每个节点通过一个bitmap来记录自己拥有哪些slot
      • bitmap就是unsigned char, 因为char是1字节, 因此分配REDIS_CLUSTER_SLOTS/8的空间
      • unsigned char slots[REDIS_CLUSTER_SLOTS/8]
  • 当写入数据时, 除了正常写数据, 还需要维护一个跳表
    • zskiplist *slots_to_keys
    • 这个跳表中score是hashslot(类似于slot的index), redisObject是key
      • zslInsert(server.cluster->slots_to_keys,hashslot,key)
    • 这个跳表可以用于快速判断自己拥有的slot中, 哪些有数据
      • zslFirstInRange(server.cluster->slots_to_keys, &range)

集群新增/移除节点 & slot迁移

  • 当集群新加入一个节点时, 这个新节点是不拥有slot的(此时这个新节点不能进行读写)
  • 此时需要从其他节点中迁移slot (reshard)
    • redis-cli --cluster reshard addr1
  • 删除节点同样需要reshard slot
    • 这里的删除不是发生故障, 而是将节点从集群中除去

集群的故障转移

  • 集群通过内部机制实现故障转移, 与哨兵机制不同
  • redis集群是去中心化的
    • 各master之间互相发送Ping/Pong信息
  • 当某个节点发现另一个节点故障(此时为主观故障)
    • 然后它向剩余节点发送FAIL消息, 要求剩下的节点进行投票
    • 当超过半数节点认为节点主观故障, 则标记为客观故障
  • 出现客观故障节点后, 进行故障转移
    • 从它的从节点中选一个成为master
This post is licensed under CC BY 4.0 by the author.