公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 資料庫和Redis如何保持強一致性,這篇文章告訴你 目的 Redis和Msql來保持數據同步,並且強一致,以此來提高對應介面的響應速度,剛開始考慮是用mybatis的二級緩存,發現坑不少,於是決定自己搞 要關註的問題點 操 ...
公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。
資料庫和Redis如何保持強一致性,這篇文章告訴你
目的
Redis和Msql來保持數據同步,並且強一致,以此來提高對應介面的響應速度,剛開始考慮是用mybatis的二級緩存,發現坑不少,於是決定自己搞
要關註的問題點
操作數據必須是唯一索引
如果更新數據不是唯一索引,則資料庫更新後的值,與緩存不一致,而查詢還會走緩存,而查詢的值是臟值。
查詢唯一數據,數據值必須是全部欄位
假如:B交易查詢欄位不是全部欄位,進行查詢放入緩存,A交易進行查詢時,從緩存獲取,由於A交易需要全部欄位,所以就會出現不可預知的問題。
查詢緩存數據後,必須要在程式中再次進行條件判斷
因為在redis中,存儲的的key是唯一索引,所以當查詢數據後,只會命中唯一索引的數據,其他附帶查詢條件不生效。
例如:唯一索引為:user_id
,那麼執行
select * from t_user_auth_info where user_id=‘111’ and user_level=‘1’
是,條件user_level是不會生效
高併發場景下要註意臟數據的控制
假設是以上流程圖,在更新操作,第一步刪除緩存後,線程切換到查詢線程,查詢操作判斷緩存中沒有數據,就會查詢資料庫,並把數據存入到緩存中,這時線程在切換到更新線程,進行資料庫的更新,這會就會造成,資料庫的數據與緩存有不一致性。
最終方案
基於以上問題,我們的最終流程圖如下
以上流程圖在進行更新操作時,增加刪除緩存lock,如果這會查詢操作判斷緩存中有數據,就直接返回數據,如果沒有再次判斷有沒有存在刪除緩存lock,如果有則走資料庫查詢,並返回,不放入緩存,如果沒有則查詢資料庫,並放入緩存,並返回。
註意: 登記緩存標識時,增加緩存lock失效時間,因為有可能刪除緩存和資料庫更新成功了,而刪除緩存lock失敗了,那這樣後續查詢就都走資料庫了,這個方案就失去意義了。
代碼實現方案
通過aop對db的操作方法,進行攔截,查詢方法採用一個切麵,刪除和更新方法採用一個切麵,然後再按照以上流程進行編寫,我們這邊是使用框架進行封裝,最後只需要開發人員配置以下xml即可
<cache-config>
<cache-entity po="com.demo.po.AuthUser" key-prefix="SYSTEM_Person" po-throws="true" key-expire="" key-expire-time-unit="">
<key-properties>userId</key-properties>
</cache-entity>
</cache-config>
如果需要具體實現方案,請聯繫作者