redis緩存和數(shù)據(jù)庫一致性問題及解決方案

根據(jù)當前計算機系統(tǒng)的三層儲存架構(gòu),cpu緩存,內(nèi)存,磁盤,我們?nèi)粘i_發(fā)通常會模仿這三層儲存架構(gòu)而在數(shù)據(jù)庫之上添加機器本地緩存及redis緩存,既然涉及到了多個儲存系統(tǒng),那么必然就有數(shù)據(jù)一致性問題。

根據(jù)redis緩存的使用,可以分成2種情況:只讀緩存和讀寫緩存

1.只讀緩存

當系統(tǒng)收到get請求,則查詢redis,redis有數(shù)據(jù)則返回,無數(shù)據(jù)則查詢數(shù)據(jù)庫,查到之后,寫入緩存,以便于以后的請求使用。至于寫請求,直接操作數(shù)據(jù)庫。這樣做的好處就是,保證了最新數(shù)據(jù)都在數(shù)據(jù)庫中,而數(shù)據(jù)庫是有可靠性保障的。

2.讀寫緩存

寫請求也會發(fā)送到redis,得益于redis的高性能,寫請求能快速完成,但是如果數(shù)據(jù)沒有寫入數(shù)據(jù)庫,便發(fā)生宕機或者掉電,那么會發(fā)生數(shù)據(jù)丟失,給業(yè)務帶來風險。所以通常會有兩種回寫策略。

2.1同步回寫

由于數(shù)據(jù)庫和redis的速度差異,同步回寫會降低系統(tǒng)的響應速度。

2.2異步回寫

所有的寫操作先在緩存中更改,優(yōu)先考慮系統(tǒng)響應,同樣的,reids的宕機或者掉電則會導致數(shù)據(jù)丟失。

3.數(shù)據(jù)一致性

分為兩種情況,一是 緩存中有數(shù)據(jù),則必須與數(shù)據(jù)庫中的數(shù)據(jù)一致;二是 緩存中沒數(shù)據(jù),則數(shù)據(jù)庫中的數(shù)據(jù)必須是最新的。

對于讀寫緩存而言,根據(jù)具體場景對一致性的要求,選擇同步或者異步回寫。

對于讀緩存而言,數(shù)據(jù)的一致性的復雜程度,主要發(fā)生在數(shù)據(jù)的刪除和修改,新增的話,直接操作數(shù)據(jù)庫,故無一致性問題。

3.1刪除和修改數(shù)據(jù)

第一種情況:我們先刪除緩存,在更新數(shù)據(jù)庫,潛在的問題:數(shù)據(jù)庫更新失敗了,get請求進來發(fā)現(xiàn)沒緩存則請求數(shù)據(jù)庫,

導致緩存又刷入了舊的值。

第二種情況:我們先更新數(shù)據(jù)庫,再刪除緩存,潛在的問題:緩存刪除失敗,get請求進來緩存命中,導致讀到的是舊值

3.2先刪除緩存再更新數(shù)據(jù)庫

假設(shè)有2個線程A和B,A刪除緩存之后,由于網(wǎng)絡(luò)延遲,在更新數(shù)據(jù)庫之前,B來訪問了,發(fā)現(xiàn)緩存未命中,則去請求數(shù)據(jù)庫然后把舊值刷入了緩存,這時候姍姍來遲的A,才把最新數(shù)據(jù)刷入數(shù)據(jù)庫,導致了數(shù)據(jù)的不一致性

3.2.1延遲雙刪

我們可以在A更新完數(shù)據(jù)庫之后,sleep一會,再刪一次緩存,需要注意的是,你要sleep到線程B把舊值刷到了緩存里面你再醒來把緩存刪了,不然就會又被線程B把舊的值刷進去,所以需要預估讀緩存和寫緩存的時間以此確認應當sleep多久

3.3先更新數(shù)據(jù)庫再刪除緩存

這種場景潛在的風險就是更新完數(shù)據(jù)庫,刪緩存之前,會有部分并發(fā)請求讀到舊值,這種情況對業(yè)務影響較小,我們通過重試機制,保證緩存能得到刪除

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容