前面介紹Redis,我們都在一台伺服器上進行操作的,也就是說讀和寫以及備份操作都是在一台Redis伺服器上進行的,那麼随着項目通路量的增加,對Redis伺服器的操作也越加頻繁,雖然Redis讀寫速度都很快,但是一定程度上也會造成一定的延時,那麼為了解決通路量大的問題,通常會采取的一種方式是主從架構Master/Slave,Master 以寫為主,Slave 以讀為主,Master 主節點更新後根據配置,自動同步到從機Slave 節點。
接下來我們就來介紹如何進行主從架構的搭建。
ps:這裡我是在一台機器上模拟多個Redis伺服器,與實際生産環境中相比,基本配置都是一樣,僅僅是IP位址和端口号變化。

1、修改配置檔案
首先将redis.conf 配置檔案複制三份,通過修改端口分别模拟三台Redis伺服器。
然後我們分别對這三個redis.conf 檔案進行修改。
①、修改 daemonize yes
表示指定Redis以守護程序的方式啟動(背景啟動)
②、配置PID檔案路徑 pidfile
表示當redis作為守護程序運作的時候,它會把 pid 預設寫到 /var/redis/run/redis_6379.pid 檔案裡面
③、配置端口 port
④、配置log 檔案名字
⑤、配置rdb檔案名
依次将 6380redis.conf 、6381redis.conf 配置一次,則配置完畢。
接下來我們分别啟動這三個服務。
通過指令檢視Redis是否啟動:
接下來通過如下指令分别進入到這三個Redis用戶端:
redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381
2、設定主從關系
①、通過 info replication 指令檢視節點角色
我們發現這三個節點都是扮演的 Master 角色。那麼如何将 6380 和 6381 節點變為 Slave 角色呢?
②、選擇6380端口和6381端口,執行指令:SLAVEOF 127.0.0.1 6379
我們再看 6379 節點資訊:
這裡通過指令來設定主從關系,一旦服務重新開機,那麼角色關系将不複存在。想要永久的儲存這種關系,可以通過配置redis.conf 檔案來配置。
slaveof 127.0.0.1 6379
3、測試主從關系
①、增量複制
主節點執行 set k1 v1 指令,從節點 get k1 能擷取嗎?
由上圖可知是可以擷取的。
②、全量複制
通過執行 SLAVEOF 127.0.0.1 6379,如果主節點 6379 以前還存在一些 key,那麼執行指令之後,從節點會将以前的資訊也都複制過來嗎?
答案也是肯定的,這裡我就不貼測試結果了。
③、主從讀寫分離
主節點能夠執行寫指令,從節點能夠執行寫指令嗎?
這裡的原因是在配置檔案 6381redis.conf 中對于 slave-read-only 的配置
如果我們将其修改為 no 之後,執行寫指令是可以的。
但是從節點寫指令的資料從節點或者主節點都不能擷取的。
④、主節點當機
主節點 Maste 挂掉,兩個從節點角色會發生變化嗎?
上圖可知主節點 Master 挂掉之後,從節點角色還是不會改變的。
⑤、主節點當機後恢複
主節點Master挂掉之後,馬上啟動主機Maste,主節點扮演的角色還是 Master 嗎?
也就是說主節點挂掉之後重新開機,又恢複了主節點的角色。
4、哨兵模式
通過前面的配置,主節點Master 隻有一個,一旦主節點挂掉之後,從節點沒法擔起主節點的任務,那麼整個系統也無法運作。如果主節點挂掉之後,從節點能夠自動變成主節點,那麼問題就解決了,于是哨兵模式誕生了。
哨兵模式就是不時地監控redis是否按照預期良好地運作(至少是保證主節點是存在的),若一台主機出現問題時,哨兵會自動将該主機下的某一個從機設定為新的主機,并讓其他從機和新主機建立主從關系。
哨兵模式搭建步驟:
①、在配置檔案目錄下建立 sentinel.conf 檔案,名字絕不能錯,然後配置相應内容
sentinel monitor 被監控機器的名字(自己起名字) ip位址 端口号 得票數
分别配置被監控的名字,ip位址,端口号,以及得票數。上面的得票數為1表示表示主機挂掉後salve投票看讓誰接替成為主機,得票數大于1便成為主機
②、啟動哨兵
redis-sentinel /etc/redis/sentinel.conf
啟動界面:
接下來,我們幹掉主機 6379,然後看從節點有啥變化。
幹掉主節點之後,我們檢視背景列印日志,發現 6381投票變為主節點了。
這時候我們檢視從節點 6381的節點資訊:
6381 節點自動變為主節點了。
PS:哨兵模式也存在單點故障問題,如果哨兵機器挂了,那麼就無法進行監控了,解決辦法是哨兵也建立叢集,Redis哨兵模式是支援叢集的。
5、主從複制原理
Redis的複制功能分為同步(sync)和指令傳播(command propagate)兩個操作。
①、舊版同步
當從節點發出 SLAVEOF 指令,要求從伺服器複制主伺服器時,從伺服器通過向主伺服器發送 SYNC 指令來完成。該指令執行步驟:
1、從伺服器向主伺服器發送 SYNC 指令
2、收到 SYNC 指令的主伺服器執行 BGSAVE 指令,在背景生成一個 RDB 檔案,并使用一個緩沖區記錄從開始執行的所有寫指令
3、當主伺服器的 BGSAVE 指令執行完畢時,主伺服器會将 BGSAVE 指令生成的 RDB 檔案發送給從伺服器,從伺服器接收此 RDB 檔案,并将伺服器狀态更新為RDB檔案記錄的狀态。
4、主伺服器将緩沖區的所有寫指令也發送給從伺服器,從伺服器執行相應指令。
②、指令傳播
當同步操作完成之後,主伺服器會進行相應的修改指令,這時候從伺服器和主伺服器狀态就會不一緻。
為了讓主伺服器和從伺服器保持狀态一緻,主伺服器需要對從伺服器執行指令傳播操作,主伺服器會将自己的寫指令發送給從伺服器執行。從伺服器執行相應的指令之後,主從伺服器狀态繼續保持一緻。
總結:通過同步操作以及指令傳播功能,能夠很好的保證了主從一緻的特性。
但是我們考慮一個問題,如果從伺服器在同步主伺服器期間,突然斷開了連接配接,而這時候主伺服器進行了一些寫操作,這時候從伺服器恢複連接配接,如果我們在進行同步,那麼就必須将主伺服器從新生成一個RDB檔案,然後給從伺服器加載,這樣雖然能夠保證一緻性,但是其實斷開連接配接之前主從伺服器狀态是保持一緻的,不一緻的是從伺服器斷開連接配接,而主伺服器執行了一些寫指令,那麼從伺服器恢複連接配接後能不能隻要斷開連接配接的哪些寫指令,而不是整個RDB快照呢?
同步操作其實是一個非常耗時的操作,主伺服器需要先通過 BGSAVE 指令來生成一個 RDB 檔案,然後需要将該檔案發送給從伺服器,從伺服器接收該檔案之後,接着加載該檔案,并且加載期間,從伺服器是無法處理其他指令的。
為了解決這個問題,Redis從2.8版本之後,使用了新的同步指令 PSYNC 來代替 SYNC 指令。該指令的部分重同步功能用于處理斷線後重複制的效率問題。也就是說當從伺服器在斷線後重新連接配接主伺服器時,主伺服器隻将斷開連接配接後執行的寫指令發送給從伺服器,從伺服器隻需要接收并執行這些寫指令即可保持主從一緻。
6、主從複制的缺點
主從複制雖然解決了主節點的單點故障問題,但是由于所有的寫操作都是在 Master 節點上操作,然後同步到 Slave 節點,那麼同步就會有一定的延時,當系統很繁忙的時候,延時問題就會更加嚴重,而且會随着從節點slave的增多而愈加嚴重。
作者:
YSOcean出處:
http://www.cnblogs.com/ysocean/本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。