一.爲何寫這邊文章redis
首先,緩存因爲其高併發和高性能的特性,已經在項目中被普遍使用。在讀取緩存方面,你們沒啥疑問,都是按照下午的流程來進行業務操做:數據庫
可是,在更新緩存方面,對於更新完數據庫,是更新緩存呢,仍是刪除緩存?又或者是先刪除緩存,再更新數據庫?其實這一塊是存在很大的爭議。緩存
2、文章結構網絡
3、正文併發
先作一個說明,從理論上來講,給緩存設置過時時間,是保證最終一致性的解決方案。這種方案下,咱們能夠對緩存的數據設置過時時間,全部的寫操做以數據庫爲準,對緩存操做只是盡最大努力便可。也就是說若是數據庫寫成功,緩存更新失敗,那麼只要到達過時時間,則後面的讀請求天然會從數據庫中讀取新值,而後回填緩存。所以,接下來討論的思路不依賴於給緩存設置過時時間這個方案。在這裏,咱們討論三種更新策略:高併發
爲何沒有先更新緩存,再更新數據庫這種策略?答案不用說了吧。性能
4、先更新數據庫,再更新緩存spa
這套方案,你們是廣泛反對的,爲何呢?有以下兩點緣由:線程
緣由一:線程安裝角度
同時又請求A和請求B進行更新操做,那麼會出現:code
這就出現請求A更新緩存應該比請求B更新緩存早纔對,可是由於網絡等緣由,B比A更早更新了緩存。這就致使了髒數據,所以不考慮!
緣由2、業務場景角度
有以下兩點:
1)若是你是一個寫數據庫場景比較多,而讀數據場景比較少的業務需求,採用這種方案就會致使,數據壓根還沒讀到,緩存就被頻繁的更新,浪費性能。
2)若是你寫入數據庫的值,並非直接寫入緩存的,而是要通過一系列負責的計算再寫入緩存。那麼,每次寫入數據庫後,都要再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更爲合適。
接下來討論的就是爭議最大的,先刪除緩存,再更新數據庫。仍是先更新數據庫,再刪除緩存的問題。
5、先刪除緩存,再更新數據庫
該方案會致使不一致的緣由:同時有一個請求A進行更新操做,另外一個請求B進行查詢操做。那麼就會出現如下情形:
上述狀況就會致使不一致的請求出現。並且,若是不採用給緩存設置過時時間策略,該數據永遠都是髒數據。
那麼,該如何解決呢?採用延時雙刪除策略!僞代碼以下:
public void write(String key, Object data){ redis.delKey(key); db.updateData(data); Thread.sleep(1000); redis.deleKey(key); }
解釋一下:
這麼作,能夠將1秒內所形成的緩存髒數據,再次刪除!