Redis 集群详解

225317-1577976797c60f.jpg

Redis 集群简介

Redis Cluster 即 Redis 集群,是 Redis 官方在 3.0 版本推出的一套分布式存储方案。完全去中心化,由多个节点组成,所有节点彼此互联。Redis 客户端可以直接连接任何一节点获取集群中的键值对,不需要中间代理,如果该节点不存在用户所指定的键值,其内部会自动把客户端重定向到键值所在的节点。

Redis 集群是一个网状结构,每个节点都通过 TCP 连接跟其他每个节点连接。在一个有 N 个节点的集群中,每个节点都有 N-1 个流出的 TCP 连接,和 N-1 个流入的连接,这些 TCP 连接会永久保持。

17168214a6f19ad1.png

Redis Cluster 同其他分布式存储系统一样,主要具备以下两个功能:

数据分区

Redis 集群会将用户数据分散保存至各个节点中,突破单机 Redis 内存最大存储容量。集群引入了 哈希槽slot的概念,其搭建完成后会生 16384 个哈希槽slot,同时会根据节点的数量大致均等的将 16384 个哈希槽映射到不同的节点上。当用户存储key-value时,集群会先对key进行 CRC16 校验然后对 16384 取模来决定key-value放置哪个槽,从而实现自动分割数据到不同的节点上。

数据冗余

Redis 集群支持主从复制和故障恢复。集群使用了主从复制模型,每个主节点master应至少有一个从节点slave。假设某个主节点故障,其所有子节点会广播一个数据包给集群里的其他主节点来请求选票,一旦某个从节点收到了大多数主节点的回应,那么它就赢得了选举,被推选为主节点,负责处理之前旧的主节点负责的哈希槽。

节点握手

虽然上面 6 个节点都启用了群集支持,但默认情况下它们是不相互信任或者说没有联系的。节点握手就是在各个节点之间创建链接(每个节点与其他节点相连),形成一个完整的网格,即集群。

节点握手的命令如下:

cluster meet ip port

但为了创建群集,不需要发送形成完整网格所需的所有 cluster meet 命令。只要能发送足够的cluster meet消息,可以让每个节点都可以通过一系列已知节点到达每个其他节点,缺失的链接将被自动创建。

例如,如果我们通过cluster meet将节点 A 与节点 B 连接起来,并将 B 与 C 连接起来,则 A 和 C 会自己找到握手方式并创建链接。

我们的创建的 6 个节点可以通过 redis-cli 连接到 A 节点执行如下五组命令完成握手,生产环境需要将 IP 127.0.0.1替换成外网 IP。

cluster meet 127.0.0.1 7002
cluster meet 127.0.0.1 7003
cluster meet 127.0.0.1 8001
cluster meet 127.0.0.1 8002
cluster meet 127.0.0.1 8003

如上述命令正常执行输出结果如下。

[root@localhost bin]# /usr/local/bin/redis-cli -p 7001
127.0.0.1:7001> cluster meet 127.0.0.1 7002
OK
127.0.0.1:7001> cluster meet 127.0.0.1 7003
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8001
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8002
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8003
OK

接下来可以通过 cluster nodes 命令查看节点之间 的链接状态。我随机找了两个节点 B 和 F 测试,输出结果如下所示。

[root@localhost /]# /usr/local/bin/redis-cli -p 7002 cluster nodes
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220691885 4 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 master - 0 1552220691000 5 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220690878 3 connected
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 myself,master - 0 1552220690000 1 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220691000 2 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220690000 0 connected
[root@localhost /]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552220700255 1 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220703281 0 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220700000 2 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,master - 0 1552220701000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220702275 4 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220701265 3 connected

可以看到,节点 B 和节点 F 都已经分别和其他 5 个节点建立链接。

至此,节点握手完成。

分配槽位

此时 Redis 集群还并没有处于上线状态,可以在任意一节点上执行 cluster info 命令来查看目前集群的运行状态。

[root@localhost ~]# /usr/local/bin/redis-cli -p 7001 cluster info
cluster_state:ok
......

分配槽位的命令如下:

cluster addslots slot [slot ...]

根据预先规划,这一步需要使用 cluster addslots 命令手动将 16384 个哈希槽大致均等分配给主节点 A、B、C。

/usr/local/bin/redis-cli -p 7001 cluster addslots {0..5461}
/usr/local/bin/redis-cli -p 7002 cluster addslots {5462..10922}
/usr/local/bin/redis-cli -p 7003 cluster addslots {10923..16383}

上面三组命令执行完毕,可以再次查看目前集群的一些运行参数。

[root@localhost ~]# /usr/local/bin/redis-cli -p 7001 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:4
cluster_stats_messages_ping_sent:11413
cluster_stats_messages_pong_sent:10509
cluster_stats_messages_meet_sent:11
cluster_stats_messages_sent:21933
cluster_stats_messages_ping_received:10509
cluster_stats_messages_pong_received:10535
cluster_stats_messages_received:21044

如上输出cluster_state:ok证明 Redis 集群成功上线。

主从复制

Redis 集群成功上线,不过还没有给主节点指定从节点,此时如果有一个节点故障,那么整个集群也就挂了,也就无法实现高可用。详细了解点这里:Redis主从复制以及主从复制原理

集群中需要使用 cluster replicate 命令手动给从节点配置主节点。

集群复制命令如下:

cluster replicate node-id

集群中各个节点的node-id可以用cluster nodes命令查看,如下输出1b4b3741945d7fed472a1324aaaa6acaa1843ccb即是主节点 B 的node-id。

[root@localhost /]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552220700255 1 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220703281 0 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220700000 2 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,master - 0 1552220701000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220702275 4 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220701265 3 connected

根据预先规划,A主D从;B主E从;C主F从。执行如下三组命令分别为从节点 D、E、F 指定其主节点,使群集可以自动完成主从复制。

/usr/local/bin/redis-cli -p 8001 cluster replicate 61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12
/usr/local/bin/redis-cli -p 8002 cluster replicate 1b4b3741945d7fed472a1324aaaa6acaa1843ccb
/usr/local/bin/redis-cli -p 8003 cluster replicate 19147f56e679767bcebb8653262ff7f56ca072a8

命令执行成功后,我们便算以手动方式成功搭建了一个 Redis 集群。

最后,再来查看一下集群中的节点信息。

转自:https://juejin.im/post/5e9170d951882573b627f25f

# redis  转载 


标 题:《Redis 集群详解
作 者:zeekling
提 示:转载请注明文章转载自个人博客:浪浪山旁那个村

评论

取消