前面介紹Redis,咱們都在一臺服務器上進行操做的,也就是說讀和寫以及備份操做都是在一臺Redis服務器上進行的,那麼隨着項目訪問量的增長,對Redis服務器的操做也越加頻繁,雖然Redis讀寫速度都很快,可是必定程度上也會形成必定的延時,那麼爲了解決訪問量大的問題,一般會採起的一種方式是主從架構Master/Slave,Master 以寫爲主,Slave 以讀爲主,Master 主節點更新後根據配置,自動同步到從機Slave 節點。redis
接下來咱們就來介紹如何進行主從架構的搭建。服務器
ps:這裏我是在一臺機器上模擬多個Redis服務器,與實際生產環境中相比,基本配置都是同樣,僅僅是IP地址和端口號變化。架構
首先將redis.conf 配置文件複製三份,經過修改端口分別模擬三臺Redis服務器。測試
而後咱們分別對這三個redis.conf 文件進行修改。3d
①、修改 daemonize yes日誌
表示指定Redis以守護進程的方式啓動(後臺啓動)blog
②、配置PID文件路徑 pidfile進程
表示當redis做爲守護進程運行的時候,它會把 pid 默認寫到 /var/redis/run/redis_6379.pid 文件裏面ip
③、配置端口 portget
④、配置log 文件名字
⑤、配置rdb文件名
依次將 6380redis.conf 、6381redis.conf 配置一次,則配置完畢。
接下來咱們分別啓動這三個服務。
經過命令查看Redis是否啓動:
接下來經過以下命令分別進入到這三個Redis客戶端:
redis-cli -p 6379 redis-cli -p 6380 redis-cli -p 6381
①、經過 info replication 命令查看節點角色
咱們發現這三個節點都是扮演的 Master 角色。那麼如何將 6380 和 6381 節點變爲 Slave 角色呢?
②、選擇6380端口和6381端口,執行命令:SLAVEOF 127.0.0.1 6379
咱們再看 6379 節點信息:
這裏經過命令來設置主從關係,一旦服務重啓,那麼角色關係將不復存在。想要永久的保存這種關係,能夠經過配置redis.conf 文件來配置。
slaveof 127.0.0.1 6379
①、增量複製
主節點執行 set k1 v1 命令,從節點 get k1 能獲取嗎?
由上圖可知是能夠獲取的。
②、全量複製
經過執行 SLAVEOF 127.0.0.1 6379,若是主節點 6379 之前還存在一些 key,那麼執行命令以後,從節點會將之前的信息也都複製過來嗎?
答案也是確定的,這裏我就不貼測試結果了。
③、主從讀寫分離
主節點可以執行寫命令,從節點可以執行寫命令嗎?
這裏的緣由是在配置文件 6381redis.conf 中對於 slave-read-only 的配置
若是咱們將其修改成 no 以後,執行寫命令是能夠的。
可是從節點寫命令的數據從節點或者主節點都不能獲取的。
④、主節點宕機
主節點 Maste 掛掉,兩個從節點角色會發生變化嗎?
上圖可知主節點 Master 掛掉以後,從節點角色仍是不會改變的。
⑤、主節點宕機後恢復
主節點Master掛掉以後,立刻啓動主機Maste,主節點扮演的角色仍是 Master 嗎?
也就是說主節點掛掉以後重啓,又恢復了主節點的角色。
經過前面的配置,主節點Master 只有一個,一旦主節點掛掉以後,從節點無法擔起主節點的任務,那麼整個系統也沒法運行。若是主節點掛掉以後,從節點可以自動變成主節點,那麼問題就解決了,因而哨兵模式誕生了。
哨兵模式就是不時地監控redis是否按照預期良好地運行(至少是保證主節點是存在的),若一臺主機出現問題時,哨兵會自動將該主機下的某一個從機設置爲新的主機,並讓其餘從機和新主機創建主從關係。
哨兵模式搭建步驟:
①、在配置文件目錄下新建 sentinel.conf 文件,名字毫不能錯,而後配置相應內容
sentinel monitor 被監控機器的名字(本身起名字) ip地址 端口號 得票數
分別配置被監控的名字,ip地址,端口號,以及得票數。上面的得票數爲1表示表示主機掛掉後salve投票看讓誰接替成爲主機,得票數大於1便成爲主機
②、啓動哨兵
redis-sentinel /etc/redis/sentinel.conf
啓動界面:
接下來,咱們幹掉主機 6379,而後看從節點有啥變化。
幹掉主節點以後,咱們查看後臺打印日誌,發現 6381投票變爲主節點了。
這時候咱們查看從節點 6381的節點信息:
6381 節點自動變爲主節點了。
PS:哨兵模式也存在單點故障問題,若是哨兵機器掛了,那麼就沒法進行監控了,解決辦法是哨兵也創建集羣,Redis哨兵模式是支持集羣的。
Redis的複製功能分爲同步(sync)和命令傳播(command propagate)兩個操做。
①、舊版同步
當從節點發出 SLAVEOF 命令,要求從服務器複製主服務器時,從服務器經過向主服務器發送 SYNC 命令來完成。該命令執行步驟:
一、從服務器向主服務器發送 SYNC 命令
二、收到 SYNC 命令的主服務器執行 BGSAVE 命令,在後臺生成一個 RDB 文件,並使用一個緩衝區記錄從開始執行的全部寫命令
三、當主服務器的 BGSAVE 命令執行完畢時,主服務器會將 BGSAVE 命令生成的 RDB 文件發送給從服務器,從服務器接收此 RDB 文件,並將服務器狀態更新爲RDB文件記錄的狀態。
四、主服務器將緩衝區的全部寫命令也發送給從服務器,從服務器執行相應命令。
②、命令傳播
當同步操做完成以後,主服務器會進行相應的修改命令,這時候從服務器和主服務器狀態就會不一致。
爲了讓主服務器和從服務器保持狀態一致,主服務器須要對從服務器執行命令傳播操做,主服務器會將本身的寫命令發送給從服務器執行。從服務器執行相應的命令以後,主從服務器狀態繼續保持一致。
總結:經過同步操做以及命令傳播功能,可以很好的保證了主從一致的特性。
可是咱們考慮一個問題,若是從服務器在同步主服務器期間,忽然斷開了鏈接,而這時候主服務器進行了一些寫操做,這時候從服務器恢復鏈接,若是咱們在進行同步,那麼就必須將主服務器重新生成一個RDB文件,而後給從服務器加載,這樣雖然可以保證一致性,可是其實斷開鏈接以前主從服務器狀態是保持一致的,不一致的是從服務器斷開鏈接,而主服務器執行了一些寫命令,那麼從服務器恢復鏈接後能不能只要斷開鏈接的哪些寫命令,而不是整個RDB快照呢?
同步操做實際上是一個很是耗時的操做,主服務器須要先經過 BGSAVE 命令來生成一個 RDB 文件,而後須要將該文件發送給從服務器,從服務器接收該文件以後,接着加載該文件,而且加載期間,從服務器是沒法處理其餘命令的。
爲了解決這個問題,Redis從2.8版本以後,使用了新的同步命令 PSYNC 來代替 SYNC 命令。該命令的部分重同步功能用於處理斷線後重複製的效率問題。也就是說當從服務器在斷線後從新鏈接主服務器時,主服務器只將斷開鏈接後執行的寫命令發送給從服務器,從服務器只須要接收並執行這些寫命令便可保持主從一致。
主從複製雖然解決了主節點的單點故障問題,可是因爲全部的寫操做都是在 Master 節點上操做,而後同步到 Slave 節點,那麼同步就會有必定的延時,當系統很繁忙的時候,延時問題就會更加嚴重,並且會隨着從節點slave的增多而越發嚴重。