標籤:
[不忘初心]
前文,我們簡要翻譯了Redis叢集的內容,在搭建叢集的過程中,我們經常使用的功能就是主從複製,冗餘備份。本文我們就來介紹這部分的內容。好了,馬上開始我們的本文部分吧。
---------------------------------------------------------------------------------------------------------------------------------------
Redis的複製功能是非常簡單易用的,配置為主從複製功能之後允許Redis的slave伺服器複製出與master完全一致的伺服器。以下是一些關於Redis複製功能的幾個重要方面:
- Redis使用非同步複製。從2.8版本開始 ,slave伺服器將以1s的頻率想master伺服器報告複製流的處理進度。
- 一個master伺服器可以擁有多個slaves伺服器。
- slave伺服器也能連結到其他slave伺服器。除了連結到master伺服器之外,slave伺服器也能夠和多個slave一起構成圖狀結構。
- Redis的複製功能不會阻塞master伺服器。話句話說,master伺服器能夠在向一個或者多個slave進行初始化複製時也能夠持續的接受服務要求。
- 複製功能也不會阻塞slave伺服器。當slave在進行初始化複製時,slave也能夠處理老版本的資料服務,前提是你在Redis.conf檔案中進行了相應的配置。另外,你也可以配置slave在與master斷開時,讓其返回錯誤。然而,在非同步初始化之後,舊資料必須被刪除,並且新資料必須被載入到slave中。此時,slave將會被阻塞直到複製完成。
- 複製功能也可以被用於提升擴充性,使得,多個slave提供唯讀服務(如,繁重的SORT命令操作可以交給複述節點進行)。或者將複製功能單純的用於資料冗餘(datar redundancy)。
- 使用複製功能來使得master節點避免執行持久化操作。只需要關閉主伺服器的持久化功能,然後由從伺服器去執行持久化操作即可。特別的:在這種配置之下,請確保master伺服器不會自動重啟。
在master節點關閉持久化功能時,複製的安全性 當在設定中開啟Redis複製功能時,強烈建議的做法的在master節點中開啟持久化功能,或者絕對不可能的,因為延遲問題,將Redis執行個體被配置為避免自動重啟。為了更好的理解為什麼將關閉持久化功能的master節點配置為自動重啟是非常危險的,我們看看下面的在資料從master節點與其對應的所有slave節點移除時發生的失敗類型有哪些:
- 假設A節點是master節點,B,C節點是其對應的副本。
- A發生崩潰時,(配置為自動重啟),重新啟動了進程。然而因為持久化功能是關閉的,所以重啟之後,該節點內的資料為空白。
- 節點B,C將會從A進行複製,這時A中的資料集是空的,因此,這時,B,C將會徹底刪除他們之前備份的資料。
為了高可用性,引入了Redis的哨兵(sentinel),並且關閉了master節點上的持久化,並且兩者都配置為自動重啟,這種做法也是非常危險的。舉個例子:master節點可能非常快的就完成了重啟,以至於sentienl都沒有感知到失敗的發生,接下來就會發生和上面例子一樣的結果。在任何時間,資料的安全都是非常重要的,因此,在使用複製功能時,master節點如果沒有持久化功能,自動重啟的功能是必須被禁止的。複製功能的運行原理當你建立一個slave節點時,slave節點都會將master節點發送一個SYNC命令。無論是首次連結還是重新串連。當maste節點接受到SYNC命令時,master節點將會開始後台儲存功能,並且開始緩衝所有接收到的將會修改資料集的新命令。當後台儲存任務完成時,master節點將資料檔案傳送給slave節點,slave節點將會把資料檔案儲存到本地磁碟,並且載入到記憶體中。緊接著,master節點將會把之前還存下的所有命令也傳輸給slave節點。這項功能將會按照指令流來完成並且是一個與Redis協議本身相同的格式。你可以通過telnet命令來親自驗證這個同步過程。首先,串連上一個正在處理命令請求的Redis伺服器,然後發送SYNC命令,之後,你將看到大量的資料轉移以及master節點上接收到的每一條命令將會被再次運行在telnet的會話中。當master節點與slave節點斷開時,slave節點能夠自動的重寫連結到master節點上。如果master節點接收到多個同時進行複製請求時,master節點也只需要執行一次SYNC命令,就可以處理到所有的slave伺服器的同步請求。當master節點與slave節點斷線重連之後,一個完整的SYNC命令將會被執行。然後在2.8版本之後,slave節點將會根據主伺服器的情況來選擇是完整同步還是部分同步。部分重新同步 從2.8版本開始,master節點和slave節點通常情況下能夠在斷線重連的情況下進行斷點續傳的複製功能,而不需要進行完整複製過程。這個特性需要master伺服器在記憶體中建立一個複製流緩衝區。並且,master和slave需要都記錄下一個複製位移量和一個master節點ID,當網路連接斷開時,slave節點將會重新串連,並且向master伺服器請求繼續執行原來的複製進程。如果master節點ID與slave節點記錄的ID保持一致,並且slave記錄的複製位移量指定的資料在master節點中仍然存在,那麼複製流將會從斷點繼續傳輸。 如果上麵條件哪怕只有一條不滿足的話,那就開始一個完整的複製過程。 Redis2.8版本的部分重新同步的特性會用到一個新增的PSYNC命令,而之前的版本只有SYNC命令。不過,只要伺服器版本高於2.8,其將會自動的選擇使用PSYNC還是SYNC。無磁碟複製通常情況下,一個完成的再同步複製請求需要建立一個RDB檔案,並且把這個RDB檔案從磁碟中載入到slave節點中。如果是在一個非常慢的磁碟上進行,這對於master節點是一個壓力非常大的操作。從2.8.18版本開始,實驗性的支援了無磁碟的複製。在該配置下,子進程能夠直接通過網路連接發送RDB給slave,而不磁碟作為中間儲存。配置配置一個slave伺服器是非常簡單,只需要在設定檔中增加一下的這一張就行:
slaveof 127.0.0.1 6379
當然,你需要將代碼中的IP與連接埠,替換成你自己的master伺服器的IP與連接埠。另外的一種方法就是:使用SLAVEOF命令,輸入master伺服器的IP和連接埠,然後,master節點就會開始同步。
127.0.0.1:6379> SLAVEOF 127.0.0.1 6379OK
這裡也有一些專門為master節點執行部分重新同步的過程中調整記憶體中的複製儲存的參數。無磁碟複製功能可以使用repl-diskless-sync參數開啟。為了在第一個slave節點到達之後等待更多slave節點到達,延遲傳輸動作,可以被repl-diskless-sync-delay參數控制。更多內容請在redis.conf檔案的分布式配置中查看。唯讀slave伺服器 從2.6版本開始,slave節點唯讀模式,並且也是預設的。這個模式也是可以被redis.conf檔案中的slave-read-only控制的,也可以通過CONFIG SET命令來設定。 唯讀模式下的slave節點將會拒絕一切寫命令,因此,也不會出現因為錯誤操作在slave中寫入資料的可能。但是,這不是說,我們可以將一個slave節點暴露給互連網或者不信任的網路用戶端,因為,管理類的命令如DEBUG,CONFIG命令仍然是可以使用的。但是,我們可以禁用redis.conf檔案中的rename-command命令,來提升唯讀slave節點的安全性。 你可能會好奇,為什麼可能出現重新覆蓋唯讀配置和slave節點會成為寫操作的目標。儘管這些寫操作在slave節點與master節點再同步或者slave重新啟動時將會被丟棄,但是,在可寫的slave節點中,這裡仍有對所儲存的一些臨時資料進行合法的使用。然而,在將來,這可能將會被移除。slave節點的授權配置如果master節點通過requirepass設定了訪問密碼,在配置slave節點中也需要配置相應的password,這樣才能進行所有的同步操作。對於一個正在啟動並執行slave可以使用下面的命令:
config set masterauth <password>
要永久的設定這個密碼,那麼可以將它加入到設定檔中:
masterauth <password>
master伺服器只有在只要N個slave伺服器的條件下,才執行寫操作 從 Redis 2.8 開始, 為了保證資料的安全性, 可以通過配置, 讓主伺服器只在有至少 N 個當前已串連從伺服器的情況下, 才執行寫命令。
不過, 因為 Redis 使用非同步複製, 所以主伺服器發送的寫資料並不一定會被從伺服器接收到, 因此, 資料丟失的可能性仍然是存在的。
以下是這個特性的運作原理:
- slave伺服器每秒ping一次master伺服器,並且報告複製流的處理情況。
- master伺服器將會記錄各個slave伺服器最後一次發送ping的時間。
- 使用者可以配置網路延遲的最大時間min-slaves-max-lag(M),以及執行寫操作所需的最少slave伺服器數量min-slaves-to-write(N).
如果至少存在N個slave伺服器,並且延遲都小於M秒,那麼寫操作將被接受。 你可以將這個特性看作是CAP理論中的C的寬鬆條件,儘管不能保證寫操作的持久性,但起碼遺失資料的視窗會被嚴格限制在指定的描述中。如果這些條件沒有被滿足,master節點將會返回一個錯誤,並且寫操作將會被拒絕。以下是這個特性的兩個選項和所需參數:
- min-slaves-to-write <number of slaves>
- min-slaves-max-lag <number of seconds>
詳細的資訊可以參考Redis源碼中附帶的redis.conf樣本檔案對帶有超期時間key的複製策略 Redis的逾時配置允許key擁有生效的有限時間。該特性以來於Redis執行個體能夠計算有效時間,然而,Redis的slave節點準確的複製這些帶有逾時時間的key,即使當這些key被lua指令碼改變了。 為了實現這樣的特性,REdis不能依靠master與slave之間同步時間的能力,因為,這個同步問題是無法解決的,並且將會導致競爭條件的產生和資料集的不一致問題,因此,Redis使用了下面三種策略實現讓帶有到期時間的key能夠被使用:
- slave不會將key到期,而是等待master節點將其到期。當master節點將一個key的時間到期之後,使用DEL命令,通知所有slave節點刪除該key。
- 然而,由於是master驅動到期時間的, 所以在某些時刻,slave仍然有可能保留了一些實際上已經到期的key,原因是master節點沒有及時的提供DEL命令。為了處理slave節點使用其正確的時間來報告一個不存在的key,只向一些不違反資料一致性的讀操作提供,(因為來自master節點的新命令將會到達)。通過這種方式,slave節點避免了返回一個實際上已經到期的,但未刪除的key。
- 在Lua指令碼執行中,將不會執行key的逾時設定。在Lua指令碼執行過程中,概念上說master上的時間是停止的,因此,在一個給定的指令碼執行期的完整時間內一個給定的key將會只能是存在或者不存在。這阻止了key在執行指令碼過程中發生逾時現象,並且在為了發送相同的指令碼到slave中也是十分必要的,其保證了對資料集產生相同的影響。
正如預期的那樣,一旦發生容錯移轉,slave變為master,其將開始獨立的判斷key的到期時間,而不是向之前的master詢問。-------------------------------------------------------------------------------------------------------------------------------------至此,NoSQL之Redis---主從複製
參考資料:
官方文檔:http://redis.io/topics/replication
其他資料:http://doc.redisfans.com/topic/cluster-tutorial.html
NoSQL之Redis---主從複製