緩存一致性問題 一、什麼是一致性問題 二、使用緩存存在的問題 三、緩存一致性問題的解決方案

一、什麼是一致性問題

爲了提升服務的性能,我們一般會把熱點放進緩存,那麼這些熱點數據就同時存在於數據庫和緩存中,緩存中的數據和數據庫中的數據要保持一致,這便是緩存一致性問題。

二、使用緩存存在的問題

加了緩存之後,讀寫流程大概如下:
1. 讀流程

2. 寫流程

3. 寫操作的應該更新緩存還是刪除緩存
答案是應該刪除緩存,如果是更新,可能會有如下問題:

如上圖所示,如果線程 A 先更新了 DB,接着線程 B 更新 DB,正常情況,緩存中保存的應該是線程 B 寫入 DB 的數據,但因爲最後是線程 A 去更新的緩存,因此導致 DB 和緩存中的數據不一致。

4. 既然要用刪除,刪除操作在更新DB之前還是之後呢
答案是之前,如果是之後,可能會出現如下問題:

如果先更新 DB,在更新了 DB 之後,還沒來得及刪除緩存之前,線程 B 讀請求進來了,那麼讀取到的是緩存中的舊數據,也會出現一致性問題。

5. 先刪除再操作DB就沒問題嗎
答案是也會有問題,可能會出現如下場景:

線程 A 先刪除了緩存,還沒來得及更新 DB 的時候,線程 B 進來了,把 DB 中的舊數據又讀取到了緩存中,最後線程 A 更新了 DB,數據還是不一致。

三、緩存一致性問題的解決方案

1. 雙刪延遲策略
上面說了先刪除緩存還是會存在問題,就是線程 A 更新 DB 之前如果線程 B 把數據讀到緩存中了,數據也會不一致。雙刪延遲策略就是更新了 DB 後休眠一段時間再次刪除緩存,如下:

  • 爲什麼要休眠一段時間?
    休眠是爲了讓線程 B 讀請求能夠執行完。如果不休眠,可能會出現第二步的時候線程 B 從 DB 讀取到舊數據了,還沒來得及更新到緩存中時,線程 A 執行了第四步和第五步,然後線程 B 才執行第三步,又把剛纔讀取到的舊數據更新到緩存中了。因此,休眠的時間應該根據線程 B 執行時間而定。

  • 存在的問題
    問題很明顯,第二次刪除要休眠一段時間,用戶體驗不好,並且對業務也有入侵。

2. 使用binlog異步刪除緩存
我們知道,DB 的操作一般都會記錄到日誌中,比如 MySQL,所有的寫操作都會記錄到 binlog 中,那麼我們可以通過 binlog,去刪除緩存。canal 就是一款用來解析數據庫日誌的工具,我們可以接入 canal,採集到日誌,然後通過 MQ 異步的去刪除緩存,這樣對業務代碼就沒有入侵了。異步刪除緩存流程如下:

  • 如果是 DB 有主從庫怎麼辦?
    主從可能會出現的情況就是主庫的數據還沒來得及同步到從庫的時候,消費者已經把緩存給刪除了,然後讀請求進來,讀取到了從庫的髒數據,更新到了緩存中,還是有一致性問題。其實解決辦法很簡單,canal 採集從庫的 binlog 就行了。

  • canal 的原理
    我們知道 MySQL 主從的原理就是三個線程,一個線程負責記錄主庫的寫操作,也就是 binlog 線程;一個線程負責把主庫的 binlog 拉取到從庫;還有一個線程就負責讀取 binlog,完成從庫數據的同步。canal 就是利用這一點,僞裝成一個從庫,從而讀取到 binlog。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章