数据库与缓存不一致,你会怎么办?

資料庫主從,為什麼會不一致?先回顧下,無快取時,資料庫主從不一致問題。

如上圖,發生的場景是,寫後立刻讀:
1. 主庫一個寫請求(主從沒同步完成);
2. 從庫接著一個讀取請求,讀到了舊數據;

3. 最後,主從同步完成;
導致的結果是:主動同步完成之前,會讀取到舊資料。
可以看到,主從不一致的影響時間很短,在主從同步完成後,就會讀到新資料。
快取與資料庫,什麼時候會不一致?

再看,引入快取後,快取和資料庫不一致問題。

如上圖,發生的場景也是,寫後立刻讀:

(1+2)先一個寫請求,淘汰緩存,寫數據庫;(3+4+5)接著立刻一個讀請求,讀緩存,cache miss,讀從庫,寫緩存放入數據,以便後續的讀能夠cache hit(主從同步沒有完成,緩存中放入了舊數據緩存(6)最後,主從同步沒有完成,緩存中同步完成了舊數據);
導致的結果是:舊資料放入緩存,即使主從同步完成,後續仍會從快取一直讀取到舊資料。
可以看到,加入快取後,導致的不一致影響時間會很長,最終不會達到一致。
為什麼會出現這類不一致?
上如所述,快取與資料庫資料不一致,根本上是由資料庫主從不一致引起的。

當主庫上發生寫入操作之後,從庫binlog同步的時間間隔內,讀取請求,可能導致有舊資料入快取。
假如主從不一致無法徹底解決,引入快取之後,binlog同步時間間隔內,也無法避免讀取舊資料。
但是,有沒有辦法做到,即使引入緩存,不一致不會比「不引入緩存」更糟呢?這是更實際的最佳化目標。
想法轉化為:從庫同步完成之後,如果有舊資料入緩存,應該及時淘汰這個舊資料。
快取與資料庫不一致,可以怎麼優化?

如上圖所述,在並發讀寫導致快取中讀入了髒資料之後:

(6)主從同步;

(7)透過工具訂閱從庫的binlog,這裡能夠最準確的知道,從庫資料同步完成的時間;(8)從庫執行完寫操作,向快取再次發起刪除,淘汰這段時間內可能寫入快取的舊資料;
如此這般,至少能夠保證,引入快取之後,主從不一致,不會比沒有引入快取更壞。
知其然,知其所以然。思路比結論更重要。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


*