關於redis數據一致性的思考

image

衆所周知的玩笑,計算機科學中只有兩個難題:緩存失效和命名。redis

緩存失效,我理解爲是如何保證緩存一致性。數據庫

首先說明,全部的方案都是存在問題的,都不能保證100%的一致性,若是嚴格要求一致性,那麼,把緩存幹掉吧....緩存

那麼到底要不要用緩存?用緩存的目的是什麼?你的業務能接受什麼樣的數據一致性?使用以前至少須要把這些問題搞清楚。
若是沒搞清楚需求,就上緩存,只能說明上緩存只是爲了PPT好看而且能多賣一些RMB而已吧。異步

我我的的理解是,一個技術不該該爲了用而用,而是服務於業務的。
假如從新設計一個系統,若是不是已經有個很成熟的系統作樣板,我會先所有用DB,而後哪裏有問題再改進哪裏,不會一上來就決定用某一箇中間件。
只用數據庫的好處在於實現事務很簡單,能保證操做的原子性,而且技術很完善。性能

若是用了緩存,數據不一致的狀況會很是多,事務處理的複雜程度遠超咱們的想象。只能根據本身的業務,選擇一種業務上能夠容忍的一致性的方案。
其實每每簡單的模型才最可靠,若是沒有必要,儘可能不用緩存,省得出現各類問題,浪費了時間還得不到想要的效果。spa

同步緩存的策略分好多好多種,什麼實時緩存、異步緩存、定時緩存、消息隊列緩存,真要是詳細提及來,估計能說一本書,主要是我也不會...
這裏就說幾種簡單、好實現、數據一致性也還算說的過去的方式吧。設計

1、不主動刪除redis,等它本身過時。

一致性 ★☆☆☆☆   實時性 ★★★★★中間件

更新數據庫之後,無論redis,等redis中的數據本身過時。查詢數據庫時,順便把新值寫入redis。

好處是:很簡單。壞處是:在沒到過時時間以前,數據都是不一致的。比較適合放一些對一致性要求不高,但查詢比較多的場景。隊列

過時時間也能夠設置的短一些,好比就幾秒鐘,能提升一些一致性,並防止緩存穿透。事務

2、更新DB -> 刪除redis

一致性 ★★☆☆☆   實時性 ★★★★☆

這種方案的不一致性在於,A更新了DB,A尚未成功刪除redis,B又來讀redis,這時候B讀走的就是舊值。在C讀取DB時纔會從新將新值放入redis。

在配合key的過時時間的使用,數據一致性能比第一種方案好很多。

3、刪除redis -> 更新DB -> 刪除redis

一致性 ★★★☆☆   實時性 ★★★☆☆

這種方案的數據不一致性在於,A先刪除redis,A在沒有完成更新DB時,這時候B讀redis,發現沒有值,再去讀DB,讀到了舊值,B尚未把舊值寫入redis呢,A就已經完成更新DB的操做並把新值寫入redis,等B完成寫入redis時,值又被替換成了舊值。

4、刪除redis -> 更新DB -> 等待一段時間 ->刪除redis

一致性 ★★★★☆   實時性★★☆☆☆

這種方案是對方案三的改進,A先刪除redis,A更新完DB以後,等待一段時間(B讀DB並寫入redis的時間,這個時間須要本身估一下),而後A再刪除redis。

其餘文章中提到過這種方法被稱爲「延時雙刪」,雖然也並不完美,但也能應付大部分的場景了。

 還有不少更高級的保持數據一致性的方法,你們能夠自行研究,臣妾作不到了,但好像任何方法都不能保證100%的數據一致性。

選擇適合本身業務場景的就好。若是嚴格要求一致性,那麼,把緩存幹掉吧....

請輕噴.....

image