一、兩種數據丟失的情況
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
限流:
在網關減慢請求涌入的速度。