使用 Docker 搭建 Redis Cluster,最重要的環節就是容器通訊的問題,這一塊咱們在以前的文章中已經給你們解決了《Docker 網絡模式詳解及容器間網絡通訊》,本篇文章主要練習使用多個容器完成 Redis Cluster 集羣環境的搭建,順便爲學習 Docker Compose 鋪鋪路。俗話說沒有對比就沒有傷害,經過對比才能感覺到 Docker Compose 的好處 😄。node
關於 Redis Cluster 集羣更多的內容請閱讀《最通俗易懂的 Redis 架構模式詳解》。redis
按照 Redis 官網:https://redis.io/topics/cluster-tutorial 的提示,爲了使 Docker 與 Redis Cluster 兼容,您須要使用 Docker 的 host
網絡模式。docker
host
網絡模式須要在建立容器時經過參數 --net host
或者 --network host
指定,host
網絡模式可讓容器共享宿主機網絡棧,容器將不會虛擬出本身的網卡,配置本身的 IP 等,而是使用宿主機的 IP 和端口。shell
環境
爲了讓環境更加真實,本文使用多機環境:bash
192.168.10.10
192.168.10.11
每臺機器所使用的基礎設施環境以下:網絡
CentOS 7.8.2003
Docker version 19.03.12
搭建
總體搭建步驟主要分爲如下幾步:架構
- 下載 Redis 鏡像(其實這步能夠省略,由於建立容器時,若是本地鏡像不存在,就會去遠程拉取);
- 編寫 Redis 配置文件;
- 建立 Redis 容器;
- 建立 Redis Cluster 集羣。
編寫 Redis 配置文件
建立目錄及文件
分別在 192.168.10.10
和 192.168.10.11
兩臺機器上執行如下操做。app
# 建立目錄 mkdir -p /usr/local/docker-redis/redis-cluster # 切換至指定目錄 cd /usr/local/docker-redis/redis-cluster/ # 編寫 redis-cluster.tmpl 文件 vi redis-cluster.tmpl
編寫配置文件
192.168.10.10
機器的 redis-cluster.tmpl
文件內容以下:函數
port ${PORT} requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.10 cluster-announce-port ${PORT} cluster-announce-bus-port 1${PORT}
192.168.10.11
機器的 redis-cluster.tmpl
文件內容以下:學習
port ${PORT} requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.11 cluster-announce-port ${PORT} cluster-announce-bus-port 1${PORT}
port
:節點端口;requirepass
:添加訪問認證;masterauth
:若是主節點開啓了訪問認證,從節點訪問主節點須要認證;protected-mode
:保護模式,默認值 yes,即開啓。開啓保護模式之後,需配置bind ip
或者設置訪問密碼;關閉保護模式,外部網絡能夠直接訪問;daemonize
:是否以守護線程的方式啓動(後臺啓動),默認 no;appendonly
:是否開啓 AOF 持久化模式,默認 no;cluster-enabled
:是否開啓集羣模式,默認 no;cluster-config-file
:集羣節點信息文件;cluster-node-timeout
:集羣節點鏈接超時時間;cluster-announce-ip
:集羣節點 IP,填寫宿主機的 IP;cluster-announce-port
:集羣節點映射端口;cluster-announce-bus-port
:集羣節點總線端口。
每一個 Redis 集羣節點都須要打開兩個 TCP 鏈接。一個用於爲客戶端提供服務的正常 Redis TCP 端口,例如 6379。還有一個基於 6379 端口加 10000 的端口,好比 16379。
第二個端口用於集羣總線,這是一個使用二進制協議的節點到節點通訊通道。節點使用集羣總線進行故障檢測、配置更新、故障轉移受權等等。客戶端永遠不要嘗試與集羣總線端口通訊,與正常的 Redis 命令端口通訊便可,可是請確保防火牆中的這兩個端口都已經打開,不然 Redis 集羣節點將沒法通訊。
在 192.168.10.10
機器的 redis-cluster
目錄下執行如下命令:
for port in `seq 6371 6373`; do \ mkdir -p ${port}/conf \ && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \ && mkdir -p ${port}/data;\ done
在 192.168.10.11
機器的 redis-cluster
目錄下執行如下命令:
for port in `seq 6374 6376`; do \ mkdir -p ${port}/conf \ && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \ && mkdir -p ${port}/data;\ done
上面兩段 shell for 語句,意思就是循環建立 6371 ~ 6376 相關的目錄及文件。
在 192.168.10.10
機器執行查看命令結果以下,若是沒有 tree
命令先安裝 yum install -y tree
。
在 192.168.10.11
機器執行查看命令結果以下。
如下內容爲每一個節點的配置文件詳細信息。
============================== 192.168.10.10 ============================== [root@localhost redis-cluster]# cat /usr/local/docker-redis/redis-cluster/637{1..3}/conf/redis.conf port 6371 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.10 cluster-announce-port 6371 cluster-announce-bus-port 16371 port 6372 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.10 cluster-announce-port 6372 cluster-announce-bus-port 16372 port 6373 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.10 cluster-announce-port 6373 cluster-announce-bus-port 16373 ============================== 192.168.10.10 ============================== ============================== 192.168.10.11 ============================== [root@localhost redis-cluster]# cat /usr/local/docker-redis/redis-cluster/637{4..6}/conf/redis.conf port 6374 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.11 cluster-announce-port 6374 cluster-announce-bus-port 16374 port 6375 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.11 cluster-announce-port 6375 cluster-announce-bus-port 16375 port 6376 requirepass 1234 masterauth 1234 protected-mode no daemonize no appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 15000 cluster-announce-ip 192.168.10.11 cluster-announce-port 6376 cluster-announce-bus-port 16376 ============================== 192.168.10.11 ==============================
建立 Redis 容器
建立容器
將宿主機的 6371 ~ 6376
之間的端口與 6 個 Redis 容器映射,並將宿主機的目錄與容器內的目錄進行映射(目錄掛載)。記得指定網絡模式,使用 host
網絡模式。
在 192.168.10.10
機器執行如下命令:
for port in $(seq 6371 6373); do \ docker run -di --restart always --name redis-${port} --net host \ -v /usr/local/docker-redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v /usr/local/docker-redis/redis-cluster/${port}/data:/data \ redis redis-server /usr/local/etc/redis/redis.conf; \ done
在 192.168.10.11
機器執行如下命令:
for port in $(seq 6374 6376); do \ docker run -di --restart always --name redis-${port} --net host \ -v /usr/local/docker-redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v /usr/local/docker-redis/redis-cluster/${port}/data:/data \ redis redis-server /usr/local/etc/redis/redis.conf; \ done
在 192.168.10.10
機器執行 docker ps -n 3
查看容器是否建立成功。
在 192.168.10.11
機器執行 docker ps -n 3
查看容器是否建立成功。
建立 Redis Cluster 集羣
隨便進入一個容器節點,並進入 /usr/local/bin/
目錄:
# 進入容器 docker exec -it redis-6371 bash # 切換至指定目錄 cd /usr/local/bin/
接下來咱們就能夠經過如下命令實現 Redis Cluster 集羣的建立。
redis-cli -a 1234 --cluster create 192.168.10.10:6371 192.168.10.10:6372 192.168.10.10:6373 192.168.10.11:6374 192.168.10.11:6375 192.168.10.11:6376 --cluster-replicas 1
出現選擇提示信息,輸入 yes,結果以下所示:
集羣建立成功以下:
如下內容是建立集羣時返回的詳細信息,也就是上兩幅圖中的全部內容。
root@localhost:/usr/local/bin# redis-cli -a 1234 --cluster create 192.168.10.10:6371 192.168.10.10:6372 192.168.10.10:6373 192.168.10.11:6374 192.168.10.11:6375 192.168.10.11:6376 --cluster-replicas 1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.10.11:6376 to 192.168.10.10:6371 Adding replica 192.168.10.10:6373 to 192.168.10.11:6374 Adding replica 192.168.10.11:6375 to 192.168.10.10:6372 M: 299cf79ddafc83dced27f628f1f82dac483fbc4e 192.168.10.10:6371 slots:[0-5460] (5461 slots) master M: ac805b90b6e20e26dc4268454bb2855beea6cc19 192.168.10.10:6372 slots:[10923-16383] (5461 slots) master S: db35494fcc5db0c88d27da7885c817e6cdcc9373 192.168.10.10:6373 replicates 7013270480d37eeab79b9cd0272e934d4548136a M: 7013270480d37eeab79b9cd0272e934d4548136a 192.168.10.11:6374 slots:[5461-10922] (5462 slots) master S: 8435e1b0d51f2690c5f94f9a5682a4ac34e94326 192.168.10.11:6375 replicates ac805b90b6e20e26dc4268454bb2855beea6cc19 S: 7b13c16fa6fe8e13cdc0b4846b87edffed55c62e 192.168.10.11:6376 replicates 299cf79ddafc83dced27f628f1f82dac483fbc4e 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 192.168.10.10:6371) M: 299cf79ddafc83dced27f628f1f82dac483fbc4e 192.168.10.10:6371 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 8435e1b0d51f2690c5f94f9a5682a4ac34e94326 192.168.10.11:6375 slots: (0 slots) slave replicates ac805b90b6e20e26dc4268454bb2855beea6cc19 S: db35494fcc5db0c88d27da7885c817e6cdcc9373 192.168.10.10:6373 slots: (0 slots) slave replicates 7013270480d37eeab79b9cd0272e934d4548136a S: 7b13c16fa6fe8e13cdc0b4846b87edffed55c62e 192.168.10.11:6376 slots: (0 slots) slave replicates 299cf79ddafc83dced27f628f1f82dac483fbc4e M: 7013270480d37eeab79b9cd0272e934d4548136a 192.168.10.11:6374 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: ac805b90b6e20e26dc4268454bb2855beea6cc19 192.168.10.10:6372 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.
至此一個高可用的 Redis Cluster 集羣搭建完成,以下圖所示,該集羣中包含 6 個 Redis 節點,3 主 3 從。三個主節點會分配槽,處理客戶端的命令請求,而從節點可用在主節點故障後,頂替主節點。
查看集羣狀態
咱們先進入容器,而後經過一些集羣經常使用的命令查看一下集羣的狀態。
# 進入容器 docker exec -it redis-6371 bash # 切換至指定目錄 cd /usr/local/bin/
檢查集羣狀態
redis-cli -a 1234 --cluster check 192.168.10.11:6375
查看集羣信息和節點信息
# 鏈接至集羣某個節點 redis-cli -c -a 1234 -h 192.168.10.11 -p 6376 # 查看集羣信息 cluster info # 查看集羣結點信息 cluster nodes
SET/GET
在 6371 節點中執行寫入和讀取,命令以下:
# 進入容器並鏈接至集羣某個節點 docker exec -it redis-6371 /usr/local/bin/redis-cli -c -a 1234 -h 192.168.10.10 -p 6371 # 寫入數據 set name mrhelloworld set aaa 111 set bbb 222 # 讀取數據 get name get aaa get bbb
彆着急,讓我來解釋一下上圖中的操做過程:
- 首先進入容器並鏈接至集羣某個節點;
- 而後執行第一個 set 命令
set name mrhelloworld
,name
鍵根據哈希函數運算之後獲得的值爲[5798]
。當前集羣環境的槽分配狀況爲:[0-5460] 6371節點
,[5461-10922] 6374節點
,[10923-16383] 6372節點
,因此該鍵的存儲就被分配到了 6374 節點上; - 再來看第二個 set 命令
set aaa
,這裏你們可能會有一些疑問,爲何看不到aaa
鍵根據哈希函數運算之後獲得的值?由於剛纔重定向至 6374 節點插入了數據,此時若是還有數據插入,正好鍵根據哈希函數運算之後獲得的值也還在該節點的範圍內,那麼直接插入數據便可; - 接着是第三個 set 命令
set bbb
,bbb
鍵根據哈希函數運算之後獲得的值爲[5287]
,因此該鍵的存儲就被分配到了 6371 節點上; - 而後是讀取操做,第四個命令
get name
,name
鍵根據哈希函數運算之後獲得的值爲[5798]
,被重定向至 6374 節點讀取; - 第五個命令
get aaa
,aaa
鍵根據哈希函數運算之後獲得的值也在 6374 節點,直接讀取; - 第六個命令
get bbb
,bbb
鍵根據哈希函數運算之後獲得的值爲[5287]
,被重定向至 6371 節點讀取。
經過以上操做咱們得知 name
鍵的存儲被分配到了 6374 節點,若是直接鏈接 6374 節點並獲取該值會怎麼樣?沒錯,不須要重定向節點,由於數據就在該節點,因此直接讀取返回。
客戶端鏈接
最後來一波客戶端鏈接操做,隨便哪一個節點,看看能否經過外部訪問 Redis Cluster 集羣。
至此使用多機環境多個容器搭建 Redis Cluster 集羣環境就到這裏,其實總體搭建過程不算特別麻煩,由於:
- 建立 Redis 集羣須要用到 Ruby,不然就得本身關聯節點構建集羣,本身分配槽;
- 若是使用 Ruby 構建 Redis 集羣,就須要安裝 Ruby 環境;
- 而 Redis 從 5 版本開始能夠直接使用
redis-cli
命令建立集羣了,就省去了不少麻煩事; - 咱們還使用了 shell for 循環語句簡化了構建過程,不然那些語句一條條執行也夠你鬧心的。
綜上所述,有沒有更簡單的辦法呢?固然有了,否則我在這跟你賣什麼關子。
Docker Compose 就能夠解決這個問題。後面咱們先學習一下什麼是 Docker Compose,而後使用 Docker Compose 再來搭建一遍 Redis Cluster 集羣環境,感覺感覺這先後的區別。
本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議
。
🤗 您的點贊
和轉發
是對我最大的支持。
📢 掃碼關注 哈嘍沃德先生
「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~