09.redis 哨兵主備切換時資料丟失的解決方案

MrMirror發表於2020-09-03

一、兩種資料丟失的情況


1. 非同步複製導致的資料丟失

  因為master->slave的複製是非同步的,所以可能有部分資料還沒複製到slave,master就當機了,此時這些部分資料就丟失了

2. 腦裂導致的資料丟失

腦裂是什麼
  某個master所在機器突然脫離了正常的網路,跟其他slave機器不能連線,但是實際上master還執行著。此時哨兵可能就會認為master當機了,然後開啟選舉將其他slave切換成了master。叢集裡就會有兩個master,也就是所謂的腦裂

引發的問題
  此時雖然某個slave被切換成了master,但是可能client還沒來得及切換到新的master,還繼續寫向舊master的資料可能也丟失了。因此舊master再次恢復的時候,會被作為一個slave掛到新的master上去,自己的資料會清空,重新從新的master複製資料


二、解決方案


1. redis層面:通過配置控制同步時間

redis.conf配置如下:

min-slaves-to-write 1
min-slaves-max-lag 10

含義:

要求至少有1個slave,資料複製和同步延遲不能超過10秒
如果說一旦所有的slave,資料複製和同步的延遲都超過了10秒鐘,那麼master就會拒絕接收任何請求

作用

  • 減少非同步複製的資料丟失

配置min-slaves-max-lag為10s後,根據目前master->slave的複製速度,如果資料同步完成所需要時間超過10s,就會認為master未來當機後損失的資料會很多,master就拒絕寫入新請求。
這樣就能將master和slave資料差控制在10s內,即使master當機也只是這未複製的10s資料。

  • 減少腦裂的資料丟失

如果不能繼續給指定數量的slave傳送資料,而且slave超過10秒沒有給自己ack訊息,那麼就直接拒絕寫入新請求。這樣腦裂後的舊master就不會接受client的新資料,也就避免了資料丟失。
因此在腦裂場景下,最多就丟失10秒的資料

2. 生產者層面:做降級限流

降級
  先講訊息寫到本地磁碟中或者放到臨時訊息佇列中,每隔10分鐘去本地磁碟或者佇列裡取來嘗試重新發給master
限流
  在閘道器減慢請求湧入的速度。

相關文章