Redis主從集群切換資料丟失的解決方案

2022-09-21 10:15:10 字數 2763 閱讀 5843

非同步複製同步丟失

集群產生腦裂資料丟失

對於redis主節點與從節點之間的資料複製,是非同步複製的,當客戶端傳送寫請求給master節點的時候,客戶端會返回ok,然後同步到各個sl**e節點中。

如果此時master還沒來得及同步給sl**e節點時發生宕機,那麼master記憶體中的資料會丟失;

要是master中開啟持久化設定資料可不可以保證不丟失呢?答案是否定的。在master 發生宕機後,sentinel集群檢測到master發生故障,重新選舉新的master,如果舊的master在故障恢復後重啟,那麼此時它需要同步新master的資料,此時新的master的資料是空的(假設這段時間中沒有資料寫入)。那麼舊master中的資料就會被重新整理掉,此時資料還是會丟失。

首先我們需要理解集群的腦裂現象,這就好比乙個人有兩個大腦,那麼到底受誰來控制呢?在分布式集群中,分布式協作框架zookeeper很好的解決了這個問題,通過控制半數以上的機器來解決。

那麼在redis中,集群腦裂產生資料丟失的現象是怎麼樣的呢?

假設我們有乙個redis集群,正常情況下client會向master傳送請求,然後同步到salve,sentinel集群監控著集群,在集**生故障時進行自動故障轉移。

此時,由於某種原因,比如網路原因,集群出現了分割槽,master與sl**e節點之間斷開了聯絡,sentinel監控到一段時間沒有聯絡認為master故障,然後重新選舉,將sl**e切換為新的master。但是master可能並沒有發生故障,只是網路產生分割槽,此時client任然在舊的master上寫資料,而新的master中沒有資料,如果不及時發現問題進行處理可能舊的master中堆積大量資料。在發現問題之後,舊的master降為sl**e同步新的master資料,那麼之前的資料被重新整理掉,大量資料丟失。

在了解了上面的兩種資料丟失場景後,我們如何保證資料可以不丟失呢?在分布式系統中,衡量乙個系統的可用性,我們一般情況下會說4個9,5個9的系統達到了高可用(99.99%,99.999%,據說**是5個9)。對於redis集群,我們不可能保證資料完全不丟失,只能做到使得盡量少的資料丟失。

在redis的配置檔案中有兩個引數我們可以設定:

min-slnlvywr**es-to-write 1

min-sl**es-max-lag 10

min-sl**es-to-write預設情況下是0,min-sl**es-max-lag預設情況下是10。

以上面配置為例,這兩個引數表示至少有1個salve的與master的同步複製延遲不能超過10s,一旦所有的sl**e複製和同步的延遲達到了10s,那麼此時master就不會接受任何請求。

我們可以減小min-sl**es-max-lag引數的值,這樣就可以避免在發生故障時大量的資料丟失,一旦發現延遲超過了該值就不會往master中寫入資料。

那麼對於client,我們可以採取降級措施,將資料暫時寫入本地快取和磁碟中,在一段時間後重新寫入master來保證資料不丟失;也可以將資料寫入kafka訊息佇列,隔一段時間去消費kafka中的資料。

通過上面兩個引數的設定我們盡可能的減少資料的丟失,具體的值還需要在特定的環境下進行測試設定。

補充:redis cluster 會丟資料嗎?

redis cluster 不保證強一致性,在一些特殊場景,客戶端即使收到了寫入確認,還是可能丟資料的。

client 寫入 master b

master b 回覆 ok

master b 同步至 sl**e b1 b2 b3

b 沒有等待 b1 b2 b3 的確認就回覆了 client,如果在 sl**e 同步完成之前,master 宕機了,其中乙個 sl**e 會被選為 master,這時之前 client 寫入的資料就丟了。

wait 命令可以增強這種場景的資料安全性。

wait 會阻塞當前 client 直到之前的寫操作被指定數量的 sl**e 同步成功。

wait 可以提高資料的安全性,但並不保證強一致性。

因為即使使用了這種同步複製方式,也存在特殊情況:乙個沒有完成同步的 sl**e 被選舉為了 master。

6個節點 a, b, c, a1, b1, c1,3個master,3個sl**e,還有乙個client,z1。

發生網路分割槽之後,形成了2個區,a, c, a1, b1, c1 和 b z1。

這時 z1 還是可以向 b 寫程式設計客棧入的,如果短時間內分割槽就恢復了,那就沒問題,整個集群繼續正常工作,但如果時間一長,b1 就會成為所在分割槽的 master,z1 寫入 b 的資料就丟了。

maximum window(最大時間視窗) 可以減少資料損失,可以控制 z1 向 b 寫入的總數:

過去一定時間後,分割槽的多數邊就會進行選舉,sl**e 成為 master,這時分割槽少數邊的 master 就會拒絕接收寫請求。

這個時間量是非常重要的,稱為節點過期時間。

乙個 master 在達到www.cppcns.com過期時間後,就被認為是故障的,進入 error 狀態,停止接收寫請求,可以被 sl**e 取代。

redis cluster程式設計客棧 不保證強一致性,存在丟失資料的場景:

在 master 寫成功,但 sl**e 同步完成之前,master 宕機了,sl**e 變為 master,資料丟失。

wnlvywrait 命令可以給為同步複製,但也無法完全保證資料不丟,而且影響效能。

分割槽後乙個 master 繼續接收寫請求,分割槽恢復後這個 master 可能會變為 sl**e,那麼之前寫入的資料就丟了。

可以設定節點過期時間,減少 master 在分割槽期間接收的寫入數量,降低資料丟失的損失。

本文標題: redis主從集群切換資料丟失的解決方案

本文位址:

redis集群主從節點自動切換

最近在將redis作為資料庫使用 redis中存放大量資料 的專案中,偶然發現redis的主從節點發生了變化,但是沒有任務報錯,redis集群的各節點也沒有fail狀態,因此記錄學習一下,redis的深層機制。首先redis是單執行緒的,所有的命令傳送的redis會進入乙個佇列,依次執行。當資料量很...

redis主從,哨兵集群

準備工作 本文用的linux為centos6.5,redis為5.0.9在兩台伺服器 redis安裝請看 redis版本 5.0.9 主 172.16.38.225 26379 sentinel 26380 主 172.16.38.226 26379 sentinel 26380 redis支援主從...

mysql主從同步切換導致資料經常丟失問題解決

mysql主庫設定了innodb flush log at trx commit 1andsync binlog 1引數保證了其一致性 切主從庫的時候,之前的從庫沒有如上的兩個引數導致現在的主從經常丟一部分資料。所以加上之後就恢復了。在使用innodb和事務的複製設定中獲得最大的永續性和一致性,需在...