您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何淺析數據庫與緩存的雙寫一致性問題,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
緩存由于其高并發和高性能的特性,在項目中被廣泛使用。讀緩存流程如下圖:
雙寫一致性有以下三個要求:
緩存不能讀到臟數據
緩存可能會讀到過期數據,但要在可容忍時間內實現最終一致
這個可容忍時間盡可能的小
要想同時滿足上面三條,可以采用讀請求和寫請求串行化,串到一個內存隊列里去,這樣就可以保證一定不會出現不一致的情況。但是,串行化之后,就會導致系統的吞吐量會大幅度的降低,要用比正常情況下多幾倍的機器去支撐線上請求。
所以,在這里,我們討論三種常見方法:
先更新數據庫,再更新緩存
先刪除緩存,再更新數據庫
先更新數據庫,再刪除緩存
這種方法是大家普遍反對的,原因集中在下面兩點:
原因1:線程安全角度。
同時有請求A和請求B進行更新操作,那么會出現:
線程A更新了數據庫
線程B更新了數據庫
線程B更新了緩存
線程A更新了緩存
這就出現請求A更新緩存應該比請求B更新緩存早才對,但是因為網絡等原因,B卻比A更早更新了緩存。這就導致了臟數據,因此不考慮。
"先更新緩存,再更新數據庫"這種方案同理,也是造成臟數據,所以不被考慮
原因2:業務場景角度。
有如下兩點:
如果你是一個寫數據庫場景比較多,而讀數據場景比較少的業務需求,采用這種方案就會導致數據壓根還沒讀到,緩存就被頻繁的更新,浪費性能。
如果你寫入數據庫的值,并不是直接寫入緩存的,而是要經過一系列復雜的計算再寫入緩存。那么,每次寫入數據庫后,都再次計算寫入緩存的值,無疑是浪費性能的。顯然,刪除緩存更為適合。
如果一定要更新緩存,可以考慮給緩存數據增加版本號
該方案同樣會導致不一致。同時有請求A和請求B進行更新操作,那么會出現:
請求A進行寫操作,刪除緩存
請求B查詢發現緩存不存在
請求B去數據庫查詢得到舊值
請求B將舊值寫入緩存
請求A將新值寫入數據庫上述情況就會導致不一致的情形出現。而且,如果不采用給緩存設置過期時間策略,該數據永遠都是臟數據。
解決方法:
先刪除緩存
再寫數據庫(這兩步和原來一樣)
休眠一定時間(例如1秒或200ms),再次刪除緩存。這么做,可以將緩存臟數據再次刪除。
然而這種解決方案由于要休眠線程還是很影響吞吐量的
這種方案是很多工程采用的方案,我們來看下是否一定安全。
假設有兩個請求,一個請求A做查詢操作,一個請求B做更新操作,那么會有如下情形產生
緩存剛好失效
請求A查詢數據庫,得一個舊值
請求B將新值寫入數據庫
請求B刪除緩存
請求A將查到的舊值寫入緩存
這樣,臟數據就產生了,然而上面的情況是假設在數據庫寫請求比讀請求還要快。實際上,工程中數據庫的讀操作的速度遠快于寫操作的。
要么通過2PC或是Paxos協議保證一致性,要么就是想盡辦法降低并發時臟數據的概率,大概是因為2PC太慢,而Paxos又太復雜,綜合考慮,Facebook選擇了這個第三種方案。
啟動一個訂閱程序去訂閱數據庫的binlog,獲得需要操作的數據。在應用程序中,另起一段程序,獲得這個訂閱程序傳來的信息,進行刪除緩存操作。
看完上述內容,你們對如何淺析數據庫與緩存的雙寫一致性問題有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。