Redis 缓存常见问题:缓存一致性的解决方案
文章目錄
- 先刪除緩存,再更新數據庫
- 延時雙刪
- 先更新數據庫,再刪除緩存
- 修改緩存過期時間
- 消息隊列
Redis 緩存常見問題 :緩存雪崩,緩存擊穿,緩存穿透,緩存預熱
在之前的博客中,我介紹了Redis緩存的一些常見問題,如:緩存雪崩、緩存擊穿、緩存穿透等。這次就來介紹一下Redis的緩存一致性的問題。
對于緩存和數據庫的更新操作,主要分為以下兩種
- 先刪除緩存,再更新數據庫
- 先更新數據庫,再刪除緩存
首先可能會帶來疑惑的點是,為什么這里是刪除緩存而不是更新緩存?
按照常理來說,更新的效率通常都會比刪除高,因為我們在刪除了緩存后當有讀操作到來時,當其查詢緩存不存在時,就會去查詢數據庫,并將讀取到的值寫入到緩存中,這樣的效率明顯比更新低。
但是我們還需要考慮一個問題,即緩存的使用率問題。如果在短時間內對數據庫進行了10000次更新操作,那么緩存也必定會進行10000次的更新操作,那這個緩存它真的有用到那么多次嗎?如果它僅僅是一個冷門數據,可能在這期間內只進行了僅僅幾次的查詢操作,那我們的這些更新操作不是會顯得很多余嗎?
所以,我們才會去使用刪除。因為在我們刪除緩存后,只有在其真正使用到這個數據的時候,才會將其寫入緩存,因此我們就不用每次都對緩存進行更新操作,從而保證效率。
先刪除緩存,再更新數據庫
對于這種情況,能夠保證緩存的一致性嗎?
答案肯定是否定的,例如下面這種情景
對于上述這種情況,線程B在線程A更新數據庫之前就提前讀取了數據庫,從而讀取到了舊值,而后線程B將讀取到的舊值再次寫入緩存中,就出現了緩存不一致的情況。
那么這個問題如何解決呢?
這時候就需要引入延時雙刪的機制
延時雙刪
為了避免在更新數據庫的時候,其他的線程讀取到了數據庫中的舊值并將其寫入緩存這種情況,我們會在數據庫更新完后等待一段時間,再次刪除緩存,來保證下一個到來的線程能夠將正確的緩存更新回去。
流程如下
那么,為了保證我們能夠將錯誤的緩存刪除,所以我們的sleep時間只需要大于線程讀寫緩存的時間即可
先更新數據庫,再刪除緩存
那么如果我們先更新數據庫,再更新緩存呢?
對于這種操作,緩存不一致的情況就更加明顯了。由于磁盤I/O速度慢,在更新數據庫、刪除緩存這段操作之前,其他線程讀取到的都是原本緩存中的舊值。甚至可能會由于緩存刪除失敗(如緩存服務當前不可用的情況)從而導致嚴重的緩存不一致問題。
那么如何解決這個問題呢?可以使用以下幾種方法
修改緩存過期時間
這是解決這個問題最簡單的方法,同時也是治標不治本的方法。
我們可以將緩存過期時間變短,使其每隔一段時間就會去數據庫中加載數據,對于更新不頻繁的數據來說,就可以很好的解決不一致的問題,但若是更新特別頻繁的熱點數據,這個方法則失去了作用。
由于這個方法的適用面小,且實時性和一致性不高,所以我們通常都會選擇使用消息隊列來解決這個問題。
消息隊列
我們可以引入一個消息隊列來解決這個問題,在更新數據庫后,我們往消息隊列中寫入數據,等到消費者從消息隊列中取出數據時,再將緩存刪除。借助消息隊列的消息重試機制來保證我們一定能夠成功刪除緩存,從而確保緩存的一致性。
但是這種方法也存在幾個問題
所以我們只有在對實時性和一致性要求不高的情況下才會選擇這種做法
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的Redis 缓存常见问题:缓存一致性的解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 内存管理 | 地址映射:分段
- 下一篇: 分布式系统概念 | 分布式理论:CAP、