快取與資料庫雙寫時的資料一致性

2021-09-29 13:18:02 字數 2151 閱讀 4764

2.最初級的快取不一致問題及解決方案

3.比較複雜的資料不一致問題分析

參考:如何保證快取與資料庫的雙寫一致性?

一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求 「快取+資料庫」 必須保持一致性的話,最好不要做這個方案,即:讀請求和寫請求序列化,串到乙個記憶體佇列裡去。

序列化可以保證一定不會出現不一致的情況,但是它也會導致系統的吞吐量大幅度降低,用比正常情況下多幾倍的機器去支撐線上的乙個請求。

最經典的快取+資料庫讀寫的模式,就是 cache aside pattern。

讀的時候,先讀快取,快取沒有的話,就讀資料庫,然後取出資料後放入快取,同時返回響應。

更新的時候,先更新資料庫,然後再刪除快取。

原因很簡單,很多時候,在複雜點的快取場景,快取不單單是資料庫中直接取出來的值。比如可能更新了某個表的乙個字段,然後其對應的快取,是需要查詢另外兩個表的資料並進行運算,才能計算出快取最新的值的。

另外更新快取的代價有時候是很高的。每次修改資料庫的時候,都一定要將其對應的快取更新乙份?這個快取到底會不會被頻繁訪問到?

其實刪除快取,而不是更新快取,就是乙個 lazy 計算的思想,不要每次都重新做複雜的計算,不管它會不會用到,而是讓它到需要被使用的時候再重新計算。像 mybatis,hibernate,都有懶載入思想。

先更新資料庫,再刪除快取。如果刪除快取失敗了,那麼會導致資料庫中是新資料,快取中是舊資料,資料就出現了不一致。

解決思路:

先刪除快取,再更新資料庫。如果資料庫更新失敗了,那麼資料庫中是舊資料,快取中是空的,那麼資料不會不一致。

因為讀的時候快取沒有,所以去讀了資料庫中的舊資料,然後更新到快取中。

資料發生了變更,先刪除了快取,然後要去修改資料庫,此時還沒修改。乙個請求過來,去讀快取,發現快取空了,去查詢資料庫,查到了修改前的舊資料,放到了快取中。隨後資料變更的程式完成了資料庫的修改。完了,資料庫和快取中的資料不一樣了…

只有在對乙個資料在併發的進行讀寫的時候,才可能會出現這種問題。如果併發量很低的情況下,不會出現剛才描述的那種不一致的場景。

如果每天的是上億的流量,每秒併發讀是幾萬,每秒只要有資料更新的請求,就可能會出現上述的資料庫+快取不一致的情況。

更新資料的時候,根據資料的唯一標識,將操作路由之後,傳送到乙個 jvm 內部佇列中。讀取資料的時候,如果發現資料不在快取中,那麼將重新執行「讀取資料+更新快取」的操作,根據唯一標識路由之後,也傳送到同乙個 jvm 內部佇列中。

乙個佇列對應乙個工作執行緒,每個工作執行緒序列拿到對應的操作,然後一條一條的執行。這樣的話,乙個資料變更的操作,先刪除快取,然後再去更新資料庫,但是還沒完成更新。此時如果乙個讀請求過來,沒有讀到快取,那麼可以先將快取更新的請求傳送到佇列中,此時會在佇列中積壓,然後同步等待快取更新完成。

這裡有乙個優化點,乙個佇列中,其實多個更新快取請求串在一起是沒意義的,因此可以做過濾,如果發現佇列中已經有乙個更新快取的請求了,那麼就不用再放個更新請求操作進去了,直接等待前面的更新操作請求完成即可。

待那個佇列對應的工作執行緒完成了上乙個操作的資料庫的修改之後,才會去執行下乙個操作,也就是快取更新的操作,此時會從資料庫中讀取最新的值,然後寫入快取中。

如果請求還在等待時間範圍內,不斷輪詢發現可以取到值了,那麼就直接返回;如果請求等待的時間超過一定時長,那麼這一次直接從資料庫中讀取當前的舊值。

1.讀請求長時阻塞

由於讀請求進行了非常輕度的非同步化,所以一定要注意讀超時的問題,每個讀請求必須在超時時間範圍內返回。

該解決方案,最大的風險點在於說,可能資料更新很頻繁,導致佇列中積壓了大量更新操作在裡面,然後讀請求會發生大量的超時,最後導致大量的請求直接走資料庫。

2.讀請求併發量過高

突然間大量讀請求會在幾十毫秒的延時行在服務上,看服務能不能扛的住,需要多少機器才能扛住最大的極限情況的峰值。

3.多服務例項部署的請求路由

可能這個服務部署了多個例項,那麼必須保證說,執行資料更新操作,以及執行快取更新操作的請求,都通過 nginx 伺服器路由到相同的服務例項上。

4.熱點商品的路由問題,導致請求的傾斜

萬一某個商品的讀寫請求特別高,全部打到相同的機器的相同的佇列裡面去了,可能會造成某台機器的壓力過大。就是說,因為只有在商品資料更新的時候才會清空快取,然後才會導致讀寫併發,所以其實要根據業務系統去看,如果更新頻率不是太高的話,這個問題的影響並不是特別大,但是的確可能某些機器的負載會高一些。

保證快取與資料庫雙寫時的資料一致性

快取與資料庫雙寫時的資料一致性問題 只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫,你只要是雙寫,就一定會有資料一致性的問題,那麼你如何解決一致性問題?一般來說,就是如果你的系統不是嚴格要求快取 資料庫必須一致性的話,快取可以稍微的跟資料庫偶爾有不一致的情況,最好不要做這個方案,讀請求和寫請求序列...

快取與資料庫資料一致性

1 無論是雙寫模式還是失效模式,都會導致快取的不一致問題。即多個例項同時更新會出事。怎麼辦?解決方案 a 如果是使用者緯度資料 訂單資料 使用者資料 這種併發機率非常小,不用考慮這個問題,快取資料加上過期時間,每隔一段時間觸發讀的主動更新即可 b 如果是選單,商品介紹等基礎資料,也可以去使用cana...

資料庫 快取資料一致性

1 不推薦更新快取 建議刪除快取 2 採用延時雙刪 先刪快取,後更新資料庫,延時再刪一次快取 但是會存在問題 改庫後延時時間內的資料可能是舊資料 如果業務場景要求,改庫成功就不能使用舊資料,可以採用如下優化方案 新增乙個快取型別,記錄key是否被更新過,並且設定自動過期時間 在訪問的時候,先查詢ke...