高併發快取 資料庫雙寫不一致

2021-08-30 21:50:54 字數 2177 閱讀 1442

情景一

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

解決方案

先刪除快取,再修改資料庫,如果刪除快取成功了,如果修改資料庫失敗了,那麼資料庫中是舊資料,快取中是空的,那麼資料不會不一致

因為讀的時候快取沒有,則讀資料庫中舊資料,然後更新到快取中

情景二

1.資料發生了變更,先刪除了快取,然後要去修改資料庫,此時還沒修改

2.乙個請求過來,去讀快取,發現快取空了,去查詢資料庫,查到了修改前的舊資料,放到了快取中

3.資料變更的程式完成了資料庫的修改

4.此時資料庫和快取中的資料不一致

解決方案

更新資料的時候,根據資料的唯一標識,將操作路由(標識位)之後,傳送到乙個jvm內部的佇列中

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

乙個佇列對應乙個工作執行緒

每個工作執行緒序列拿到對應的操作,一條一條的執行

乙個資料變更的操作,先執行,刪除快取,然後再去更新資料庫,但是還沒完成更新

此時如果乙個讀請求過來,讀到了空的快取,那麼可以先將快取更新的請求傳送到佇列中,然後同步等待快取更新完成

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

如果請求還在等待時間範圍內,不斷輪詢發現可以取到值了,那麼就直接返回;

如果請求等待的時間超過一定時長,那麼這一次直接從資料庫中讀取當前的舊值

(1)讀請求長時阻塞

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

另外一點,因為乙個佇列中,可能會積壓針對多個資料項的更新操作,因此需要根據自己的業務情況進行測試,可能需要部署多個服務,每個服務分攤一些資料的更新操作.如果乙個記憶體佇列裡居然會擠壓100個商品的庫存修改操作,每隔庫存修改操作要耗費10ms區完成,那麼最後乙個商品的讀請求,可能等待10 * 100 = 1000ms = 1s後,才能得到資料。這個時候就導致讀請求的長時阻塞

(2)讀請求併發量過高

這裡還必須做好壓力測試,確保恰巧碰上上述情況的時候,還有乙個風險,就是突然間大量讀請求會在幾十毫秒的延時hang在服務上,看服務能不能抗的住,需要多少機器才能抗住最大的極限情況的峰值

但是因為並不是所有的資料都在同一時間更新,快取也不會同一時間失效,所以每次可能也就是少數資料的快取失效了,然後那些資料對應的讀請求過來,併發量應該也不會特別大

按1:99的比例計算讀和寫的請求,每秒5萬的讀qps,可能只有500次更新操作

如果一秒有500的寫qps,那麼要測算好,可能寫操作影響的資料有500條,這500條資料在快取中失效後,可能導致多少讀請求,傳送讀請求到庫存服務來,要求更新快取

一般來說,1:1,1:2,1:3,每秒鐘有1000個讀請求,會hang在庫存服務上,每個讀請求最多hang多少時間,200ms就會返回

在同一時間最多hang住的可能也就是單機200個讀請求,同時hang住單機hang200個讀請求,還是ok的。

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

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

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

萬一某個商品的讀寫請求特別高,全部打到相同的機器的相同的佇列裡面去了,可能造成某台機器的壓力過大

就是說,因為只有在商品資料更新的時候才會清空快取,然後才會導致讀寫併發,所以更新頻率不是太高的話,這個問題的影響並不是特別大

但是的確可能某些機器的負載會高一些

高併發快取資料庫不一致

在一般的 的架構中,我們都會採用快取架構來抗住高併發場景下的讀請求。那麼對於寫請求,先更新快取還是先更新資料庫?本文以商品庫存資訊為例,我們展開討論,假設剛開始資料庫庫存 100,快取中庫存 100.1.先更新資料庫,後更新快取 這種情況下,當需要更新庫存的時候,先更新資料庫中的庫存 99,然後再更...

redis快取 資料庫雙寫不一致

讀的時候 先讀快取,快取沒有的話,再讀取資料庫,然後取出資料後放入快取,同時返回響應 更新的時候 先刪除快取,然後再更新資料庫 之所以刪除快取而不是更新,其實是乙個懶載入的思想,避免頻繁更新,降低開銷,同時也可以避免更新快取成功後在更新資料庫時異常帶來的問題 場景1 先修改資料庫,再修改 刪除快取,...

快取與資料庫雙寫不一致

在大併發下,多執行緒運算元據庫與快取會存在兩者資料不一致的問題。首先重要的是先更新資料庫,在失效快取。執行緒1先更新資料庫,將字段t改為6,然後將快取失效,執行緒結束。執行緒2過來讀資料庫,讀取到了t為6的資訊,在準備插入快取之前發生了執行緒排程,執行緒3過來更新資料庫,並且將快取失效後執行緒3結束...