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 </usr/local/openresty/nginx/lua/access_by_redis.lua:1>, 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
發現是叢集處於下線狀態導致的 :
原因分析
開啟叢集
假設A伺服器上有127.0.0.1:6379
127.0.0.1:6370
兩個 Redis 節點。在 節點 6379 的redis.conf
中開啟cluster-enabled yes
,那麼節點 6379 就處於一個只包含自己的叢集中。構建叢集
向127.0.0.1:6379
傳送命令:
CLUSTER MEET 127.0.0.1:6370
就把 6370 節點 拉到了 6379 所在的叢集中。- 槽指派
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
:
[email protected]:~# redis-cli -h 127.0.0.1 -p 6379 -a Qqq291838322siwei cluster addslots {0..5000}
(error) ERR Slot 0 is already busy
[email protected]:~# redis-cli -h 127.0.0.1 -p 6379 -a Qqq291838322siwei cluster addslots 5
OK
...
...
[email protected]:~# redis-cli -h 127.0.0.1 -p 6379 -a Qqq291838322siwei cluster addslots {8400..12000}
(error) ERR Slot 11955 is already busy
[email protected]:~# redis-cli -h 127.0.0.1 -p 6379 -a Qqq291838322siwei cluster addslots {8400..11954}
OK
[email protected]:~# redis-cli -h 127.0.0.1 -p 6379 -a Qqq291838322siwei 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