目錄
1.主從複制過程
2.設定從伺服器的方式
3.多個從伺服器連接配接時
4.主從鍊
5.slaveof指令
6.主從複制與網絡延遲
6.1.注意
8.主從模式缺點
9.Sentinel哨兵
11.Sentinel哨兵模式缺點
12.Redis分布式方案
13.Redis Cluster
1.主從複制過程
從伺服器在連接配接一個主伺服器的時候,主伺服器會建立一個RDB快照檔案,并将該檔案發送至從伺服器,這是主從複制的第一步,下面列出主從複制的全部流程:
步驟 | 主伺服器操作 | 從伺服器操作 |
1 | 等待從伺服器指令 | 連接配接/重連接配接主伺服器,發送sync指令 |
2 | 接收到sync指令後,開始執行bgsave,并使用記憶體緩沖區記錄bgsave之後執行的所有寫入指令 | 根據配置選項來決定是繼續使用現有的資料來處理用戶端的指令請求,還是向發送請求的用戶端傳回錯誤? |
3 | bgsave執行完畢,向從伺服器發送RDB快照檔案,并在發送期間繼續使用記憶體緩沖區記錄被執行的寫入指令 | 丢棄所有舊資料(如果有的話),開始載入主伺服器發來的快照檔案 |
4 | 快照檔案發送完畢,開始向從伺服器發送存儲在緩沖區裡面的寫入指令 | 完成對RDB快照檔案的解釋操作,像往常一樣開始接受用戶端指令請求 |
5 | 緩沖區存儲的寫入指令發送完畢,從現在開始,每執行一個寫入指令,就向從伺服器發送相同的寫入指令 | 執行主伺服器發來的所有存儲在記憶體緩沖區的寫入指令,并從現在開始,接收并執行主伺服器傳來的每一個寫入指令 |
2.設定從伺服器的方式
配置某台伺服器作為從伺服器的方式有2種:
①在Redis.conf檔案中通過slaveof host port将其設定為從伺服器,然後該伺服器啟動時會先去載入目前任何可用的RDB檔案或者AOF檔案,然後再去連接配接主伺服器并執行主從複制過程;
②向正在運作的伺服器發送slaveof指令,動态将其變為從伺服器,然後該伺服器會立即嘗試連接配接主伺服器,并在連接配接成功之後,開始上面提到的主從複制過程;
注意:從伺服器在與主伺服器進行初始連接配接時,從伺服器中的原有的所有資料都将丢失,并被替換成主伺服器發來的資料;
3.多個從伺服器連接配接時
當多個從伺服器嘗試連接配接同一個主伺服器時,會出現下面2種情況中的一種:
步驟 | 主伺服器操作 | 從伺服器操作 |
1 | 等待從伺服器指令 | 連接配接/重連接配接主伺服器,發送sync指令 |
2 | 接收到sync指令後,開始執行bgsave,并使用記憶體緩沖區記錄bgsave之後執行的所有寫入指令 | 根據配置選項來決定是繼續使用現有的資料(如果有的話)來處理用戶端的指令請求,還是向發送請求的用戶端傳回錯誤? |
情況1:當步驟3尚未執行時,所有從伺服器都會接收到相同的快照檔案和相同的緩沖區寫入指令 | ||
3 | bgsave執行完畢,向從伺服器發送RDB快照檔案,并在發送期間繼續使用記憶體緩沖區記錄被執行的寫入指令 | 丢棄所有舊資料(如果有的話),開始載入主伺服器發來的快照檔案 |
情況2:當步驟3正在執行或者已經執行完畢後,當主伺服器與較早進行連接配接的從伺服器執行完複制所需的5個步驟之後,主伺服器會與新連接配接的從伺服器執行一次新的步驟1-5 | ||
4 | 快照檔案發送完畢,開始向從伺服器發送存儲在緩沖區裡面的寫入指令 | 完成對RDB快照檔案的解釋操作,像往常一樣開始接受用戶端指令請求 |
5 | 緩沖區存儲的寫入指令發送完畢,從現在開始,每執行一個寫入指令,就向從伺服器發送相同的寫入指令 | 執行主伺服器發來的所有存儲在記憶體緩沖區的寫入指令,并從現在開始,接收并執行主伺服器傳來的每一個寫入指令 |
4.主從鍊
當建立多個從伺服器時可能會造成網絡不可用,那是因為RDB檔案是通過網際網路傳遞,從伺服器也可以擁有自己的從伺服器,進而形成主從鍊,一環扣一環,形成長長的鎖鍊;
從從複制與主從複制的唯一差別在于:如果從伺服器X擁有從伺服器Y,那麼當從伺服器X在執行步驟4時,伺服器X會主動斷開與從伺服器Y的連接配接,進而導緻從服務區Y需要重新連接配接并重新同步resync;
5.slaveof指令
slaveof host port
通過執行SLAVEOF指令,可以将目前伺服器轉變為指定伺服器host的從屬伺服器;如果目前伺服器已經從伺服器,那麼執行SLAVEOF host port将使目前伺服器停止對舊主伺服器的同步,丢棄舊資料集,轉而開始對新主伺服器進行同步;
host指的是主伺服器的IP位址,port指的是主伺服器Redis資料庫端口号;
slaveof no one
将使得這個從伺服器關閉複制功能,并從從伺服器轉變回主伺服器,原來同步所得的資料集不會被丢棄;利用這個特性,可以在主伺服器失敗的時候,将從伺服器用作新的主伺服器,進而實作無間斷運作;
注意:從節點隻能讀get,不能寫set,隻能從主節點同步資料;
6.主從複制與網絡延遲
主從複制需要經過網絡來傳輸,既然是通過網絡來傳輸,可以可以配置傳輸方式,是有一條發一條,還是先積攢N條之後再一次性發過去呢,這裡就需要參數repl-disable-tcp-nodelay,該參數取值範圍如下:
①yes:redis先合并小的TCP包進而節省帶寬,但會增加同步延遲(40ms發一次),進而造成master與slave資料不一緻,這種方式關注帶寬性能;
②no:主伺服器會立即發送同步資料,沒有延遲,但會造成網絡帶寬卡頓,這種方式關注資料一緻性;
有興趣的話,可以自己私下查查TCP_NODELAY協定;
6.1.注意
在Redis 2.8.18版本之前,主伺服器先通過bgsave在磁盤上生成RDB檔案,然後再把RDB檔案通過網絡傳輸到從伺服器,從伺服器先把檔案生成到磁盤上,然後清理掉資料,然後再從磁盤加載RDB檔案;
從Redis 2.8.18開始,Redis支援無盤複制,即主伺服器直接通過網絡套接字把RDB内容發送到從伺服器上,主伺服器一邊周遊記憶體,一邊将序列化的内容發送到從節點,而從節點還是跟之前一樣,先把接收到的内容存儲到磁盤中,然後再進行一次性加載;
- info指令中與主從複制有關的資訊
Replication子產品
指令 | 備注 |
role | 目前執行個體的角色master還是slave |
connected_slaves | slave的數量 |
master_replid | 主執行個體啟動随機字元串 |
master_replid2 | 主執行個體啟動随機字元串2 |
slave:ip,port,state,offset,lag | slave機器的資訊、狀态 |
master_repl_offset | 主從同步偏移量,此值如果和上面的offset相同說明主從一緻沒延遲,與master_replid可被用來辨別主執行個體複制流中的位置 |
second_repl_offset | 主從同步偏移量2,此值如果和上面的offset相同說明主從一緻沒延遲 |
repl_backlog_active | 複制緩沖區是否開啟 |
repl_backlog_size | 複制緩沖區大小 |
repl_backlog_first_byte_offset | 複制緩沖區裡偏移量的大小 |
repl_backlog_histlen | 此值等于 master_repl_offset - repl_backlog_first_byte_offset,該值不會超過repl_backlog_size的大小 |
8.主從模式缺點
主伺服器無法提供服務後,不能自動切換,需要手工切換,為了避開這種手工切換,需要Redis的哨兵模式;
9.Sentinel哨兵
從Redis2.8版本開始提供了哨兵功能,下面說一下Sentinel工作流程:
①每個Sentinel以每秒鐘一次的頻率向它所知的Master、Slave、其他Sentinel執行個體發送一個PING指令;
②如果一個執行個體(instance)距離最後一次有效回複PING指令的時間超過down-after-milliseconds選項所指定的值, 則這個執行個體會被Sentinel标記為主觀下線;
③如果一個Master被标記為主觀下線,則正在監視這個Master的所有Sentinel要以每秒一次的頻率确認Master的确進入了主觀下線狀态;
④當有足夠數量的Sentinel(大于等于配置檔案指定的值)在指定的時間範圍内确認Master的确進入了主觀下線狀态, 則Master會被标記為客觀下線;
在Sentinel叢集通過Raft算法選擇一個Sentinel來作為Leader,然後由Leader完成故障轉移流程。
⑤在一般情況下,每個Sentinel會以每10秒一次的頻率向它已知的所有Master、Slave發送INFO指令;
⑥當Master被Sentinel标記為客觀下線時,Sentinel向下線的Master的所有Slave發送INFO指令的頻率會從10秒一次改為每秒一次;
Sentinel Leader向某個節點發送slaveof no one指令,讓它成為獨立節點,然後向其他節點發送slaveof host port(本機服務),讓它們成為這個節點的子節點,故障轉移完成。
⑦若沒有足夠數量的Sentinel同意Master已經下線,Master的客觀下線狀态就會被移除,若Master重新向Sentinel的PING指令傳回有效回複, Master的主觀下線狀态就會被移除;
官網:https://redis.io/topics/sentinel
- sentinel.conf配置檔案說明
參數名 | 參數說明 |
port | 哨兵sentinel執行個體運作的端口,預設26379 |
dir | 哨兵sentinel的工作目錄 |
sentinel monitor <master-name> <ip> <redis-port> <quorum> | ①哨兵sentinel監控的redis主節點的ip、port; ②master-name可以自己命名的主節點名字,隻能由字母A-z、數字0-9、這三個字元".-_"組成; ③quorum配置多少個sentinel哨兵統一認為master主節點失聯,那麼這時客觀上認為主節點失聯了; |
sentinel auth-pass <master-name> <password> | ①當在Redis執行個體中開啟了requirepass foobared 授權密碼 ,這樣所有連接配接Redis執行個體的用戶端都要提供密碼; ②設定哨兵sentinel連接配接主從的密碼,注意必須為主從設定一樣的驗證密碼; |
sentinel down-after-milliseconds <master-name> <milliseconds> | 指定多少毫秒之後,主節點沒有應答哨兵sentinel,此時哨兵主觀上認為主節點下線,預設30秒 |
sentinel parallel-syncs <master-name> <numslaves> | 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味着越 多的slave因為replication而不可用。可以通過将這個值設為1來保證每次隻有一個slave 處于不能處理指令請求的狀态。 |
sentinel failover-timeout <master-name> <milliseconds> | 故障轉移的逾時時間 failover-timeout 可以用在以下這些方面: 1. 同一個sentinel對同一個master兩次failover之間的間隔時間。 2. 當一個slave從一個錯誤的master那裡同步資料開始計算時間。直到slave被糾正為向正确的master那裡同步資料時。 3.當想要取消一個正在進行的failover所需要的時間。 4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個逾時,slaves依然會被正确配置為指向master,但是就不按parallel-syncs所配置的規則來了 預設三分鐘 |
sentinel notification-script <master-name> <script-path> | 配置當某一事件發生時所需要執行的腳本,可以通過腳本來通知管理者,例如當系統運作不正常時發郵件通知相關人員。對于腳本的運作結果有以下規則: 1.若腳本執行後傳回1,那麼該腳本稍後将會被再次執行,重複次數目前預設為10 2.若腳本執行後傳回2,或者比2更高的一個傳回值,腳本将不會重複執行。 3.如果腳本在執行過程中由于收到系統中斷信号被終止了,則同傳回值為1時的行為相同。 4.一個腳本的最大執行時間為60s,如果超過這個時間,腳本将會被一個SIGKILL信号終止,之後重新執行 |
sentinel client-reconfig-script <master-name> <script-path> | 用戶端重新配置主節點參數腳本 當一個master由于failover而發生改變時,這個腳本将會被調用,通知相關的用戶端關于master位址已經發生改變的資訊。以下參數将會在調用腳本時傳給腳本: <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port> 目前<state>總是“failover”, <role>是“leader”或者“observer”中的一個。 參數 from-ip, from-port, to-ip, to-port是用來和舊的master和新的master(即舊的slave)通信的 這個腳本應該是通用的,能被多次調用,不是針對性的。 |
11.Sentinel哨兵模式缺點
主從切換的過程中會丢失資料,因為隻有一個master,隻能對這一個master進行get與set,沒有解決水準擴容的問題。
如果資料量非常大,需要多個master-slave的group,把資料分布到不同的group中,那麼,針對這些group,資料該如何均勻落到這些不同的group中?
12.Redis分布式方案
方式名稱 | 說明 |
在用戶端實作相關的邏輯 | Jedis用戶端提供了RedisSharding的方案,并且支援連接配接池。使用ShardedJedis之類的用戶端分片代碼的優勢是配置簡單,不依賴于其他中間件,分區的邏輯可以自定義,比較靈活。 但是基于用戶端的方案,不能實作動态的服務增減,每個用戶端需要自行維護分片政策,存在重複代碼。 |
把做分片處理的邏輯抽取出來,運作一個獨立的代理服務,用戶端連接配接到這個代理服務,代理服務做請求的轉發 | 典型的代理分區方案有Twitter開源的Twemproxy和國内的豌豆莢開源的Codis |
基于服務端實作 | Redis Cluster |
13.Redis Cluster
Redis Cluster是在Redis3.0的版本正式推出的,用來解決分布式的需求,同時也可以實作高可用。跟Codis不一樣,它是去中心化的,用戶端可以連接配接到任意一個可用節點;