1 重啓和故障轉移後的部分重同步
Redis 4.0 開始,當一個實例在故障轉移後被提升爲 master 時,它仍然能夠與舊 master 的 slave 進行部分重同步。爲此,slave 會記住舊 master 的舊 replication ID 和複製偏移量,因此即使詢問舊的 replication ID,也可以將部分複製緩衝提供給連接的 slave 。
但是,升級的 slave 的新 replication ID 將不同,因爲它構成了數據集的不同歷史記錄。例如,master 可以返回可用,並且可以在一段時間內繼續接受寫入命令,因此在被提升的 slave 中使用相同的 replication ID 將違反一對複製標識和偏移對只能標識單一數據集的規則。
另外,slave 在關機並重新啓動後,能夠在 RDB 文件中存儲所需信息,以便與 master 進行重同步。這在升級的情況下很有用。當需要時,最好使用 SHUTDOWN 命令來執行 slave 的保存和退出操作。
2 主從數據不一致
主從網絡延時:
主多從少
部分重同步。可以通過命令 PSYNC master_run_id offset 執行。
主少從多
全量複製,覆蓋。這種情況是因爲從節點讀寫模式導致的,關閉從節點讀寫模式,或者刪除從節點數據,重新從主節點全量複製。
3 數據延遲
編寫外部程序監聽主從節點的複製偏移量,延遲較大時發出報警或通知客戶端,切換到主節點或其他節點。
設置從節點slave-serve-stale-data
爲no,除INFO和SLAVOF命令之外的任何請求都會返回一個錯誤“SYNC with master in progress”。
當副本失去與mater的連接時或仍在進行復制時,副本可以如下方式起作用:
- 若
replica-serve-stale-data
設爲“是”(默認值),則副本仍會回覆客戶端請求,可能帶有過期數據,或者,如果這是第一次同步,則數據集可能只是空的 - 若將
replica-serve-stale-data
設爲no,則該副本將對除以下信息以外的所有命令返回錯誤“SYNC with master in progress”:INFO,REPLICAOF,AUTH,PING,SHUTDOWN,REPLCONF,ROLE,CONFIG ,SUBSCRIBE,UNSUBSCRIBE,PSUBSCRIBE,PUNSUBSCRIBE,PUBLISH,PUBSUB,COMMAND,POST,HOST和LATENCY
4 髒數據
4.1 髒數據產因
4.1.1 Redis 刪除策略
是因爲讀到了過期數據。
讀到過期數據是 Redis 刪除策略導致:
惰性刪除
master 每次讀取命令時都會檢查K是否超時,若超時則執行 del 命令刪除鍵對象,之後異步把 del 命令 slave 節點,這樣可以保證數據複製的一致性,slave 永遠不會主動去刪除超時數據。
定時刪除
Redis 的 master 節點在內部定時任務,會循環採樣一定數量的鍵,當發現採樣的鍵過期時,會執行 del 命令,之後再同步個 slave 節點。
主動刪除
當前已用內存超過 maxMemory 限定時,觸發主動清理策略。主動設置的前提是設置了 maxMemory 的值 注:如果數據大量超時,master 節點採樣速度跟不上過期的速度,而且 master 節點沒有讀取過期鍵的操作,那 slave 節點是無法收到 del 命令的,這時從節點上讀取的數據已經是超時的了。
4.1.2 從節點可寫
如果從節點(默認讀模式)是讀寫模式,可能誤寫入從節點的數據,後期就會成爲髒數據。
4.2 解決方案
忽略
比如 12306 查餘票、雙十一秒殺的庫存,你會發現經常就是前後不一致的數據。因爲你查詢時得到的數據,就是需要允許寫錯誤。
選擇性強制讀主
但是真正下單扣庫存時,你就必須確保數據的正確性 選擇強制讀 master,slave間接變爲備份服務器(某個業務)。
從節點只讀
防止 slave 寫入髒數據。
Redis自身優化
Redis3.2 版本解決了 Redis 刪除策略導致的過期數據,在此版本中 slave 讀數據前,會檢查K過期時間,以決定是否返回數據。
5 數據安全性
5.1 關閉主節點持久化
爲提升Redis性能,一般會關閉主節點持久化的功能(這樣所有數據都會持久化在 slave),因爲主從同步時,master 都會 bgsave rdb。但這樣也會帶來複制的安全性問題。
在使用 Redis 複製功能時的設置中,推薦在 master 和在 slave 中啓用持久化。當不可能啓用時,例如由於非常慢的磁盤性能而導致的延遲問題,應該禁用主節點自動重啓功能。
爲什麼關閉了持久化並配置了自動重啓的 master 是危險的呢:
- 關閉 Master 的持久化設置,Replica1 和 Replica2 從 Master 複製數據。此時 Master 只有內存數據,沒有磁盤數據了。
- 當 master 宕機,由於自動重啓機制重啓了,但重啓後由於持久化被關閉了,Master數據集爲空!
- 重啓後的 Master,發現 runId 發生變化,也會重新和從節點建立連接,兩個從節點會發起復制請求,從Master 複製數據,但 Master 此時數據集爲空,因此複製的結果是它們會銷燬自身之前的數據副本而變成空數據集。
5.1.1 解決方案
- 犧牲性能,開啓 Master 的持久化功能。
- 爲了性能,依舊選擇關閉,那就讓主節點不自動重啓,比如不要有Docker或腳本等自動重啓機制。