數據庫事務環境下表級緩存的更新問題
阿新 • • 發佈:2019-03-09
用戶 事務管理 回來 環境 同時 查詢 現在 我們 表數據
表數據過多時,通常會為表的記錄增加緩存。在我們的業務中,用戶的信息是使用redis來做緩存的,避免用戶的每次請求都直接查詢數據庫。
在一些場景下,需要為用戶的一連串數據庫操作做事務管理,同時也需要刪除掉舊的用戶信息表的緩存。例如現在有一個金幣兌換物品的場景,用戶兌換的流程如下:
- 用戶信息表:扣除用戶金幣
- 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
- 用戶金幣流水表:新增用戶扣除金幣記錄
- 進行實際下單兌換的接口調用
- 更新用戶兌換表狀態為:已扣除金幣
如果在進行實際下單兌換時接口調用返回來非超時失敗,那麽需要將1、2、3步驟的數據庫操作進行回滾。
這種場景下,什麽時候刪除舊的緩存就顯得很重要,更新緩存的時機不當,會留下緩存數據與數據庫數據不一致的隱患。例如將緩存刪除的操作位於以下位置時:
- 用戶信息表:扣除用戶金幣
--》 刪除用戶信息表緩存 - 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
- 用戶金幣流水表:新增用戶扣除金幣記錄
- 進行實際下單兌換的接口調用
- 更新用戶兌換表狀態為:已扣除金幣
在並發的情況下,可能會出現:
- 下單兌換的線程刪除了用戶信息表緩存
- 另一個請求的線程重新讀取用戶信息表數據並更新了緩存
- 此時下單兌換的線程下單失敗進行了金幣回滾
此時緩存中的用戶金幣與數據庫表中的用戶金幣是不一致的。將緩存刪除的位置處於以下位置時:
- 用戶信息表:扣除用戶金幣
- 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
- 用戶金幣流水表:新增用戶扣除金幣記錄
- 進行實際下單兌換的接口調用
- 更新用戶兌換表狀態為:已扣除金幣
--》 刪除用戶信息表緩存
則不會發生以上的情況。在使用表級緩存 + 數據庫事務 的環境下 需要註意這個問題。
數據庫事務環境下表級緩存的更新問題