Redis 分布式集群,分配Slots

某天在开启了Redis集群之后,发现网站没法正常访问了,发现Nginx-lua 中的 Redis 丢失连接 …

集群下线

问题表现

通过查看 openrestry log 发现 lua脚本报错 :

2018/06/12 17:48:20 [error] 23272#0: *75665 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/lua/access_by_redis.lua:67: attempt to compare boolean with number
stack traceback:
coroutine 0:
        /usr/local/openresty/nginx/lua/access_by_redis.lua: in function , client: 66.249.65.116, server: www.leon0204.com, request: "GET /wechat-858.html HTTP/1.1", host: "www.leon0204.com"

从而 Nginx 返回 500,测试 Redis set 发现是集群处于下线状态导致的 :
Redis 分布式集群,分配Slots_第1张图片

原因分析

  1. 开启集群
    假设A服务器上有 127.0.0.1:6379127.0.0.1:6370 两个 Redis 节点。在 节点 6379 的 redis.conf中开启 cluster-enabled yes ,那么节点 6379 就处于一个只包含自己的集群中。

  2. 构建集群
    127.0.0.1:6379 发送命令:
    CLUSTER MEET 127.0.0.1:6370
    就把 6370 节点 拉到了 6379 所在的集群中。

  3. 槽指派
    Redis集群通过分片的方式来保存数据库的所有键值对:整个数据库被分成16384 个 Slot ,数据库键空间的所有键被分配到这 16384 个槽中的一个,每个node 处理 0~16384 个槽。当16384个槽有任意1个没有被处理,集群处于 fail 下线状态,否则处于上线 状态。

猜想是有一些槽没有被分配处理,进行分配槽

分配槽

查看集群状态:

127.0.0.1:6379> CLUSTER INFO
cluster_state:fail
cluster_slots_assigned:7
cluster_slots_ok:7
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:1
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0

有 7 个 Slot 已经被分配,由于有 slots没有分配干净,所以集群处于 fail 下线状态,进行分配 slots

root@iZm5eabkgmsfy2phj5pr1xZ:~# redis-cli -h 127.0.0.1  -p 6379 -a Qqq291838322siwei cluster addslots {0..5000}
(error) ERR Slot 0 is already busy
root@iZm5eabkgmsfy2phj5pr1xZ:~# redis-cli -h 127.0.0.1  -p 6379 -a 密码 cluster addslots 5
OK
...
...
root@iZm5eabkgmsfy2phj5pr1xZ:~# redis-cli -h 127.0.0.1  -p 6379 -a 密码 cluster addslots {8400..12000}
(error) ERR Slot 11955 is already busy
root@iZm5eabkgmsfy2phj5pr1xZ:~# redis-cli -h 127.0.0.1  -p 6379 -a 密码 cluster addslots {8400..11954}
OK
root@iZm5eabkgmsfy2phj5pr1xZ:~# redis-cli -h 127.0.0.1  -p 6379 -a 密码 cluster addslots {13001..16383}
OK

可以看到这里不断有一些slots : 1151 1389 1909 5798 6918 8399 11955
已经被分配了,这是为什么呢,是不是我把 6379 加入集群之后,已经默认给我分配了这些 槽呢?先来看看分配完成集群的状态,和slot_assigned的数目:

127.0.0.1:6379> CLUSTER NODES
151ce5ca0524b02c7af07402dcb40f5d678f7bb1 :6379 myself,master - 0 0 0 connected 0-16383

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:1
cluster_size:1
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0

# 可以正确的 set 了
127.0.0.1:6379> set leon leon0204
OK
127.0.0.1:6379>

验证一下,分配过程中那些 断点 槽 ,也就是单节点集群 6379主机的所有 key ,和他们被分配到的槽 :

127.0.0.1:6379> KEYS *
1) "pyq"
2) "user:183.234.61.216:freq"
3) "leon0204"
4) "name"
5) "funet"
6) "goodsId"
7) "test"

刚刚我分配 0,16383 个槽给 当前node节点时,提示槽X已经busy 的 有

1151 1389 1909 5798 6918 8399 11955
我们知道,当集群被建立之后,集群的整个数据库就会被分配到 16383 个槽中,类似于分片的概念 。那么是否是我之前的这些key ?
那么,我们查看 这些key 被分配的槽号

127.0.0.1:6379> CLUSTER KEYSLOT "pyq"
(integer) 1151
127.0.0.1:6379> CLUSTER KEYSLOT "user:183.234.61.216:freq"
(integer) 1909
127.0.0.1:6379> CLUSTER KEYSLOT "leon0204"
(integer) 11955
127.0.0.1:6379> CLUSTER KEYSLOT "name"
(integer) 5798
127.0.0.1:6379> CLUSTER KEYSLOT "funet"
(integer) 8399
127.0.0.1:6379> CLUSTER KEYSLOT "goodsId"
(integer) 1389
127.0.0.1:6379> CLUSTER KEYSLOT "test"
(integer) 6918

正好和上面的 addslots 过程中,冲突的 slots 吻合 ,7个key 对应7 个 slot

你可能感兴趣的:(Redis)