Open Source, Open Future!
  menu
107 文章
ღゝ◡╹)ノ❤️

redis--集群

简介

* 从 3.0 版本开始支持。
* 采用无中心结构。
* 每个节点保存集群的部分数据。
* 每个节点保存集群中所有节点的信息(地址、角色、槽范围等)。
* 主节点提供读写。
* 从节点作为备用,复制主节点的数据。
* 整个集群包含 16384 个哈希槽。
* 可以分散单台服务器的访问压力和存储压力。

搭建

准备3台服务器,搭建3主3从(6个实例)集群。

IP端口
192.168.1.2016379
192.168.1.2016380
192.168.1.2026379
192.168.1.2026380
192.168.1.2036379
192.168.1.2036380
  1. 192.168.1.201服务器上 ,修改redis-6379.conf,添加配置:
# 开启集群功能
cluster-enabled yes 
# 记录集群状态
cluster-config-file nodes-6379.conf 
# 超时时间
cluster-node-timeout 15000
  1. 192.168.1.201服务器上 ,修改redis-6380.conf,添加配置:
# 开启集群功能
cluster-enabled yes 
# 记录集群状态
cluster-config-file nodes-6380.conf 
# 超时时间
cluster-node-timeout 15000
  1. 用同样的方式修改剩下的4个实例的配置。

  2. 启动6个实例。

  3. 输入命令:ps -ef |grep redis

    image.png

    可以看到有cluster标记

  4. 此时每个节点之间是孤立的,需要建立联系,输入以下命令:

redis-cli --cluster create 192.168.1.201:6379 192.168.1.201:6380 192.168.1.202:6379 192.168.1.202:6380 192.168.1.203:6379 192.168.1.203:6380 --cluster-replicas 1 
说明:
--replicas 1 // 表示每个master有1个slave

报错:

image.png

因为设置的有密码,所以命令中需要带上密码: -a 123456

image.png
image.png

当命令执行后,可以看到:

  • 分配了3个master:192.168.1.201:6379、192.168.1.202:6379、192.168.1.203:6379
  • 分配了3个 salve:192.168.1.201:6380、192.168.1.202:6380、192.168.1.203:6380
  • 192.168.1.201:6379的 salve为 192.168.1.202:6380
  • 192.168.1.202:6379的 salve为 192.168.1.203:6380
  • 192.168.1.203:6379的 salve为 192.168.1.201:6380
  • 每一个master与跟它对应的salve不在同一个服务器上
  • 192.168.1.201:6379分配的slots为[0-5460]
  • 192.168.1.202:6379分配的slots为[5461-10922]
  • 192.168.1.203:6379分配的slots为[10923-16383]

随便打开一个节点的node文件:

image.png

可以看到每个节点都会在文件中记录整个集群的所有节点的地址、角色等信息。

测试

master测试

比如 :192.168.1.201:6379

  1. 客户端连接
# 操作集群需要添加-c;-a 为密码
redis-cli -h 192.168.1.201 -p 6379 -c -a 123456
  1. 添加数据
192.168.1.201:6379> set a 1
-> Redirected to slot [15495] located at 192.168.1.203:6379
OK
192.168.1.203:6379> set b 2
-> Redirected to slot [3300] located at 192.168.1.201:6379
OK
192.168.1.201:6379> set c 3
-> Redirected to slot [7365] located at 192.168.1.202:6379
OK
192.168.1.202:6379> set d 4
-> Redirected to slot [11298] located at 192.168.1.203:6379
OK
192.168.1.203:6379> set e 5
OK
192.168.1.203:6379> mset f 6 g 7 h 8
(error) CROSSSLOT Keys in request don't hash to the same slot

插入了8个数据,成功了5个,可以看到:

  • 前面4次都基于某种规则,做了重定向;
  • 重定向后,下一次操作时,前面的ip也发生了变化;
  • 第5次没有重定向,是在当前节点操作;
  • 最后3个数据批量插入失败:key没有哈希到同一个slot中
  • 所有插入操作都是在master节点上处理。

每个节点存储的数据如下:
imagee2dde554.png

  1. 查询数据
192.168.1.203:6379> get a
"1"
192.168.1.203:6379> get b
-> Redirected to slot [3300] located at 192.168.1.201:6379
"2"
192.168.1.201:6379> get c
-> Redirected to slot [7365] located at 192.168.1.202:6379
"3"
192.168.1.202:6379> get d
-> Redirected to slot [11298] located at 192.168.1.203:6379
"4"
192.168.1.203:6379> get e
"5"
192.168.1.203:6379> 

查询了5个数据,可以看到:

  • 中间3次做了重定向;
  • 重定向后,下一次操作时,前面的ip也发生了变化
  • 第1次和第5次没有重定向,是在当前节点操作。
  • 5次查询操作都是在master节点上。
  1. 查询所有key
192.168.1.203:6379> keys *
1) "d"
2) "a"
3) "e"

查到的只有当前节点的数据。

  1. 删除数据
192.168.1.201:6379> del a
-> Redirected to slot [15495] located at 192.168.1.203:6379
(integer) 1
192.168.1.203:6379> del b
-> Redirected to slot [3300] located at 192.168.1.201:6379
(integer) 1
192.168.1.201:6379> del c
-> Redirected to slot [7365] located at 192.168.1.202:6379
(integer) 1
192.168.1.202:6379> del d
-> Redirected to slot [11298] located at 192.168.1.203:6379
(integer) 1
192.168.1.203:6379> del e
(integer) 1

删除了5个数据,可以看到:

  • 前面4次做了重定向;
  • 重定向后,下一次操作时,前面的ip也发生了变化
  • 最后一次没有重定向,是在当前节点操作。
  • 5次删除操作都是在master节点上。

每个节点存储的数据如下:

image6929abc6.png

slave测试

  1. 客户端连接
# 操作集群需要添加-c
redis-cli -h 192.168.1.201 -p 6380 -c -a 123456
  1. 添加数据
192.168.1.201:6380> set a 1
-> Redirected to slot [15495] located at 192.168.1.203:6379
OK
192.168.1.203:6379> set b 2
-> Redirected to slot [3300] located at 192.168.1.201:6379
OK
192.168.1.201:6379> set c 3
-> Redirected to slot [7365] located at 192.168.1.202:6379
OK
192.168.1.202:6379> set d 4
-> Redirected to slot [11298] located at 192.168.1.203:6379
OK
192.168.1.203:6379> set e 5
OK

请求经过某种规则后,做了重定向。所有的操作都由master处理。
每个节点存储的数据如下:

image.png

  1. 查询自己有的数据
192.168.1.201:6380> get a
-> Redirected to slot [15495] located at 192.168.1.203:6379
"1"

在192.168.1.201:6380节点上存在a,但是查询时仍然做了重定向,到对应的master。

  1. 删除自己有的数据
192.168.1.201:6380> del a
-> Redirected to slot [15495] located at 192.168.1.203:6379
(integer) 1

在192.168.1.201:6380节点上存在a,但是删除时仍然做了重定向,到对应的master。

image.png

节点操作

下线

  1. 下线192.168.1.201:6379,查看集群节点信息:

image.png

它对应的slave自动提升为master,并且查看任一个节点本地的nodes.conf文件,都会有更新:

image.png

  1. 上线192.168.1.201:6379,查看集群节点信息:

image.png

它的角色为slave。

新增master

把新节点192.168.1.203:6381加入集群:

redis-cli --cluster add-node 192.168.1.203:6381 192.168.1.203:6379 -a 123456

image.png

查看集群节点信息:

image.png

已经加入到了集群中,角色为master,对应的槽为空。

分配槽

为新加入的节点分配槽:

redis-cli --cluster reshard 192.168.1.203:6381 -a 123456

5.png

查看集群节点信息:

image.png

新增slave

将192.168.1.202:6381加入集群,并成为192.168.1.203:6381的slave:

redis-cli --cluster add-node 192.168.1.202:6381 192.168.1.203:6381  --cluster-slave --cluster-master-id 9441bcc05bb58ae0ec6a33cbf7b16a24781286ed -a 123456

查看集群节点信息:

image.png

删除slave

将192.168.1.202:6381从集群中剔除:

redis-cli --cluster del-node 192.168.1.202:6381 62f03b4a3079d90c4cb7ebd0abe3b0bb3b3fe98b -a 123456

image.png

查看集群节点信息:

image.png

192.168.1.202:6381节点已经消失了。

删除master

删除master时,需要先把上面的槽转移走,否则会报错:

image.png

使用前面提到的分配槽命令redis-cli --cluster reshard处理后,再删。

原理

  • Redis集群将所有的存储空间分成了16384个槽(0~16383),每个master节点维护其中一部分槽。
  • 每个节点都会在本地保存集群中所有节点的状态信息(地址、槽记录等)。

处理请求

向某个节点发出请求,处理流程:
   1.先通过计算(CRC16(key)&16383)找到key对应的槽;
   2.若当前节点是slave,则重定向到相关的master上处理;
   3.若槽不在当前节点上,则重定向到相关的master上处理;
   4.若槽在当前节点上且当前节点是master,则由当前节点处理。

计算key对应的槽算法见: Redis--集群--哈希算法

故障检测

* 集群中的每个节点会定期向其他节点发送PING信息,来检测对方是否在线;
* 若有节点没有在指定时间内返回PONG信息,则记录为疑似下线;
* 集群中的各个节点会互相交换记录的信息;
* 若有半数以上的master都认为某个节点下线了,则这个节点就会被标记为已下线。

故障转移

当master下线后,它的slave会自动成为master,流程如下:
  1.当某个slave发现自己的master宕机后,向集群广播一条信息;
  2.所有具有投票权且没有投过票的的master会对这个slave投票;
  3.若有投票权的master有N个,则当某个slave收到的票数>=N/2+1时,会当选为新的master。
  4.新master将旧master下的槽分配给自己;
  5.新master广播一条信息,让集群的其他节点知道自己的状态;
  6.接收和处理与自己的槽相关的请求。

其他操作

  • 查看集群节点
192.168.1.203:6379> cluster nodes
4a6a1a91240b9dec4688af57aea908fd6a94e0d4 192.168.1.203:6380@16380 slave 77cf784053fdc072e0b4dcad9fe9a17142c5a5e6 0 1587734251000 6 connected
3c7010e72bbe88e69efc6d78aebed1dcd071bddd 192.168.1.201:6380@16380 slave 67f6f91f94ac945c0d55622828e599570620f089 0 1587734251248 5 connected
199230e7f7411e451185a785fbdf35169716b283 192.168.1.202:6380@16380 slave 55109741ff5c52a9fc3a0212bb9ffbb96c6c2eb8 0 1587734253289 4 connected
55109741ff5c52a9fc3a0212bb9ffbb96c6c2eb8 192.168.1.201:6379@16379 master - 0 1587734254320 1 connected 0-5460
77cf784053fdc072e0b4dcad9fe9a17142c5a5e6 192.168.1.202:6379@16379 master - 0 1587734252266 3 connected 5461-10922
67f6f91f94ac945c0d55622828e599570620f089 192.168.1.203:6379@16379 myself,master - 0 1587734252000 5 connected 10923-16383
  • 查看集群slots
192.168.1.203:6379> cluster slots
1) 1) (integer) 0
   2) (integer) 5460
   3) 1) "192.168.1.201"
      2) (integer) 6379
      3) "55109741ff5c52a9fc3a0212bb9ffbb96c6c2eb8"
   4) 1) "192.168.1.202"
      2) (integer) 6380
      3) "199230e7f7411e451185a785fbdf35169716b283"
2) 1) (integer) 5461
   2) (integer) 10922
   3) 1) "192.168.1.202"
      2) (integer) 6379
      3) "77cf784053fdc072e0b4dcad9fe9a17142c5a5e6"
   4) 1) "192.168.1.203"
      2) (integer) 6380
      3) "4a6a1a91240b9dec4688af57aea908fd6a94e0d4"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "192.168.1.203"
      2) (integer) 6379
      3) "67f6f91f94ac945c0d55622828e599570620f089"
   4) 1) "192.168.1.201"
      2) (integer) 6380
      3) "3c7010e72bbe88e69efc6d78aebed1dcd071bddd"
  • 查看key对应的slot
192.168.1.203:6379> cluster keyslot a
(integer) 15495
  • 查看集群信息
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:7
cluster_size:4
cluster_current_epoch:14
cluster_my_epoch:8
cluster_stats_messages_ping_sent:20438
cluster_stats_messages_pong_sent:12602
cluster_stats_messages_fail_sent:7
cluster_stats_messages_auth-ack_sent:2
cluster_stats_messages_update_sent:2
cluster_stats_messages_sent:33051
cluster_stats_messages_ping_received:12599
cluster_stats_messages_pong_received:12891
cluster_stats_messages_meet_received:3
cluster_stats_messages_fail_received:2
cluster_stats_messages_auth-req_received:2
cluster_stats_messages_received:25497