場景
我們在很多情況下會使用緩存提高查詢效率,減小數據庫壓力。但是引入緩存后,就要面對如何保證緩存與DB數據一致性的問題。在討論以下方案前,得先明白任何方案都不是百分百可靠且適用你的,要依據業(yè)務場景做出選擇。
解決方案
- 先更新/刪除緩存,再更新DB
- 先更新DB,再更新/刪除緩存
- 延遲雙刪
- 先更新DB,再使用binlog日志+消息隊列更新/刪除緩存
先更新/刪除緩存,再更新DB
如果先更新緩存,然后更新DB的動作失敗,下一個請求獲取到的依然是舊值,DB上的也是舊值,那么當緩存過期后,之前的更新操作完全失效就很奇怪了。
如果先更新緩存,再更新DB,下一個請求獲取到的可能依然是舊值。

先更新DB,再更新/刪除緩存
如果先更新DB,然后操作緩存失敗或出現并發(fā),下一個請求獲取到的依然是舊值,但是DB上是最新的,當緩存過期后,重新寫入緩存的就是最新值。
如果先更新DB,再更新緩存,下一個請求獲取到的可能依然是舊值。

延遲雙刪
延遲雙刪是指在操作緩存后,再更新DB,等待一段時間后(一般要求大于一次緩存操作時間),再操作一次緩存。
但其實在并發(fā)的時候也可能出現在二次更新緩存后,有其他線程又將他更新成舊值。
先更新DB,再使用binlog日志+消息隊列更新/刪除緩存
使用消息隊列的好處是自帶了重試機制,增加了操作緩存成功率。對于復雜的緩存操作,也實現了解耦。但是復雜度也大大提升了,也提升運維成本,并且面對高并發(fā),還會有性能問題。
刪除緩存還是更新緩存
還有個容易讓人糾結的問題是,如何操作緩存,是刪除緩存還是更新緩存?
更新緩存
更新緩存最大的好處就是簡單方便。
刪除緩存
如果你是一個寫入DB場景比較多,而讀取DB場景比較少的業(yè)務需求,采用這種方案就會導致,數據壓根還沒讀到,緩存就被頻繁的更新,浪費性能。
如果在寫入緩存前,要經過一系列復雜的計算再寫入緩存。那么,每次寫入數據庫后,都再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更為適合。
總結
綜合各方面考量,最好的方案是使用分布式鎖+延遲雙刪,在查詢的時候加上分布式鎖還有雙重校驗。現在大部分應用都實現了分布式鎖,再加上數據庫事務的使用,這已經解決了大部分的緩存一致性問題。以上討論更重要的是幫大家總結歸納各個場景,以便大家更深層的研究。