引言
在引入緩存系統的項目中,我們需要舊數據進行更新操作時,我們是先淘汰緩存,再更新數據庫。還是先更新數據庫,再淘汰緩存。亦或是更新數據庫,再更新緩存呢?下面,將會講講小編對這三種方案的優缺點的一些想法。
目的
- 整理自己對這方面的知識;
- 分享自己的看法,和小伙伴們一起學習;
- 用初學者的角度來淺顯的講解這方面的內容。
緩存更新策略
- 先更新數據庫,再更新緩存;
- 先更新數據庫,再刪除緩存;
- 先刪除緩存,再更新數據庫;
先更新數據庫,再更新緩存
這套方案,小編認為大多數場景不合適。為什么呢?主要從以下幾個原因講解:
一、資源浪費
在一些大型的信息網站中(博客、貼吧),我們引入緩存主要是對熱數據(請求頻繁的)進行緩存,而這時候,如果很多用戶對於冷數據(長時間沒人訪問,或者訪問量很少)進行更新,然后再去更新緩存,這就造成了緩存資源的大量浪費(因為訪問量少,導致這些緩存命中低,浪費緩存資源)。
二、臟數據
這是由於出現了並發操作的原因導致的,如:同時有兩個請求A和B對數據進行了更新操作,由於網絡原因,可能存在以下情況:
- 請求A更新了數據庫;
- 請求B更新了數據庫;
- 請求B更新了緩存;
- 請求A更新了緩存。
這就出現了A數據覆蓋了B數據的情況,此時就產生了臟數據,如果沒有緩存定時過期機制,此時的臟數據需要等待下一次的更新,才會對緩存進行更新,雖然用戶看到數據出現問題,會再重新更新一次,但這已經有多了一次不必要的請求了,寫請求量大的時候,容易造成眾多不必要的更新請求。
三、請求時間
如果緩存不是一種簡單的數據緩存,而是需要經過較為復雜的運算,才能得出緩存值,這時候,請求將會在計算緩存值上,耗費一部分時間,而這就導致了請求的響應時間變長,增加系統的負擔,降低了系統的處理能力。
四、頻繁寫入
在寫請求很多,而讀請求很少的場景下,緩存沒起到多大的作用,就給頻繁更新了,造成了資源浪費,如:
- 對數據A進行了一次修改,生成了緩存A;
- 此時沒有讀取數據A的請求;
- 對數據A進行了一次修改,更新了緩存A;
- 此時沒有讀取數據A的請求;
- 對數據A進行了一次修改;
- 此時有了讀取數據A的請求。
這時就會造成緩存的不必要更新操作(沒有人讀取緩存),用戶量大的時候,會造成大量的不必要操作,造成系統資源的浪費。
適合場景
當然,這種也不是說就不能使用這些,既然存在,就有其存在的道理。一下的場景就適合:
- 讀請求占據網站的總流量的99%;
- 網站數據量不大(幾十萬的文章數據);
- 很少會去更新數據(一般文章寫好后,不會去更新)。
案例
- 個人博客
- 手冊網站(w3cschool、菜鳥教程等)
先更新數據庫,再刪除緩存
這種策略比較多平台使用,如:Facebook。但是這種策略也存在一些問題,如:
一、臟數據
造成臟數據的原因主要由並發引起,如:
- 用戶A請求數據A
- 數據A緩存失效
- 用戶A從數據庫中得到舊數據數據A
- 用戶B更新了數據A(新數據)
- 用戶B刪除了緩存
- 用戶A將查到舊數據寫入了緩存
此時就產生了臟數據,雖然這種概率非常小,但對於更新不頻繁的網站來說,此時的臟數據就是個很嚴重的錯誤。
二、緩存刪除失敗
- 用戶A更新了數據A
- 用戶A刪除數據A的緩存失敗
- 用戶B讀到數據A緩存的舊數據
此時就產生了數據不一致的問題。
解決方案
1、設置緩存的有效時間(最簡單的方案)
優點:
- 簡單
- 易操作
缺點:
- 會存在短時間內的舊數據
- 如果數據量太多,緩存有效時間短,容易發生一段時間內緩存大量失效,此時的數據庫壓力突然劇增,引發緩存雪崩現象(緩存有效時間為隨機值減少發生緩存雪崩的可能性)
2、消息隊列(比較復雜,需要引入消息隊列系統)
步驟:
- 更新數據庫;
- 刪除緩存失敗;
- 將需要刪除的Key發送到消息隊列;
- 隔斷時間從消息隊列中拉取要刪除的key;
- 繼續刪除,直至成功為止。
優點:
- 不會引發緩存雪崩
- 只刪除需要刪除的緩存
缺點:
- 引入了消息系統(增加了系統的復雜性)
先刪除緩存,再更新數據庫
這種方法也是比較多人使用的,但是也會出現臟數據的問題:
原因
- 用戶A刪除緩存失敗
- 用戶A成功更新了數據
或者
- 用戶A刪除了緩存;
- 用戶B讀取緩存,緩存不存在;
- 用戶B從數據庫拿到舊數據;
- 用戶B更新了緩存;
- 用戶A更新了數據。
以上兩種情況都能造成臟數據的產生。
解決方案
1、設置緩存的有效時間(最簡單的方案)
優點:
- 簡單
- 易操作
缺點:
- 會存在短時間內的舊數據
- 如果數據量太多,緩存有效時間短,容易發生一段時間內緩存大量失效,此時的數據庫壓力突然劇增,引發緩存雪崩現象(緩存有效時間為隨機值減少發生緩存雪崩的可能性)
2、消息隊列
- 先淘汰緩存;
- 更新數據庫;
- 將需要淘汰的緩存Key發送到消息隊列;
- 另起一程序拉取消息隊列的數據;
- 對需要刪除的key進行刪除,直至刪除為止。
優點:
- 保證了緩存的刪除
- 不會增加更新的處理時間
- 不會引發緩存雪崩
缺點:
- 會增加一次緩存miss(可以忽略不計)
- 引入了消息系統(增加了系統的復雜性)
總結
- 上述的方法根據自己的系統業務來選擇;
- 既然存在,就有其道理;
- 使用緩存有效時間時,需要注意緩存雪崩問題;
- 可以引入消息系統來避免臟數據;
- 還存在分析binlog來異步刪除緩存(小編未研究這個,所以小編沒寫);