1. 程式人生 > >數據庫事務環境下表級緩存的更新問題

數據庫事務環境下表級緩存的更新問題

用戶 事務管理 回來 環境 同時 查詢 現在 我們 表數據

表數據過多時,通常會為表的記錄增加緩存。在我們的業務中,用戶的信息是使用redis來做緩存的,避免用戶的每次請求都直接查詢數據庫。
在一些場景下,需要為用戶的一連串數據庫操作做事務管理,同時也需要刪除掉舊的用戶信息表的緩存。例如現在有一個金幣兌換物品的場景,用戶兌換的流程如下:

  1. 用戶信息表:扣除用戶金幣
  2. 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
  3. 用戶金幣流水表:新增用戶扣除金幣記錄
  4. 進行實際下單兌換的接口調用
  5. 更新用戶兌換表狀態為:已扣除金幣

如果在進行實際下單兌換時接口調用返回來非超時失敗,那麽需要將1、2、3步驟的數據庫操作進行回滾。
這種場景下,什麽時候刪除舊的緩存就顯得很重要,更新緩存的時機不當,會留下緩存數據與數據庫數據不一致的隱患。例如將緩存刪除的操作位於以下位置時:

  1. 用戶信息表:扣除用戶金幣
    --》 刪除用戶信息表緩存
  2. 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
  3. 用戶金幣流水表:新增用戶扣除金幣記錄
  4. 進行實際下單兌換的接口調用
  5. 更新用戶兌換表狀態為:已扣除金幣

在並發的情況下,可能會出現:

  • 下單兌換的線程刪除了用戶信息表緩存
  • 另一個請求的線程重新讀取用戶信息表數據並更新了緩存
  • 此時下單兌換的線程下單失敗進行了金幣回滾

此時緩存中的用戶金幣與數據庫表中的用戶金幣是不一致的。將緩存刪除的位置處於以下位置時:

  1. 用戶信息表:扣除用戶金幣
  2. 用戶的兌換表:新增一行記錄,狀態為:“已扣金幣;未創建訂單”
  3. 用戶金幣流水表:新增用戶扣除金幣記錄
  4. 進行實際下單兌換的接口調用
  5. 更新用戶兌換表狀態為:已扣除金幣
    --》 刪除用戶信息表緩存

則不會發生以上的情況。在使用表級緩存 + 數據庫事務 的環境下 需要註意這個問題。

數據庫事務環境下表級緩存的更新問題