Redis Cluster 介紹與搭建
1. Redis Cluster介紹
Redis Cluster
是Redis
的分佈式解決方案,在Redis 3.0
版本正式推出的,有效解決了Redis
分佈式方面的需求。當遇到單機內存、併發、流量等瓶頸時,可以採用Cluster
架構達到負載均衡的目的。
1.1 數據分佈理論
分佈式數據庫首要解決把整個數據集按照分區規則映射到多個節點的問題,即把數據集劃分到多個節點上,每個節點負責整個數據的一個子集。常見的分區規則有哈希分區和順序分區。Redis Cluster
採用哈希分區規則,因此接下來會討論哈希分區規則。常見的哈希分區有以下幾種:
- 節點取餘分區
- 一致性哈希分區
- 虛擬槽分區
Redis Cluster
採用虛擬槽分區,因此先介紹一下虛擬槽分區。
虛擬槽分區巧妙地使用了哈希空間,使用分散度良好的哈希函數把所有的數據映射到一個固定範圍內的整數集合,整數定義爲槽(slot)。比如Redis Cluster
槽的範圍是0 ~ 16383
。槽是集羣內數據管理和遷移的基本單位。採用大範圍的槽的主要目的是爲了方便數據的拆分和集羣的擴展,每個節點負責一定數量的槽。
1.2 Redis 數據分區
Redis Cluster
採用虛擬槽分區,所有的鍵根據哈希函數映射到0 ~ 16383
,計算公式:slot = CRC16(key)&16383
。每一個節點負責維護一部分槽以及槽所映射的鍵值數據。
下圖展現一個五個節點構成的集羣,每個節點平均大約負責3276
個槽,以及通過計算公式映射到對應節點的對應槽的過程。
Redis
虛擬槽分區的特定:
- 解耦數據和節點之間的關係,簡化了節點擴容和收縮難度。
- 節點自身維護槽的映射關係,不需要客戶端或者代理服務維護槽分區元數據。
- 支持節點、槽、鍵之間的映射查詢,用於數據路由、在線伸縮等場景。
1.3 Redis 集羣功能限制
Redis
集羣相對單機在功能上有一定限制。
key
批量操作支持有限。如:MSET``MGET
,目前只支持具有相同slot
值的key執行批量操作。key
事務操作支持有限。支持多key
在同一節點上的事務操作,不支持分佈在多個節點的事務功能。key
作爲數據分區的最小粒度,因此不能將一個大的鍵值對象映射到不同的節點。如:hash
、list
。- 不支持多數據庫空間。單機下
Redis
支持16
個數據庫,集羣模式下只能使用一個數據庫空間,即db 0
。 - 複製結構只支持一層,不支持嵌套樹狀複製結構。
2. 搭建 Redis Cluster
搭建集羣工作分爲三步:
- 準備節點
- 節點握手
- 分配槽
2.1 準備節點
Redis
集羣一般由多個節點組成,節點數量爲6
個才能保證組成完整高可用的集羣。下面給出一個節點的配置,其他的節點和該節點只是端口不同。
port 6379 //端口
cluster-enabled yes //開啓集羣模式
cluster-config-file nodes-6379.conf //集羣內部的配置文件
cluster-node-timeout 15000 //節點超時時間,單位毫秒
// 其他配置和單機模式相同
啓動所有的節點
sudo redis-server conf/redis-6384.conf
sudo redis-server conf/redis-6383.conf
sudo redis-server conf/redis-6382.conf
sudo redis-server conf/redis-6381.conf
sudo redis-server conf/redis-6380.conf
sudo redis-server conf/redis-6379.conf
可以查看日誌文件
cat log/redis-6379.log
13103:M 30 May 15:02:09.577 * DB loaded from disk: 0.000 seconds
13103:M 30 May 15:02:09.578 * The server is now ready to accept connections on port 6379
有日誌文件可得,節點已經啓動成功。這個日誌文件是Redis
服務器普通的日誌文件,在集羣模式下,第一次也會自動創建一個日誌文件,由配置文件cluster-config-file
指定文件。
集羣配置文件的作用:當集羣內節點發生信息變化時,如添加節點、節點下線、故障轉移等。節點會自動保存集羣的狀態到配置文件中。該配置文件由Redis
自行維護,不要手動修改,防止節點重啓時產生集羣信息錯亂。
我們來查看一下,集羣模式的日誌文件:
cat nodes-6379.conf
29978c0169ecc0a9054de7f4142155c1ab70258b :0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
也可以通過客戶端連接該節點,通過命令CLUSTER NODES
來查看:
127.0.0.1:6379> CLUSTER NODES
29978c0169ecc0a9054de7f4142155c1ab70258b :6379 myself,master - 0 0 0 connected
2.2 節點握手
節點握手是指一批運行在集羣模式的節點通過Gossip
協議彼此通信,達到感知對方的過程。節點握手是集羣彼此通信的第一步,由客戶端發起命令:cluster meet <ip> <port>
127.0.0.1:6379> CLUSTER MEET 127.0.0.1 6380
OK
// 發送CLUSTER NODES可以查看到已經感知到 6380 端口的節點了。
127.0.0.1:6379> CLUSTER NODES
29978c0169ecc0a9054de7f4142155c1ab70258b 127.0.0.1:6379 myself,master - 0 0 1 connected
8f285670923d4f1c599ecc93367c95a30fb8bf34 127.0.0.1:6380 master - 0 1496129041442 0 connected
讓所有的節點都互相感知:
127.0.0.1:6379> CLUSTER MEET 127.0.0.1 6381
OK
127.0.0.1:6379> CLUSTER MEET 127.0.0.1 6382
OK
127.0.0.1:6379> CLUSTER MEET 127.0.0.1 6383
OK
127.0.0.1:6379> CLUSTER MEET 127.0.0.1 6384
OK
// 已經全部感知到所有的節點
127.0.0.1:6379> CLUSTER NODES
e0c7961a1b07ab655bc31d8dfd583da565ec167d 127.0.0.1:6384 master - 0 1496129143703 0 connected
961097d6be64ebd2fd739ff719e97565a8cee7b5 127.0.0.1:6382 master - 0 1496129141678 0 connected
29978c0169ecc0a9054de7f4142155c1ab70258b 127.0.0.1:6379 myself,master - 0 0 1 connected
8f285670923d4f1c599ecc93367c95a30fb8bf34 127.0.0.1:6380 master - 0 1496129142682 3 connected
6fb7dfdb6188a9fe53c48ea32d541724f36434e9 127.0.0.1:6383 master - 0 1496129145699 4 connected
66478bda726ae6ba4e8fb55034d8e5e5804223ff 127.0.0.1:6381 master - 0 1496129147704 2 connected
當前已經使這六個節點組成集羣,但是現在還無法工作,因爲集羣節點還沒有分配槽(slot)。
2.3 分配槽
可以看一下6379
端口的槽個數
127.0.0.1:6379> CLUSTER INFO
cluster_state:fail
cluster_slots_assigned:0 // 被分配槽的個數爲0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:479
cluster_stats_messages_received:479
接下來爲節點分配槽空間。通過cluster addslots
命令。
redis-cli -h 127.0.0.1 -p 6379 cluster addslots {0..5461}
OK
redis-cli -h 127.0.0.1 -p 6380 cluster addslots {5462..10922}
OK
redis-cli -h 127.0.0.1 -p 6381 cluster addslots {10923..16383}
OK
我們將16383
個槽平均分配給6379
、6380
、6381
端口的節點。再次執行CLUSTER INFO
查看一下集羣的狀態:
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok // 集羣狀態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:1
cluster_stats_messages_sent:1212
cluster_stats_messages_received:1212
可以通過CLUSTER NODES
來查看分配情況:
127.0.0.1:6379> CLUSTER NODES
e0c7961a1b07ab655bc31d8dfd583da565ec167d 127.0.0.1:6384 master - 0 1496129666347 0 connected
961097d6be64ebd2fd739ff719e97565a8cee7b5 127.0.0.1:6382 master - 0 1496129664844 5 connected
29978c0169ecc0a9054de7f4142155c1ab70258b 127.0.0.1:6379 myself,master - 0 0 1 connected 0-5461
8f285670923d4f1c599ecc93367c95a30fb8bf34 127.0.0.1:6380 master - 0 1496129665846 3 connected 5462-10922
6fb7dfdb6188a9fe53c48ea32d541724f36434e9 127.0.0.1:6383 master - 0 1496129661838 4 connected
66478bda726ae6ba4e8fb55034d8e5e5804223ff 127.0.0.1:6381 master - 0 1496129666848 2 connected 10923-16383
目前還有三個節點沒有使用,作爲一個完整的集羣,每個負責處理槽的節點應該具有從節點,保證當主節點出現故障時,可以自動進行故障轉移。集羣模式下,首次啓動的節點和被分配槽的節點都是主節點,從節點負責複製主節點槽的信息和相關數據。
使用cluster replicate <nodeid>
在從節點上執行。
redis-cli -h 127.0.0.1 -p 6382 cluster replicate 29978c0169ecc0a9054de7f4142155c1ab70258b
OK
redis-cli -h 127.0.0.1 -p 6383 cluster replicate 8f285670923d4f1c599ecc93367c95a30fb8bf34
OK
redis-cli -h 127.0.0.1 -p 6384 cluster replicate 66478bda726ae6ba4e8fb55034d8e5e5804223ff
OK
通過CLUSTER NODES
可以查看集羣節點的狀態
127.0.0.1:6379> CLUSTER NODES
e0c7961a1b07ab655bc31d8dfd583da565ec167d 127.0.0.1:6384 slave 66478bda726ae6ba4e8fb55034d8e5e5804223ff 0 1496130082754 2 connected
961097d6be64ebd2fd739ff719e97565a8cee7b5 127.0.0.1:6382 slave 29978c0169ecc0a9054de7f4142155c1ab70258b 0 1496130080749 5 connected
29978c0169ecc0a9054de7f4142155c1ab70258b 127.0.0.1:6379 myself,master - 0 0 1 connected 0-5461
8f285670923d4f1c599ecc93367c95a30fb8bf34 127.0.0.1:6380 master - 0 1496130078744 3 connected 5462-10922
6fb7dfdb6188a9fe53c48ea32d541724f36434e9 127.0.0.1:6383 slave 8f285670923d4f1c599ecc93367c95a30fb8bf34 0 1496130079747 4 connected
66478bda726ae6ba4e8fb55034d8e5e5804223ff 127.0.0.1:6381 master - 0 1496130081751 2 connected 10923-16383
這樣就完成了一個3
主3
從的Redis
集羣搭建。如下圖所示:
本文參考:《Redis開發與運維》