1. 程式人生 > 程式設計 >docker-compose搭建redis叢集及可用性實踐

docker-compose搭建redis叢集及可用性實踐

叢集搭建概述

redis一般需要6個節點才能組成完整的高可用叢集,這裡我們使用docker-compose來快速搭建叢集。 叢集搭建一般分為三個步驟:

  • 準備節點
  • 節點握手
  • 分配槽

步驟一:準備節點

從GitHub下載程式碼

專案GitHub地址:github.com/willcat/red…

注意

由於程式碼更新,在配置檔案中手動設定了容器名稱,所以文章和程式碼中的容器名有區別,比如文章中的redis-cluster_redis-cluster-6380_1,在程式碼和實際執行中是node-80,文章中的redis-cluster_redis-cluster-6381_1,在程式碼和實際執行中是node-81

開啟後臺服務,啟動所有節點

進入redis-cluster-docker目錄,執行docker-compose up -d

檢查當前叢集狀況

隨便進入一個容器比如redis-cluster_redis-cluster-6380_1[1],docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380,然後執行cluster nodes命令,整個過程如下:

$ docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380
127.0.0.1:6380> cluster nodes
3914fe7597f9ad9e9c485cf473bcaa461973baaa :6380@16380 myself,master - 0 0 0 connected

複製程式碼

可以看到目前各個節點還只能返回自己的資訊,每個節點還不能感知到彼此。

[1] 這是docker-compose根據我們在docker-compose.yml配置的服務名稱自動生成的,如果不想使用預設名稱,可以在配置檔案中使用container_name指定容器名稱 docker exec

步驟二 節點握手

節點握手是指一批執行在叢集模式下的節點通過Gossip協議彼此通訊,達到感知對方的過程。

  • 在某個節點上執行cluster meet {ip} {port}命令,達到兩個節點間的握手,這兩個節點就組成了一個真正的彼此感知的叢集,之後兩個節點間會定期通過ping/pong訊息進行正常的節點通訊
  • 在叢集中任意節點上執行cluster meet {ip} {port}命令,新增尚未加入叢集的新節點
  • 所有節點全部加入之後可以看到叢集中所有節點資訊
127.0.0.1:6380> cluster nodes
c6db83c252a072407707917474001c70da649407 172.26.0.6:6385@16385 master - 0 1565199856348 3 connected
e356c336482f7a8a3f786674b96ac06030b0dcb4 172.26.0.3:6381@16381 master - 0 1565199855000 0 connected
dae83c485b9fb1357947944b36007c3371a750f2 172.26.0.7:6383@16383 master - 0 1565199857362 5 connected
c87aba899473356f25a919dc2d477340f5222ba4 172.26.0.2:6382@16382 master - 0 1565199855000 4 connected
5ebbd85dfbe1e4e01bae5f4954418a436453876c 172.26.0.5:6384@16384 master - 0 1565199855339 2 connected
3914fe7597f9ad9e9c485cf473bcaa461973baaa 172.26.0.4:6380@16380 myself,master - 0 1565199855000 1 connected
複製程式碼

補充知識:docker-compose預設組網

  • 使用docker-compose up啟動容器後,這些容器都會被加入{app_name}_default網路中
  • 使用docker network ls可以檢視網路列表,docker network inspect <network_name>可以檢視對應網路的配置以及各個容器的ip。
  • 還可以通過docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-cluster_redis-cluster-6385_1命令直接檢視某個容器的ip。

步驟三 分配槽

節點建立握手之後,叢集還處於下線狀態,無法執行寫操作。

127.0.0.1:6380> set hello world
(error) CLUSTERDOWN Hash slot not served
複製程式碼

檢視叢集資訊可以看到叢集是fail狀態

127.0.0.1:6380> cluster info
cluster_state:fail
cluster_slots_assigned: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_ping_sent:718
cluster_stats_messages_pong_sent:283
cluster_stats_messages_meet_sent:8
cluster_stats_messages_sent:1009
cluster_stats_messages_ping_received:283
cluster_stats_messages_pong_received:285
cluster_stats_messages_received:568
複製程式碼

執行分配槽的命令

在各個節點上執行類似cluster addslots {0...5461}的命令,將0~16383個slot平均分配到所有節點上。這裡我們只分配三個節點,另外三個節點分別當作前面三個節點的從節點,從而在主節點出現故障時能夠自動完成故障轉移。

//分配三個節點,注意,以下三個命令在登入redis-cli之後是不成功的,只能使用redis-cli -p 6380 cluster addslots {0..5461}這種模式
$ docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380 cluster addslots {0..5461}
$ docker exec -it redis-cluster_redis-cluster-6381_1 redis-cli -p 6381 cluster addslots {5462..10922}
$ docker exec -it redis-cluster_redis-cluster-6382_1 redis-cli -p 6382 cluster addslots {10923..16282}

// 將三個未分配槽的節點設定為從節點
127.0.0.1:6383> CLUSTER REPLICATE 3914fe7597f9ad9e9c485cf473bcaa461973baaa
OK

127.0.0.1:6384> CLUSTER REPLICATE e356c336482f7a8a3f786674b96ac06030b0dcb4
OK

127.0.0.1:6385> CLUSTER REPLICATE  c87aba899473356f25a919dc2d477340f5222ba4
OK
複製程式碼

官方叢集快速搭建工具

這樣3主3從的叢集就搭建完成了,可以感覺到還是比較麻煩的,所以redis官方在redis3.xredis4.x提供了redis-trib.rb工具方便我們快速搭建叢集,在redis5.x中更是可以直接使用redis-cli命令來直接完成叢集的一鍵搭建,省去了redis-trib.rb依賴ruby環境的問題。在程式碼中,readme.md裡提供了快速搭建的命令。

//官方指出: 可以使用redis5.x 的redis-cli命令模式來搭建由redis-4.x組成的叢集。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
複製程式碼

叢集使用

請求重定向

在叢集中某個節點讀寫不屬於此節點的資料會返回錯誤(error) MOVED 5798 172.20.0.6:6381,為了減少手動切換的環節,在開啟客戶端時可以新增-c引數,開啟請求重定向,詳細命令redis-cli -p 6380 -c,這樣以後操作跨節點時會自動跳轉到相應的節點

Smart客戶端

大多數開發語言的Redis客戶端都採用Smart客戶端支援叢集協議,客戶端選擇可以參考clients

  • Smart客戶端在內容維護slot->node的對映關係,本地就可實現鍵到節點的查詢,從而保證IO效率的最大化
  • Moved重定向負責協助Smart客戶端更新slot->node的對映關係。

ASK重定向

當叢集伸縮時,slot會發生遷移,這時去原來節點讀寫會返回(error) ASK {slot} {targetIP}:{targetPort}錯誤,客戶端從ASK重定向異常提取出目標節點資訊,傳送asking命令到目標節點開啟客戶端連線標識,再執行鍵命令。如果存在則執行,不存在則返回不存在資訊。

叢集容錯

TODO