1. 程式人生 > >Docker Compose 搭建 Redis Cluster 叢集環境

Docker Compose 搭建 Redis Cluster 叢集環境

  在前文《Docker 搭建 Redis Cluster 叢集環境》中我已經教過大家如何搭建了,本文使用 Docker Compose 再帶大家搭建一遍,其目的主要是為了讓大家感受 Docker Compose 所帶來的便捷之處。   按照 Redis 官網:https://redis.io/topics/cluster-tutorial 的提示,為了使 Docker 與 Redis Cluster 相容,您需要使用 Docker 的 `host` 網路模式。   `host` 網路模式需要在建立容器時通過引數 `--net host` 或者 `--network host` 指定,`host` 網路模式可以讓**容器共享宿主機網路棧**,容器將不會虛擬出自己的網絡卡,配置自己的 IP 等,而是使用宿主機的 IP 和埠。   關於 Docker 網路模式更多的內容請閱讀《Docker 網路模式詳解及容器間網路通訊》。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f13981ab594f402dbcc4da23dc143f81~tplv-k3u1fbpfcp-zoom-1.image " ")    ## 環境      為了讓環境更加真實,本文使用**多機**環境: - `192.168.10.10` - `192.168.10.11`      每臺機器所使用的基礎設施環境如下: - `CentOS 7.8.2003` - `Docker version 19.03.12 ` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cf14de4140574fc08b7c7a936427deae~tplv-k3u1fbpfcp-zoom-1.image " ")    ## 搭建      整體搭建步驟主要分為以下幾步: - 下載 Redis 映象(其實這步可以省略,因為建立容器時,如果本地映象不存在,就會去遠端拉取); - 編寫 Redis 配置檔案; - 編寫 Docker Compose 模板檔案; - 建立並啟動所有服務容器; - 建立 Redis Cluster 叢集。    ### 編寫 Redis 配置檔案    #### 建立目錄及檔案      分別在 `192.168.10.10` 和 `192.168.10.11` 兩臺機器上執行以下操作。 ```shell # 建立目錄 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` 檔案內容如下: ```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` 檔案內容如下: ```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` 目錄下執行以下命令: ```shell 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` 目錄下執行以下命令: ```shell 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`。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e7e920193dcb4fe8be5a5acf510f37fd~tplv-k3u1fbpfcp-zoom-1.image " ")   在 `192.168.10.11` 機器執行檢視命令結果如下。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4305e29ed43341b595c691827904df2c~tplv-k3u1fbpfcp-zoom-1.image " ")      以下內容為每個節點的配置檔案詳細資訊。 ```shell ============================== 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 ============================== ```    ### 編寫 Docker Compose 模板檔案      在 `192.168.10.10` 機器的 `/usr/local/docker-redis` 目錄下建立 `docker-compose.yml` 檔案並編輯。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: redis-6371: # 服務名稱 image: redis # 建立容器時所需的映象 container_name: redis-6371 # 容器名稱 restart: always # 容器總是重新啟動 network_mode: "host" # host 網路模式 volumes: # 資料卷,目錄掛載 - /usr/local/docker-redis/redis-cluster/6371/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6371/data:/data command: redis-server /usr/local/etc/redis/redis.conf # 覆蓋容器啟動後預設執行的命令 redis-6372: image: redis container_name: redis-6372 network_mode: "host" volumes: - /usr/local/docker-redis/redis-cluster/6372/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6372/data:/data command: redis-server /usr/local/etc/redis/redis.conf redis-6373: image: redis container_name: redis-6373 network_mode: "host" volumes: - /usr/local/docker-redis/redis-cluster/6373/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6373/data:/data command: redis-server /usr/local/etc/redis/redis.conf ```      在 `192.168.10.10` 機器的 `/usr/local/docker-redis` 目錄下建立 `docker-compose.yml` 檔案並編輯。 ```yaml # 描述 Compose 檔案的版本資訊 version: "3.8" # 定義服務,可以多個 services: redis-6374: # 服務名稱 image: redis # 建立容器時所需的映象 container_name: redis-6374 # 容器名稱 restart: always # 容器總是重新啟動 network_mode: "host" # host 網路模式 volumes: # 資料卷,目錄掛載 - /usr/local/docker-redis/redis-cluster/6374/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6374/data:/data command: redis-server /usr/local/etc/redis/redis.conf # 覆蓋容器啟動後預設執行的命令 redis-6375: image: redis container_name: redis-6375 network_mode: "host" volumes: - /usr/local/docker-redis/redis-cluster/6375/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6375/data:/data command: redis-server /usr/local/etc/redis/redis.conf redis-6376: image: redis container_name: redis-6376 network_mode: "host" volumes: - /usr/local/docker-redis/redis-cluster/6376/conf/redis.conf:/usr/local/etc/redis/redis.conf - /usr/local/docker-redis/redis-cluster/6376/data:/data command: redis-server /usr/local/etc/redis/redis.conf ```    ### 建立並啟動所有服務容器      分別在 `192.168.10.10` 和 `192.168.10.11` 機器的 `/usr/local/docker-redis` 目錄下執行以下命令: ```shell docker-compose up -d ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/01024129e0af4a6289a6f54aefa4d5ed~tplv-k3u1fbpfcp-zoom-1.image " ") ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ef2e8fbca38240c996d90fef6a958d78~tplv-k3u1fbpfcp-zoom-1.image " ")    ### 建立 Redis Cluster 叢集      請先確保你的兩臺機器可以互相通訊,然後隨便進入一個容器節點,並進入 `/usr/local/bin/` 目錄: ```shell # 進入容器 docker exec -it redis-6371 bash # 切換至指定目錄 cd /usr/local/bin/ ```      接下來我們就可以通過以下命令實現 Redis Cluster 叢集的建立。 ```shell 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**,結果如下所示: ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31224912d3a844a18a5bd11249a4bc01~tplv-k3u1fbpfcp-zoom-1.image " ")   叢集建立成功如下: ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a724ec04606a4e57a002f249e1a5195a~tplv-k3u1fbpfcp-zoom-1.image " ")      以下內容是建立叢集時返回的詳細資訊,也就是上兩幅圖中的所有內容。 ```shell 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: 04444afa3ca66de6af4a182984c79d4d140293d7 192.168.10.10:6371 slots:[0-5460] (5461 slots) master M: fb76ada83a70ea8d367f22f8a6436d427f12022c 192.168.10.10:6372 slots:[10923-16383] (5461 slots) master S: 20f6913a4b08afe3b4092a4f6c70fddd9506f2fa 192.168.10.10:6373 replicates c130120ffbd7c4e442ac9fc9870e977dc801cb54 M: c130120ffbd7c4e442ac9fc9870e977dc801cb54 192.168.10.11:6374 slots:[5461-10922] (5462 slots) master S: d4d5f7fd94fcd2239e82e481f0529380b288ff51 192.168.10.11:6375 replicates fb76ada83a70ea8d367f22f8a6436d427f12022c S: e08b8f629e2dfa474a836910634052d83c77d06a 192.168.10.11:6376 replicates 04444afa3ca66de6af4a182984c79d4d140293d7 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: 04444afa3ca66de6af4a182984c79d4d140293d7 192.168.10.10:6371 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 20f6913a4b08afe3b4092a4f6c70fddd9506f2fa 192.168.10.10:6373 slots: (0 slots) slave replicates c130120ffbd7c4e442ac9fc9870e977dc801cb54 S: d4d5f7fd94fcd2239e82e481f0529380b288ff51 192.168.10.11:6375 slots: (0 slots) slave replicates fb76ada83a70ea8d367f22f8a6436d427f12022c M: fb76ada83a70ea8d367f22f8a6436d427f12022c 192.168.10.10:6372 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: c130120ffbd7c4e442ac9fc9870e977dc801cb54 192.168.10.11:6374 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: e08b8f629e2dfa474a836910634052d83c77d06a 192.168.10.11:6376 slots: (0 slots) slave replicates 04444afa3ca66de6af4a182984c79d4d140293d7 [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 從。三個主節點會分配槽,處理客戶端的命令請求,而從節點可用在主節點故障後,頂替主節點。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f9707596af6a4ea08e1d2ed9744b3f01~tplv-k3u1fbpfcp-zoom-1.image " ")    ## 檢視叢集狀態      我們先進入容器,然後通過一些叢集常用的命令檢視一下叢集的狀態。 ```shell # 進入容器 docker exec -it redis-6371 bash # 切換至指定目錄 cd /usr/local/bin/ ```    ### 檢查叢集狀態    ```shell redis-cli -a 1234 --cluster check 192.168.10.11:6375 ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/66dabc070c2e4f24964a046d368066e7~tplv-k3u1fbpfcp-zoom-1.image " ")    ### 檢視叢集資訊和節點資訊    ```shell # 連線至叢集某個節點 redis-cli -c -a 1234 -h 192.168.10.11 -p 6376 # 檢視叢集資訊 cluster info # 檢視叢集結點資訊 cluster nodes ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/291806dd75d04315abb470ebf7c8db54~tplv-k3u1fbpfcp-zoom-1.image " ")    ### SET/GET      在 6371 節點中執行寫入和讀取,命令如下: ```shell # 進入容器並連線至叢集某個節點 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 ``` ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f762ad484214d3296b46d13651ff18b~tplv-k3u1fbpfcp-zoom-1.image " ")   彆著急,讓我來解釋一下上圖中的操作過程: - 首先進入容器並連線至叢集某個節點; - 然後執行**第一個** 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 節點並獲取該值會怎麼樣?沒錯,不需要重定向節點,因為資料就在該節點,所以直接讀取返回。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c0c00eca9915462e8c518095c11ff5f3~tplv-k3u1fbpfcp-zoom-1.image " ")    ## 客戶端連線      最後來一波客戶端連線操作,隨便哪個節點,看看可否通過外部訪問 Redis Cluster 叢集。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d4808432f3e64222ba1e981bd52670f9~tplv-k3u1fbpfcp-zoom-1.image " ") ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4a53802b98a5419a98276902585110e4~tplv-k3u1fbpfcp-zoom-1.image " ")   至此使用多機環境基於 Docker Compose 搭建 Redis Cluster 就到這裡。雖然整體搭建過程感覺比起之前並沒有簡化太多。但是,如果我們想要停止並刪除 Redis Cluster 叢集環境,之前的方式就需要一個個去操作,而 Docker Compose 只需要一個 `docker-compose down` 命令的操作即可。Docker Compose 的學習及使用就到這裡,下文開始我們學習 Docker Swarm 的相關內容。 ![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e960aeaed69e4c7b9ad1931062c93956~tplv-k3u1fbpfcp-zoom-1.image) 本文采用 `知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議`。 大家可以通過 `分類` 檢視更多關於 `Docker` 的文章。