這次在搞不定 Redis 叢集搭建!你來找我~~
-
Redis 叢集簡介
-
下載 & 安裝 Redis
-
搭建 Redis 叢集
-
- 手動方式搭建
- 自動方式搭
-
Redis 叢集簡介
Redis Cluster 即 Redis 叢集,是 Redis 官方在 3.0 版本推出的一套分散式儲存方案。完全去中心化,由多個節點組成,所有節點彼此互聯。Redis 客戶端可以直接連線任何一節點獲取叢集中的鍵值對,不需要中間代理,如果該節點不存在使用者所指定的鍵值,其內部會自動把客戶端重定向到鍵值所在的節點。
Redis 叢集是一個網狀結構,每個節點都通過 TCP 連線跟其他每個節點連線。在一個有 N 個節點的叢集中,每個節點都有 N-1 個流出的 TCP 連線,和 N-1 個流入的連線,這些 TCP 連線會永久保持。
Redis Cluster 同其他分散式儲存系統一樣,主要具備以下兩個功能:
資料分割槽Redis 叢集會將使用者資料分散儲存至各個節點中,突破單機 Redis 記憶體最大儲存容量。叢集引入了 雜湊槽slot
的概念,其搭建完成後會生 16384 個雜湊槽slot
,同時會根據節點的數量大致均等的將 16384 個雜湊槽對映到不同的節點上。當用戶儲存key-value
時,叢集會先對key
進行 CRC16 校驗然後對 16384 取模來決定key-value
放置哪個槽,從而實現自動分割資料到不同的節點上。
資料冗餘Redis 叢集支援主從複製和故障恢復。叢集使用了主從複製模型,每個主節點master
slave
。假設某個主節點故障,其所有子節點會廣播一個數據包給叢集裡的其他主節點來請求選票,一旦某個從節點收到了大多數主節點的迴應,那麼它就贏得了選舉,被推選為主節點,負責處理之前舊的主節點負責的雜湊槽。
關於 Redis Cluster 詳細介紹以及實現原理請參見 Redis Cluster 教程 和 Redis Cluster 規範,在此不再贅述。
下載 & 安裝 Redis
實驗環境資訊 Linux 版本:CentOS Linux release 7.4.1708 Redis 版本:5.0.3
先在伺服器或虛擬機器中安裝一個單機 Redis,如果已安裝可以跳過本節,未安裝過的正好學習下。
進入 Redis 待安裝目錄。
Copycd /usr/local
下載、解壓 Redis 原始碼壓縮包。
Copywget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz
然後進入解壓後的目錄並使用 make 命令執行編譯安裝 Redis。
Copycd redis-5.0.3
make && make install
不要高興,因為你極有可能會遇到因為 GCC 編譯器未安裝導致編譯失敗的情況。不要著急,請順序執行如下命令。
Copyyum -y install gcc
make distclean
make && make install
Redis 基於 C 語言開發,故編譯原始碼需要 GCC(Linux下的一個編譯器,這裡需要用來編譯`.c`檔案)的支援。如機器上未安裝需要先執行命令`yum -y install gcc`安裝 GCC 編譯工具,然後`make distclean`清除之前生成的檔案,最後`make && make install`重新編譯安裝。
最終出現類似下文輸出則表示 Redis 安裝成功。
Copy......
Hint: It's a good idea to run 'make test' ;)
INSTALL install
INSTALL install
INSTALL install
INSTALL install
INSTALL install
make[1]: 離開目錄“/usr/local/redis-5.0.3/src”
如果原始碼編譯無誤且執行結果正確,make install
命令會將程式安裝至系統預設的可執行檔案存放路徑,一般是/usr/local/bin
目錄,可以通過如下終端輸出確認。當然,也可以使用make install PREFIX=
命令安裝到指定路徑。
Copy[root@localhost bin]# cd /usr/local/bin
[root@localhost bin]# ls -l
總用量 32672
-rwxr-xr-x. 1 root root 4367328 3月 6 06:11 redis-benchmark
-rwxr-xr-x. 1 root root 8092024 3月 6 06:11 redis-check-aof
-rwxr-xr-x. 1 root root 8092024 3月 6 06:11 redis-check-rdb
-rwxr-xr-x. 1 root root 4802696 3月 6 06:11 redis-cli
lrwxrwxrwx. 1 root root 12 3月 6 06:11 redis-sentinel - redis-server
-rwxr-xr-x. 1 root root 8092024 3月 6 06:11 redis-server
至此,單機 Redis 安裝完成。
搭建 Redis 叢集
進入正題。
依據 Redis Cluster 內部故障轉移實現原理,Redis 叢集至少需要 3 個主節點,而每個主節點至少有 1 從節點,因此搭建一個叢集至少包含 6 個節點,三主三從,並且分別部署在不同機器上。
條件有限,測試環境下我們只能在一臺機器上建立一個偽叢集,通過不同的 TCP 埠啟動多個 Redis 例項,組成叢集。
目前 Redis Cluster 的搭建有兩種方式:
- 手動方式搭建,即手動執行 cluster 命令,一步步完成搭建流程。
- 自動方式搭建,即使用官方提供的叢集管理工具快速搭建。
兩種方式原理一樣,自動搭建方式只是將手動搭建方式中需要執行的 Redis 命令封裝到了可執行程式。生產環境下推薦使用第二種方式,簡單快捷,不易出錯。不過本文實戰演示兩種方式都會提及。
手動方式搭建
啟動節點
搭建叢集的第一步就是要先把參與搭建叢集的每個節點啟動起來。
由於我們這是在一臺機器上模擬多個節點,可以預先規劃下各個節點的屬性:
節點編號 | IP 地址 | TCP 埠 | 節點型別 | 從節點 | 啟動配置 |
---|---|---|---|---|---|
A | 127.0.0.1 | 7001 | 主 | D | /usr/local/redis-cluster/7001/redis.conf |
B | 127.0.0.1 | 7002 | 主 | E | /usr/local/redis-cluster/7002/redis.conf |
C | 127.0.0.1 | 7003 | 主 | F | /usr/local/redis-cluster/7003/redis.conf |
D | 127.0.0.1 | 8001 | 從 | / | /usr/local/redis-cluster/8001/redis.conf |
E | 127.0.0.1 | 8002 | 從 | / | /usr/local/redis-cluster/8002/redis.conf |
F | 127.0.0.1 | 8003 | 從 | / | /usr/local/redis-cluster/8003/redis.conf |
根據上述規劃,可以先通過如下命令建立各個節點啟動配置檔案的存放目錄。
Copymkdir /usr/local/redis-cluster
cd redis-cluster
mkdir -p 7001 7002 7003 8001 8002 8003
順序執行如下行命令,進入 Redis 原始碼包目錄並將預設配置檔案redis.conf
分別複製到六個節點配置存放目錄中,作為各自節點啟動配置檔案。
Copycd /usr/local/redis-5.0.3
cp redis.conf /usr/local/redis-cluster/7001
cp redis.conf /usr/local/redis-cluster/7002
cp redis.conf /usr/local/redis-cluster/7003
cp redis.conf /usr/local/redis-cluster/8001
cp redis.conf /usr/local/redis-cluster/8002
cp redis.conf /usr/local/redis-cluster/8003
接下來需要分別修改每個節點的配置檔案。下面貼的是節點 A 的配置檔案/usr/local/redis-cluster/7001/redis.conf
中啟用或修改的一些必要引數。其他節點 B、C、D、E、F 參照修改,注意把涉及埠的地方修改成各自節點預先規劃的即可。
Copybind 192.168.83.128 # 設定當前節點主機地址
port 7001 # 設定客戶端連線監聽埠
pidfile /var/run/redis_7001.pid # 設定 Redis 例項 pid 檔案
daemonize yes # 以守護程序執行 Redis 例項
cluster-enabled yes # 啟用叢集模式
cluster-node-timeout 15000 # 設定當前節點連線超時毫秒數
cluster-config-file nodes-7001.conf # 設定當前節點叢集配置檔案路徑
完成上述工作就可以通過如下幾組命令啟動待搭建叢集中的 6 個節點了。
Copy/usr/local/bin/redis-server /usr/local/redis-cluster/7001/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/7002/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/7003/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8001/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8002/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8003/redis.conf
最後通過ps -ef|grep redis
命令確認各個節點服務是否已經正常執行。
Copy[root@localhost bin]# ps -ef|grep redis
root 5613 1 0 04:25 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:7001 [cluster]
root 5650 1 0 04:26 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:7002 [cluster]
root 5661 1 0 04:26 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:7003 [cluster]
root 5672 1 0 04:27 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:8001 [cluster]
root 5681 1 0 04:27 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:8002 [cluster]
root 5690 1 0 04:27 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:8003 [cluster]
root 5731 1311 0 04:28 pts/0 00:00:00 grep --color=auto redis
如上輸出可以看出上面規劃的 6 個節點都成功啟動。
節點握手
雖然上面 6 個節點都啟用了群集支援,但預設情況下它們是不相互信任或者說沒有聯絡的。節點握手就是在各個節點之間建立連結(每個節點與其他節點相連),形成一個完整的網格,即叢集。
節點握手的命令如下:
Copycluster 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。
Copycluster 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
如上述命令正常執行輸出結果如下。
Copy[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 測試,輸出結果如下所示。
Copy[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 命令來檢視目前叢集的執行狀態。
Copy[root@localhost ~]# /usr/local/bin/redis-cli -p 7001 cluster info
cluster_state:fail
......
上面輸出cluster_state:fail
表示當前叢集處於下線狀態。因為只有給叢集中所有主節點分配好槽位(即雜湊槽slot
,本文第一小節有提及)叢集才能上線。
分配槽位的命令如下:
Copycluster addslots slot [slot ...]
根據預先規劃,這一步需要使用 cluster addslots 命令手動將 16384 個雜湊槽大致均等分配給主節點 A、B、C。
Copy/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}
上面三組命令執行完畢,可以再次檢視目前叢集的一些執行引數。
Copy[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 叢集成功上線,不過還沒有給主節點指定從節點,此時如果有一個節點故障,那麼整個叢集也就掛了,也就無法實現高可用。
叢集中需要使用 cluster replicate 命令手動給從節點配置主節點。
叢集複製命令如下:
Copycluster replicate node-id
叢集中各個節點的node-id
可以用cluster nodes
命令檢視,如下輸出1b4b3741945d7fed472a1324aaaa6acaa1843ccb
即是主節點 B 的node-id
。
Copy[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 指定其主節點,使群集可以自動完成主從複製。
Copy/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 叢集。
最後,再來檢視一下叢集中的節點資訊。
Copy[root@localhost ~]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552233328337 1 connected 5462-10922
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 slave 19147f56e679767bcebb8653262ff7f56ca072a8 0 1552233327000 2 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552233325000 2 connected 10923-16383
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,slave 1b4b3741945d7fed472a1324aaaa6acaa1843ccb 0 1552233327000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552233327327 4 connected 0-5461
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 slave 61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 0 1552233326320 4 connected
自動方式搭建
Redis 3.0 版本之後官方釋出了一個叢集管理工具 redis-trib.rb,整合在 Redis 原始碼包的src
目錄下。其封裝了 Redis 提供的叢集命令,使用簡單、便捷。
不過 redis-trib.rb 是 Redis 作者使用 Ruby 語言開發的,故使用該工具之前還需要先在機器上安裝 Ruby 環境。後面作者可能意識到這個問題,Redis 5.0 版本開始便把這個工具整合到 redis-cli 中,以--cluster
引數提供使用,其中create
命令可以用來建立叢集。
啟動節點
使用叢集管理工具搭建叢集之前,也是需要先把各個節點啟動起來的。節點的啟動方式請參見本文「手動方式建立」-「啟動節點」一節,此處不再贅述。
叢集管理工具搭建
如果您安裝的 Redis 是 3.x 和 4.x 的版本可以使用 redis-trib.rb 搭建,不過之前需要安裝 Ruby 環境。
先使用 yum 安裝 Ruby 環境以及其他依賴項。
Copyyum -y install ruby ruby-devel rubygems rpm-build
確認安裝版本。
Copy[root@localhost redis-cluster]# ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
再使用 redis-trib.rb 指令碼搭建叢集,具體命令如下所示。
Copy/usr/local/redis-5.0.3/src/redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003
不過,本文實驗環境使用的 Redis 版本是 5.0.3,所以我可以直接使用redis-cli --cluster create
命令搭建,具體命令如下所示。
Copy/usr/local/bin/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 --cluster-replicas 1
主節點在前,從節點在後。其中--cluster-replicas
引數用來指定一個主節點帶有的從節點個數,如上--cluster-replicas 1
即表示 1 個主節點有 1 個從節點。
命令執行成功會有類似如下輸出。
Copy[root@localhost bin]# redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 --cluster-replicas 1
>> Performing hash slots allocation on 6 nodes...
Master[0] - Slots 0 - 5460
Master[1] - Slots 5461 - 10922
Master[2] - Slots 10923 - 16383
Adding replica 127.0.0.1:8001 to 127.0.0.1:7001
Adding replica 127.0.0.1:8002 to 127.0.0.1:7002
Adding replica 127.0.0.1:8003 to 127.0.0.1:7003
>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 32f9819fc7d561bfa2b7189182200e86d9901b8a 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
M: cca0fbfa374bc175d481e68ee9ed13b65453e967 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
M: 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
S: 1b47b9e6e7a79523579b8d2ddcd5e708583ed317 127.0.0.1:8001
replicates 32f9819fc7d561bfa2b7189182200e86d9901b8a
S: aba9330f3e70f26a8af4ced1b672fbcc7bc62d78 127.0.0.1:8002
replicates cca0fbfa374bc175d481e68ee9ed13b65453e967
S: 254db0830cd764e075aa793144572d5fa3a398f0 127.0.0.1:8003
replicates 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e
Can I set the above configuration? (type 'yes' to accept): yes
>> Nodes configuration updated
>> Assign a different config epoch to each node
>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 32f9819fc7d561bfa2b7189182200e86d9901b8a 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: aba9330f3e70f26a8af4ced1b672fbcc7bc62d78 127.0.0.1:8002
slots: (0 slots) slave
replicates cca0fbfa374bc175d481e68ee9ed13b65453e967
S: 1b47b9e6e7a79523579b8d2ddcd5e708583ed317 127.0.0.1:8001
slots: (0 slots) slave
replicates 32f9819fc7d561bfa2b7189182200e86d9901b8a
S: 254db0830cd764e075aa793144572d5fa3a398f0 127.0.0.1:8003
slots: (0 slots) slave
replicates 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e
M: cca0fbfa374bc175d481e68ee9ed13b65453e967 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>> Check for open slots...
>> Check slots coverage...
[OK] All 16384 slots covered.
OK,搭建完成!一條命令搞定。
歡迎關注公眾號 【碼農開花】一起學習成長
我會一直分享Java乾貨,也會分享免費的學習資料課程和麵試寶典
回覆:【計算機】【設計模式】有驚喜哦