缓存一致性解决方法
對于緩存 + 數(shù)據(jù)庫讀寫,有個(gè)經(jīng)典的Cache Aside Pattern:
讀取:先讀取緩存,緩存里沒有,讀取數(shù)據(jù)庫,然后返回響應(yīng),順便保存緩存:
更新:先更新數(shù)據(jù)庫,然后刪除緩存
為什么是刪除緩存而不是更新緩存?
- 并發(fā)情況下更新緩存可能會帶來更多問題,直接刪除緩存更加穩(wěn)妥
- 緩存更新消耗更多資源,直接刪除,用時(shí)再從數(shù)據(jù)庫讀取,寫進(jìn)緩存,更省性能
先更新數(shù)據(jù)庫,然后刪除緩存
一致性問題
假設(shè)更新數(shù)據(jù)庫成功,接下來還沒來得及刪除緩存,或者刪除緩存失敗,此時(shí)其他線程進(jìn)來讀的就是臟數(shù)據(jù)。
既然刪除緩存失敗會導(dǎo)致臟數(shù)據(jù),那么就得想辦法能讓它刪除成功。一般來說有兩種方法:消息隊(duì)列重試機(jī)制和監(jiān)聽binlog異步刪除
消息隊(duì)列重試機(jī)制
如果刪除緩存失敗,向消息隊(duì)列發(fā)送消息,把刪除失敗的key放進(jìn)去,消費(fèi)消息隊(duì)列,獲取要?jiǎng)h除的key,然后重試刪除。
這樣做的話引入了消息隊(duì)列,對現(xiàn)有的業(yè)務(wù)造成了入侵,復(fù)雜度升高
監(jiān)聽binlog異步刪除
用一個(gè)服務(wù)去監(jiān)聽數(shù)據(jù)庫的binlog,獲取需要操作的數(shù)據(jù)。然后用另外一個(gè)服務(wù)獲取訂閱程序傳來的信息,進(jìn)行緩存刪除操作。這樣對于業(yè)務(wù)的入侵就小了。
先刪除緩存,再更新數(shù)據(jù)庫
在并發(fā)情況下,先刪除緩存,再更新數(shù)據(jù)庫,此時(shí)數(shù)據(jù)庫還未更新成功,這時(shí)有其他線程進(jìn)來,讀取緩存,緩存不存在,讀取數(shù)據(jù)庫,讀取的是就是舊值,此時(shí)緩存不一致就發(fā)生了。
解決方案便是延時(shí)雙刪:
就是在刪除緩存,更新數(shù)據(jù)庫之后,休眠一段時(shí)間后,再次刪除緩存。延時(shí)刪除之后,就把緩存里面緩存的舊值刪除了。
再有請求進(jìn)來,就是讀取數(shù)據(jù)庫里的新值,再把新值保存進(jìn)緩存。如果第二次刪除也失敗,那么就再次重試。
| 圖1 緩存不一致 | 圖2 延時(shí)雙刪 |
總結(jié)
- 上一篇: 地下城与勇士广东8区金币跌到了412代币
- 下一篇: 单体、分布式、微服务、Serverles