Docker 搭建 Redis Cluster 集群環(huán)境

使用 Docker 搭建 Redis Cluster,最重要的環(huán)節(jié)就是容器通信的問題,這一塊我們在之前的文章中已經(jīng)給大家解決了《Docker 網(wǎng)絡(luò)模式詳解及容器間網(wǎng)絡(luò)通信》,本篇文章主要練習(xí)使用多個(gè)容器完成 Redis Cluster 集群環(huán)境的搭建,順便為學(xué)習(xí) Docker Compose 鋪鋪路。俗話說沒有對比就沒有傷害,通過對比才能感受到 Docker Compose 的好處 ??。

關(guān)于 Redis Cluster 集群更多的內(nèi)容請閱讀《最通俗易懂的 Redis 架構(gòu)模式詳解》。

按照 Redis 官網(wǎng):https://redis.io/topics/cluster-tutorial 的提示,為了使 Docker 與 Redis Cluster 兼容,您需要使用 Docker 的 host 網(wǎng)絡(luò)模式。

host 網(wǎng)絡(luò)模式需要在創(chuàng)建容器時(shí)通過參數(shù) --net host 或者 --network host 指定,host 網(wǎng)絡(luò)模式可以讓容器共享宿主機(jī)網(wǎng)絡(luò)棧,容器將不會(huì)虛擬出自己的網(wǎng)卡,配置自己的 IP 等,而是使用宿主機(jī)的 IP 和端口。

環(huán)境

為了讓環(huán)境更加真實(shí),本文使用多機(jī)環(huán)境:

  • 192.168.10.10
  • 192.168.10.11

每臺(tái)機(jī)器所使用的基礎(chǔ)設(shè)施環(huán)境如下:

  • CentOS 7.8.2003
  • Docker version 19.03.12

搭建

整體搭建步驟主要分為以下幾步:

  • 下載 Redis 鏡像(其實(shí)這步可以省略,因?yàn)閯?chuàng)建容器時(shí),如果本地鏡像不存在,就會(huì)去遠(yuǎn)程拉?。?/li>
  • 編寫 Redis 配置文件;
  • 創(chuàng)建 Redis 容器;
  • 創(chuàng)建 Redis Cluster 集群。

編寫 Redis 配置文件

創(chuàng)建目錄及文件

分別在 192.168.10.10192.168.10.11 兩臺(tái)機(jī)器上執(zhí)行以下操作。

# 創(chuàng)建目錄
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 機(jī)器的 redis-cluster.tmpl 文件內(nèi)容如下:

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 機(jī)器的 redis-cluster.tmpl 文件內(nèi)容如下:

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:節(jié)點(diǎn)端口;
  • requirepass:添加訪問認(rèn)證;
  • masterauth:如果主節(jié)點(diǎn)開啟了訪問認(rèn)證,從節(jié)點(diǎn)訪問主節(jié)點(diǎn)需要認(rèn)證;
  • protected-mode:保護(hù)模式,默認(rèn)值 yes,即開啟。開啟保護(hù)模式以后,需配置 bind ip 或者設(shè)置訪問密碼;關(guān)閉保護(hù)模式,外部網(wǎng)絡(luò)可以直接訪問;
  • daemonize:是否以守護(hù)線程的方式啟動(dòng)(后臺(tái)啟動(dòng)),默認(rèn) no;
  • appendonly:是否開啟 AOF 持久化模式,默認(rèn) no;
  • cluster-enabled:是否開啟集群模式,默認(rèn) no;
  • cluster-config-file:集群節(jié)點(diǎn)信息文件;
  • cluster-node-timeout:集群節(jié)點(diǎn)連接超時(shí)時(shí)間;
  • cluster-announce-ip:集群節(jié)點(diǎn) IP,填寫宿主機(jī)的 IP;
  • cluster-announce-port:集群節(jié)點(diǎn)映射端口;
  • cluster-announce-bus-port:集群節(jié)點(diǎn)總線端口。

每個(gè) Redis 集群節(jié)點(diǎn)都需要打開兩個(gè) TCP 連接。一個(gè)用于為客戶端提供服務(wù)的正常 Redis TCP 端口,例如 6379。還有一個(gè)基于 6379 端口加 10000 的端口,比如 16379。

第二個(gè)端口用于集群總線,這是一個(gè)使用二進(jìn)制協(xié)議的節(jié)點(diǎn)到節(jié)點(diǎn)通信通道。節(jié)點(diǎn)使用集群總線進(jìn)行故障檢測、配置更新、故障轉(zhuǎn)移授權(quán)等等。客戶端永遠(yuǎn)不要嘗試與集群總線端口通信,與正常的 Redis 命令端口通信即可,但是請確保防火墻中的這兩個(gè)端口都已經(jīng)打開,否則 Redis 集群節(jié)點(diǎn)將無法通信。

192.168.10.10 機(jī)器的 redis-cluster 目錄下執(zhí)行以下命令:

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 機(jī)器的 redis-cluster 目錄下執(zhí)行以下命令:

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 語句,意思就是循環(huán)創(chuàng)建 6371 ~ 6376 相關(guān)的目錄及文件。

192.168.10.10 機(jī)器執(zhí)行查看命令結(jié)果如下,如果沒有 tree 命令先安裝 yum install -y tree。

192.168.10.11 機(jī)器執(zhí)行查看命令結(jié)果如下。

以下內(nèi)容為每個(gè)節(jié)點(diǎn)的配置文件詳細(xì)信息。

============================== 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 ==============================

創(chuàng)建 Redis 容器

創(chuàng)建容器

將宿主機(jī)的 6371 ~ 6376 之間的端口與 6 個(gè) Redis 容器映射,并將宿主機(jī)的目錄與容器內(nèi)的目錄進(jìn)行映射(目錄掛載)。記得指定網(wǎng)絡(luò)模式,使用 host 網(wǎng)絡(luò)模式。

192.168.10.10 機(jī)器執(zhí)行以下命令:

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 機(jī)器執(zhí)行以下命令:

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 機(jī)器執(zhí)行 docker ps -n 3 查看容器是否創(chuàng)建成功。

192.168.10.11 機(jī)器執(zhí)行 docker ps -n 3 查看容器是否創(chuàng)建成功。

創(chuàng)建 Redis Cluster 集群

隨便進(jìn)入一個(gè)容器節(jié)點(diǎn),并進(jìn)入 /usr/local/bin/ 目錄:

# 進(jìn)入容器
docker exec -it redis-6371 bash
# 切換至指定目錄
cd /usr/local/bin/

接下來我們就可以通過以下命令實(shí)現(xiàn) Redis Cluster 集群的創(chuàng)建。

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

出現(xiàn)選擇提示信息,輸入 yes,結(jié)果如下所示:

集群創(chuàng)建成功如下:

以下內(nèi)容是創(chuàng)建集群時(shí)返回的詳細(xì)信息,也就是上兩幅圖中的所有內(nèi)容。

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.

至此一個(gè)高可用的 Redis Cluster 集群搭建完成,如下圖所示,該集群中包含 6 個(gè) Redis 節(jié)點(diǎn),3 主 3 從。三個(gè)主節(jié)點(diǎn)會(huì)分配槽,處理客戶端的命令請求,而從節(jié)點(diǎn)可用在主節(jié)點(diǎn)故障后,頂替主節(jié)點(diǎn)。

查看集群狀態(tài)

我們先進(jìn)入容器,然后通過一些集群常用的命令查看一下集群的狀態(tài)。

# 進(jìn)入容器
docker exec -it redis-6371 bash
# 切換至指定目錄
cd /usr/local/bin/

檢查集群狀態(tài)

redis-cli -a 1234 --cluster check 192.168.10.11:6375

查看集群信息和節(jié)點(diǎn)信息

# 連接至集群某個(gè)節(jié)點(diǎn)
redis-cli -c -a 1234 -h 192.168.10.11 -p 6376
# 查看集群信息
cluster info
# 查看集群結(jié)點(diǎn)信息
cluster nodes

SET/GET

在 6371 節(jié)點(diǎn)中執(zhí)行寫入和讀取,命令如下:

# 進(jìn)入容器并連接至集群某個(gè)節(jié)點(diǎn)
docker exec -it redis-6371 /usr/local/bin/redis-cli -c -a 1234 -h 192.168.10.10 -p 6371
# 寫入數(shù)據(jù)
set name mrhelloworld
set aaa 111
set bbb 222
# 讀取數(shù)據(jù)
get name
get aaa
get bbb

別著急,讓我來解釋一下上圖中的操作過程:

  • 首先進(jìn)入容器并連接至集群某個(gè)節(jié)點(diǎn);
  • 然后執(zhí)行第一個(gè) set 命令 set name mrhelloworld,name 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值為 [5798]。當(dāng)前集群環(huán)境的槽分配情況為:[0-5460] 6371節(jié)點(diǎn)[5461-10922] 6374節(jié)點(diǎn),[10923-16383] 6372節(jié)點(diǎn),所以該鍵的存儲(chǔ)就被分配到了 6374 節(jié)點(diǎn)上;
  • 再來看第二個(gè) set 命令 set aaa,這里大家可能會(huì)有一些疑問,為什么看不到 aaa 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值?因?yàn)閯偛胖囟ㄏ蛑?6374 節(jié)點(diǎn)插入了數(shù)據(jù),此時(shí)如果還有數(shù)據(jù)插入,正好鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值也還在該節(jié)點(diǎn)的范圍內(nèi),那么直接插入數(shù)據(jù)即可;
  • 接著是第三個(gè) set 命令 set bbb,bbb 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值為 [5287],所以該鍵的存儲(chǔ)就被分配到了 6371 節(jié)點(diǎn)上;
  • 然后是讀取操作,第四個(gè)命令 get name,name 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值為 [5798],被重定向至 6374 節(jié)點(diǎn)讀??;
  • 第五個(gè)命令 get aaaaaa 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值也在 6374 節(jié)點(diǎn),直接讀?。?/li>
  • 第六個(gè)命令 get bbb,bbb 鍵根據(jù)哈希函數(shù)運(yùn)算以后得到的值為 [5287],被重定向至 6371 節(jié)點(diǎn)讀取。

通過以上操作我們得知 name 鍵的存儲(chǔ)被分配到了 6374 節(jié)點(diǎn),如果直接連接 6374 節(jié)點(diǎn)并獲取該值會(huì)怎么樣?沒錯(cuò),不需要重定向節(jié)點(diǎn),因?yàn)閿?shù)據(jù)就在該節(jié)點(diǎn),所以直接讀取返回。

客戶端連接

最后來一波客戶端連接操作,隨便哪個(gè)節(jié)點(diǎn),看看可否通過外部訪問 Redis Cluster 集群。

至此使用多機(jī)環(huán)境多個(gè)容器搭建 Redis Cluster 集群環(huán)境就到這里,其實(shí)整體搭建過程不算特別麻煩,因?yàn)椋?/p>

  • 創(chuàng)建 Redis 集群需要用到 Ruby,否則就得自己關(guān)聯(lián)節(jié)點(diǎn)構(gòu)建集群,自己分配槽;
  • 如果使用 Ruby 構(gòu)建 Redis 集群,就需要安裝 Ruby 環(huán)境;
  • 而 Redis 從 5 版本開始可以直接使用 redis-cli 命令創(chuàng)建集群了,就省去了很多麻煩事;
  • 我們還使用了 shell for 循環(huán)語句簡化了構(gòu)建過程,否則那些語句一條條執(zhí)行也夠你鬧心的。

綜上所述,有沒有更簡單的辦法呢?當(dāng)然有了,不然我在這跟你賣什么關(guān)子。

Docker Compose 就可以解決這個(gè)問題。后面我們先學(xué)習(xí)一下什么是 Docker Compose,然后使用 Docker Compose 再來搭建一遍 Redis Cluster 集群環(huán)境,感受感受這前后的區(qū)別。

本文采用 知識(shí)共享「署名-非商業(yè)性使用-禁止演繹 4.0 國際」許可協(xié)議。

大家可以通過 分類 查看更多關(guān)于 Docker 的文章。


?? 您的點(diǎn)贊轉(zhuǎn)發(fā)是對我最大的支持。

?? 關(guān)注公眾號(hào) 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學(xué)習(xí)更輕松噢 ~


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容