讀的時候,先讀快取,快取中沒有資料的話,就讀資料庫,然後將資料取出,存入快取並返回。更新資料時,先將資料更新資料庫,然後在刪除快取。
在現實場景下快取的資料不僅僅是資料庫直接讀取出來的值,可能需要和資料庫中其他資料聚合,再次聚合計算後寫入快取的話,加大了效能消耗。
其實刪除快取是乙個lazy計算的思想。
問題:更新資料庫後,刪除快取出錯,導致資料庫是新資料快取中是舊資料。
處理方式:先刪除快取,再更新資料庫。
如果刪除快取出錯,資料庫不會修改,兩者都是舊資料;如果更新資料庫出錯,讀取時,快取中是空的,資料庫是舊的,那麼兩者都是舊資料,可解決不一致問題。
問題:資料發生了變更,先刪除了快取,然後要去修改資料庫,此時還沒修改。乙個請求過來,去讀快取,發現快取空了,去查詢資料庫,查到了修改前的舊資料,放到了快取中。隨後資料變更的程式完成了資料庫的修改,導致資料庫是新資料快取中是舊資料。
處理方式:更新資料的時候,根據資料的唯一標識,將操作路由之後,傳送到乙個 jvm 內部佇列中。讀取資料的時候,如果發現資料不在快取中,那麼將重新讀取資料+更新快取的操作,根據唯一標識路由之後,也傳送同乙個 jvm 內部佇列中。
乙個佇列對應乙個工作執行緒,每個工作執行緒序列拿到對應的操作,然後一條一條的執行。這樣的話,乙個資料變更的操作,先刪除快取,然後再去更新資料庫,但是還沒完成更新。此時如果乙個讀請求過來,讀到了空的快取,那麼可以先將快取更新的請求傳送到佇列中,此時會在佇列中積壓,然後同步等待快取更新完成。
這裡有乙個優化點,乙個佇列中,其實多個更新快取請求串在一起是沒意義的,因此可以做過濾,如果發現佇列中已經有乙個更新快取的請求了,那麼就不用再放個更新請求操作進去了,直接等待前面的更新操作請求完成即可。
如果請求還在等待時間範圍內,不斷輪詢發現可以取到值了,那麼就直接返回;如果請求等待的時間超過一定時長,那麼這一次直接從資料庫中讀取當前的舊值。
Redis如何保證快取與資料庫的雙寫一致性?
原創 只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫,你只要是雙寫,就一定會有資料一致性的問題 那麼,如何解決一致性問題?一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求快取 資料庫必須保持一致性的話,最好不要做這個方案。即 讀請求和寫請求序列化,串到乙...
如何保證快取與資料庫的雙寫一致性?
cache aside pattern 最經典的快取 資料庫讀寫的模式,就是 cache aside pattern。讀的時候,先讀快取,快取沒有的話,就讀資料庫,然後取出資料後放入快取,同時返回響應。三種方案如下 為什麼是刪除快取,而不是更新快取?原因很簡單,很多時候,在複雜點的快取場景,快取不單...
如何保證快取與資料庫的雙寫一致性?
只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫,你只要是雙寫,就一定會有資料一致性的問題,那麼你如何解決一致性問題?一般來說,如果允許快取可以稍微的跟資料庫偶爾有不一致的情況,也就是說如果你的系統不是嚴格要求 快取 資料庫 必須保持一致性的話,最好不要做這個方案,即 讀請求和寫請求序列化,串到乙個...