一、資料庫主從不一致
先回顧下,無快取時,資料庫主從不一致問題。
如上圖,發生的場景是,寫後立刻讀:
(1)主庫乙個寫請求(主從沒同步完成)
(2)從庫接著乙個讀請求,讀到了舊資料
(3)最後,主從同步完成
導致的結果是:主動同步完成之前,會讀取到舊資料。
可以看到,主從不一致的影響時間很短,在主從同步完成後,就會讀到新資料。
二、快取與資料庫不一致
如上圖,發生的場景也是,寫後立刻讀:
(1+2)先乙個寫請求,淘汰快取,寫資料庫
(3+4+5)接著立刻乙個讀請求,讀快取,cache miss,讀從庫,寫快取放入資料,以便後續的讀能夠cache hit(主從同步沒有完成,快取中放入了舊資料)
(6)最後,主從同步完成
導致的結果是:舊資料放入快取,即使主從同步完成,後續仍然會從快取一直讀取到舊資料。
可以看到,加入快取後,導致的不一致影響時間會很長,並且最終也不會達到一致。
三、問題分析
可以看到,這裡提到的快取與資料庫資料不一致,根本上是由資料庫主從不一致引起的。當主庫上發生寫操作之後,從庫binlog同步的時間間隔內,讀請求,可能導致有舊資料入快取。
假如主從不一致沒法徹底解決,引入快取之後,binlog同步時間間隔內,也無法避免讀舊資料。
但是,有沒有辦法做到,即使引入快取,不一致不會比「不引入快取」更糟呢?這是更為實際的優化目標。
思路轉化為:在從庫同步完成之後,如果有舊資料入快取,應該及時把這個舊資料淘汰掉。
四、不一致優化
如上圖所述,在併發讀寫導致快取中讀入了髒資料之後:
(6)主從同步
(7)通過工具訂閱從庫的binlog,這裡能夠最準確的知道,從庫資料同步完成的時間
畫外音:本圖畫的訂閱工具是dts,可以是cannal,也可以自己訂閱和分析binlog
(8)從庫執行完寫操作,向快取再次發起刪除,淘汰這段時間內可能寫入快取的舊資料
如此這般,至少能夠保證,引入快取之後,主從不一致,不會比沒有引入快取更壞。
畫外音:即使引入快取,也只有乙個很小的時間間隔,可能讀到舊資料。
快取不一致
當程式在執行過程中,會將運算需要的資料從主存複製乙份到cpu的快取記憶體當中,那麼cpu進行計算時就可以直接從它的快取記憶體讀取資料和向其中寫入資料,當運算結束之後,再將快取記憶體中的資料重新整理到主存當中。舉個簡單的例子 i i 1。當執行緒執行這個語句時,會先從主存當中讀取i的值,然後複製乙份到...
快取與資料庫雙寫不一致
在大併發下,多執行緒運算元據庫與快取會存在兩者資料不一致的問題。首先重要的是先更新資料庫,在失效快取。執行緒1先更新資料庫,將字段t改為6,然後將快取失效,執行緒結束。執行緒2過來讀資料庫,讀取到了t為6的資訊,在準備插入快取之前發生了執行緒排程,執行緒3過來更新資料庫,並且將快取失效後執行緒3結束...
高併發快取資料庫不一致
在一般的 的架構中,我們都會採用快取架構來抗住高併發場景下的讀請求。那麼對於寫請求,先更新快取還是先更新資料庫?本文以商品庫存資訊為例,我們展開討論,假設剛開始資料庫庫存 100,快取中庫存 100.1.先更新資料庫,後更新快取 這種情況下,當需要更新庫存的時候,先更新資料庫中的庫存 99,然後再更...