1. 程式人生 > 資料庫 >使用Docker搭建Redis主從複製的叢集

使用Docker搭建Redis主從複製的叢集

在主從複製模式的叢集裡,主節點一般是一個,從節點一般是兩個或多個,寫入主節點的資料會被複制到從節點上,這樣一旦主節點出現故障,應用系統能切換到從節點去讀寫資料,這樣能提升系統的可用性。而且如果再採用主從複製模式裡預設的讀寫分離的機制,更能提升系統的快取讀寫效能。所以對效能和實時性不高的系統而言,主從複製模式足以滿足一般的效能和安全性方面的需求。

1 概述主從複製模式

在實際應用中,如果有相應的設定,在向一臺Redis伺服器裡寫資料後,這個資料可以複製到另外一臺(或多臺)Redis伺服器,這裡資料來源伺服器叫主伺服器(Master Server),而複製資料目的地所在的伺服器叫從伺服器(Slave Server)。

這種主從複製模式能帶來兩個好處,第一,可以把寫操作集中在主伺服器上,把讀操作集中到從伺服器上,這樣能提升讀寫效能;第二,由於出現了資料備份,所以能提升資料安全性,比如當主Redis伺服器失效後,能很快切換到從伺服器上讀資料。

如果在專案,併發要求不高,或者說哪怕從Redis快取裡讀不到資料對效能也不會有太大的損害,那麼可以用一主一從的複製模式,效果圖如下圖所示。

使用Docker搭建Redis主從複製的叢集

也可以設定一主多從的複製效果,在下圖裡,給出對應的效果圖,即寫到主節點的資料會同步到兩個從節點上,其它一主多從的模式和這很相似。

使用Docker搭建Redis主從複製的叢集

關於主從複製模式,請大家注意如下的要點。

第一, 一個主伺服器可以帶一個或多個從伺服器,甚至從伺服器也可以再帶從伺服器,但在複製資料時,只能把主伺服器的資料複製到從伺服器上,反之不能。

第二, 一臺從伺服器只能跟隨一臺主伺服器,而不能出現一從多主的模式。

第三, 在 Redis 2.8以後的版本里,是採用非同步的複製模式,即進行主從複製時,不會影響主伺服器上的讀寫資料操作。

2 用命令搭建主從叢集

這裡將用Docker容器來搭建一主二從模式的叢集,在配置主從關係時,需要在從節點上使用slaveof命令,具體的步驟如下。

第一步,開啟一個命令視窗,在其中執行如下命令建立一個名為redis-master的Redis容器,請注意它的埠是6379。

docker run -itd --name redis-master -p 6379:6379 redis:latest

第二步,再新開一個命令視窗,在其中執行如下命令建立一個名為redis-slave1的容器,請注意它的埠是6380。請注意這裡是在一臺電腦上執行,所以用埠號來區別一臺主Redis容器和另外兩臺從Redis容器。如果在真實專案裡,多臺Redis會部署在不同的伺服器上,所以可以都用6379埠。

docker run -itd --name redis-slave1 -p 6380:6380 redis:latest

第三步,回到包含redis-master容器的命令視窗,在其中執行docker inspect redis-master命令,檢視redis-master容器的資訊,在其中能通過IPAddress項看到改容器的IP地址,這裡是172.17.0.2。如果在真實專案裡,Redis伺服器所在的IP地址是固定的,而通過Docker容器啟動的Redis伺服器的IP地址是動態的,所以這裡要用上述命令來獲取IP地址。

第四步,在redis-master容器的命令窗口裡,執行docker exec -it redis-master /bin/bash命令,進入到命令列視窗,在其中用redis-cli命令進入到Redis客戶端命令列後,再通過info replication命令檢視當前的主從模式的狀態,能看到如下所示的部分結果。

 c:\work>docker exec -it redis-master /bin/bash
    root@9433cd584d80:/data# redis-cli
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:0

從第5行的輸出裡能看到,當前reids-master容器在主從模式裡的角色是“主伺服器”,從第6行的輸出裡能看到,當前該主伺服器沒有攜帶從伺服器。

同樣再到redis-slave1容器的命令窗口裡,通過docker exec -it redis-slave1 /bin/bash命令進入容器的命令列視窗,也通過redis-cli命令進入客戶端命令列,也再通過info replication命令檢視該Redis伺服器的主從模式的狀態,部分結果如下所示。

 c:\work>docker exec -it redis-slave1 /bin/bash
    root@2e3237c60211:/data# redis-cli
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:0

由於此時還沒有通過命令列設定主從模式,所以從第5行和第6行的輸出結果裡,依然看到當前伺服器是“主伺服器”,同時沒有攜帶從伺服器。

第五步,在redis-slave1容器的命令窗口裡,執行如下的slaveof命令,指定當前Redis伺服器為從伺服器。該命令的格式是slaveof IP地址 埠號,這裡是指向172.17.0.2:6379所在的主伺服器。

slaveof 172.17.0.2 6379

執行完該命令後,還是在redis-slave1客戶端裡,再次執行info replication,會看到如下所示的部分結果。從第3行的結果裡能看到,該redis-slave1伺服器已經成為從伺服器,並能從第4行和第5行的輸出裡能確認,該從伺服器是從屬於172.17.0.2:6379所在的Redis主伺服器。

127.0.0.1:6379> info replication
    # Replication
    role:slave
    master_host:172.17.0.2
    master_port:6379

此時再回到redis-master容器的命令窗口裡,在Redis客戶端裡再次執行info replication命令檢視主從狀態,能看到如下所示的部分結果。從第4行的輸出裡能看到,該Redis主伺服器已經攜帶了一個從伺服器。

 127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:1

第六步,再開啟一個新的命令視窗,在其中執行如下命令,開啟一個新的名為redis-slave2的Redis容器,請注意它的埠是6381。

docker run -itd --name redis-slave2 -p 6381:6381 redis:latest

隨後再執行docker exec -it redis-slave2 /bin/bash命令進入該容器的命令列視窗,再通過redis-cli命令進入客戶端,執行slaveof 172.17.0.2 6379命令,把這個Redis伺服器也設為從伺服器,並連到redis-master這個容器所在的主Redis伺服器上。

連線完成後,再回到redis-master容器所在的命令列視窗,再執行info replication命令,此時能看到如下的部分輸出,從第4行的輸出裡能看到,當前該主伺服器連線著兩臺從伺服器。

127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:2

至此配置完成一主兩從模式的主從模式,此時如果到兩臺從伺服器裡執行get name命令,返回是空,如果到redis-master容器所在的命令列視窗,在其中執行set name Peter後,再到兩臺從伺服器裡執行get name命令,就能看到返回值。這說明主從模式配置成功,主伺服器裡的資料會自動同步到各從伺服器上。

3 通過配置搭建主從叢集

在專案裡可以用slaveof命令搭建主從模式的叢集外,還可以用配置引數的方式來搭建,具體的步驟如下。

第一步,搭建主伺服器redis-master的命令不變,依然用如下的命令,這裡還是用6379埠。

docker run -itd --name redis-master -p 6379:6379 redis:latest

用docker inspect redis-master命令確認該Redis伺服器所在容器的IP地址依然是172.17.0.2。

第二步,到C:\work\redis\redisConf目錄裡,建立配置檔案redisSlave1.conf,並在其中編寫如下內容。

port 6380

slaveof 172.17.0.2 6379

通過第1行的命令,設定該Redis的埠為6380,通過第2行的slaveof配置,把該Redis伺服器設定成“從模式”,並連線到redis-master所在的主伺服器上。

第三步,在新的命令窗口裡執行如下的命令,建立名為redids-slave1的Redis伺服器。該伺服器的工作埠是6380,並且用redis-server後的引數指定在啟動Redis伺服器時載入redisSlave1.conf配置檔案,

docker run -itd --name redis-slave1 -v C:\work\redis\redisConf:/redisConfig:rw -p 6380:6380 redis:latest redis-server /redisConfig/redisSlave1.conf

隨後再通過docker exec -it redis-slave1 /bin/bash命令進入到該容器的命令列,由於這裡Redis工作埠已經變成6380,所以需要通過redis-cli -h 127.0.0.1 -p 6380命令來進入Redis客戶端,如果在其中執行info replication命令,能看到如下的部分結果,由此能進一步確認redis-slave1伺服器已經從屬於redis-master伺服器。

 root@80e7ae14a322:/data# redis-cli -h 127.0.0.1 -p 6380
    127.0.0.1:6380> info replication
    # Replication
    role:slave
    master_host:172.17.0.2
    master_port:6379

第四步,到C:\work\redis\redisConf目錄裡,建立配置檔案redisSlave2.conf,並在其中編寫如下內容。

port 6381

slaveof 172.17.0.2 6379

這裡用到了6381埠,同樣也通過slaveof命令連線到redis-master伺服器上。隨後在新的命令窗口裡執行如下的命令,建立名為redids-slave2的Redis伺服器。該伺服器的工作埠是6381,並且用redis-server後的引數指定在啟動Redis伺服器時載入redisSlave2.conf配置檔案,

docker run -itd --name redis-slave2 -v C:\work\redis\redisConf:/redisConfig:rw -p 6381:6381 redis:latest redis-server /redisConfig/redisSlave2.conf

隨後再通過docker exec -it redis-slave2 /bin/bash命令進入到該容器的命令列,由於這裡Redis工作埠已經變成6381,所以需要通過redis-cli -h 127.0.0.1 -p 6381命令來進入Redis客戶端,這裡可以再通過info replication命令確認配置效果,部分執行結果如下所示。

root@6017108b97c4:/data# redis-cli -h 127.0.0.1 -p 6381
    127.0.0.1:6381> info replication
    # Replication
    role:slave
    master_host:172.17.0.2
    master_port:6379

至此完成了以配置檔案設定主從複製叢集的設定,此時如果到主伺服器redis-master所在的客戶端裡執行set age 18命令,再到redis-slave1和redis-slave2這兩臺從伺服器裡執行get age命令,能看到age的值,由此能再次確認主從伺服器之間能同步資料。

4 配置讀寫分離效果

如果在上文裡配置的redis-slave1和redis-slave2這兩臺從伺服器裡,執行info replication命令,還能看到“slave_read_only:1”這項配置,說明從伺服器預設是“只讀”的,如果到redis-slave1的Redis客戶端命令列裡輸入set val 1,會看到如下第2行所示的錯誤,從而能進一步驗證該Redis伺服器的“只讀”屬性。

127.0.0.1:6380> set val 1

(error) READONLY You can't write against a read only replica.

對於Redis從伺服器而言,建議採用預設的“只讀”配置,因為在專案裡,一般不會向作為資料同步目的地的“從伺服器”上寫資料。如果業務上確實需要,可以通過如下的步驟設定“可讀可寫”的效果。

第一步,在上文提到的redisSlave2.conf配置檔案裡再加入一行“slave-read-only no”的配置,指定該伺服器可讀可寫。

第二步,如果上文提到的redis-slave2容器還處於活動狀態,則需要先用docker stop redis-slave2停止該容器,隨後再用docker rm redis-slave2命令刪除該容器,之後可以再用如下的命令再次建立redis-slave2容器。

docker run -itd --name redis-slave2 -v C:\work\redis\redisConf:/redisConfig:rw -p 6381:6381 redis:latest redis-server /redisConfig/redisSlave2.conf

在redis-server命令後所帶的redisSlave2.conf配置檔案裡,已經用“slave-read-only no”配置項設定了“可讀可寫”的模式。

第三步,再通過docker exec -it redis-slave2 /bin/bash命令進入到該容器的命令列,再通過redis-cli -h 127.0.0.1 -p 6381命令進入Redis客戶端, 此時如果再執行set val 1命令,就能成功寫入資料。

5 用心跳機制提升主從複製可靠性

在Redis主從複製模式裡,如果主從伺服器之間有資料同步的情況,那麼從伺服器會預設以一秒一次的頻率,向主伺服器傳送REPLCONF ACK命令,依次來確保兩者間連線通暢。這種定時互動命令確保連線的機制就叫“心跳”機制。在上文開啟的redis-master這個主伺服器的命令列裡,如果執行info replication命令,能看到它從屬伺服器的“心跳”狀況。

 127.0.0.1:6379> info replication
   2  # Replication
   3  role:master
   4  connected_slaves:2
   5  slave0:ip=172.17.0.3,port=6380,state=online,offset=16185,lag=1
   6  slave1:ip=172.17.0.4,port=6381,lag=1

其中在第5行和第6行裡,能通過lag表示該從屬伺服器傳送REPLCONF ACK命令的時間,這裡均是1秒,這表示兩臺從伺服器和主伺服器的連線均屬通暢。

這裡大家可以想象下,如果從伺服器宕機,那麼主從複製就沒有意義了。對此,可以通過如下的步驟來關聯心跳機制和主動複製的動作。

第一步,在C:\work\redis\redisConf目錄裡新建redisMaster.conf檔案,在其中編寫如下的程式碼。

min-slaves-to-write 2

min-slaves-max-lag 15

第1行的引數表示實現主從複製的從伺服器個數最少是2臺,第2行的引數表示,如果有第1行引數指定的從伺服器個數(這裡是2臺)的心跳延遲時間(即lag值)大於15秒,不執行主從複製。

這兩個條件是“或者”的關係,即只要出現從伺服器個數小於2,或者2臺從伺服器的心跳延遲時間大於15秒,主伺服器即停止主從複製的操作。

第二步,通過如下的命令啟動redis-master容器,由於此時啟動Redis伺服器時已經載入了上述配置,所以該Redis主伺服器在執行主從複製時,會檢測第一步所設定的條件。從而能提升主從複製的可靠性。

docker run -itd --name redis-master -v C:\work\redis\redisConf:/redisConfig:rw -p 6379:6379 redis:latest redis-server /redisConfig/redisMaster.conf

6 用偏移量檢查資料是否一致

在上文開啟的redis-master主伺服器的命令列裡,如果執行info replication命令,還能看到表示複製資料偏移量的master_repl_offset資料,效果如下第6行所示。這裡資料是276,表示主伺服器向從伺服器傳送資料的位元組數。

127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:1
    …
    master_repl_offset:276

同樣如果到redis-slave1從伺服器的命令列裡,也能通過info replication檢視該偏移量,效果如下第7行所示。

127.0.0.1:6380> info replication
    # Replication
    role:slave
    master_host:172.17.0.2
    master_port:6379
    …
    slave_repl_offset:276

在從伺服器裡,該資料表示從主伺服器中接收到的資料位元組數,如果主從伺服器中兩者資料一致,這說明主從伺服器間的資料是同步的。

當在主伺服器redis-master裡執行set nextVal 1命令後,再用info replication檢視master_repl_offset數值,會發現有變化,而此時再到redis-slave1從伺服器執行info replication命令,會發現從伺服器的master_repl_offset數值依然和主伺服器一致,這說明用set nextVal 1命令在主伺服器裡增加的資料已經成功同步到從伺服器。也就是說,如果出現Redis問題,可以通過master_repl_offset數值來檢查同步資料是否正確,由此再進一步排查問題。

總結

到此這篇關於使用Docker搭建Redis主從複製的叢集的文章就介紹到這了,更多相關Docker搭建Redis主從複製的叢集內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!