在 Redis 中保證緩存與數據庫的數據一致性,需結合業務場景選擇以下策略:
核心策略總結
-
Cache Aside(旁路緩存)模式
- 讀操作:先查緩存,未命中則查數據庫并寫入緩存。
- 寫操作:先更新數據庫,再刪除緩存(推薦延遲雙刪或異步重試)。
- 適用場景:大多數業務,實現簡單但需處理并發不一致。
-
Write Through(寫穿透)模式
- 應用程序僅操作緩存,由緩存同步更新數據庫。
- 適用場景:對一致性要求高但寫入頻率低的簡單數據模型。
-
Write Behind(異步緩存寫入)模式
- 寫操作僅更新緩存,異步批量同步到數據庫。
- 適用場景:非關鍵數據(如日志、瀏覽量),追求極致性能。
-
數據庫變更通知(Binlog監聽)
- 通過 Canal 等工具訂閱數據庫 Binlog,觸發緩存更新。
- 適用場景:需要實時性強的強一致性場景。
-
分布式鎖與原子操作
- 通過鎖機制保證數據庫和緩存操作的原子性。
- 適用場景:強一致性要求極高的核心業務(如金融交易)。
-
緩存失效策略
- 設置合理的 TTL,平衡緩存命中率和一致性需求。
- 適用場景:允許短暫不一致的通用數據(如商品信息)。
方案選擇建議
- 強一致性場景(如金融、訂單):
優先選擇 Cache Aside + 延遲雙刪 或 數據庫變更通知,結合重試機制。 - 最終一致性場景(如商品庫存、用戶信息):
使用 Cache Aside + 合理 TTL,降低實現復雜度。 - 高并發寫場景(如日志、點贊數):
使用 Write Behind 模式,犧牲部分一致性換取性能。
關鍵實現細節
- 延遲雙刪:更新數據庫后,延遲一段時間(如 100ms)再次刪除緩存,覆蓋并發讀請求。
- 重試機制:刪除緩存失敗時,將任務寫入消息隊列異步重試。
- 監控與告警:建立緩存命中率、數據庫負載等指標的監控,及時發現不一致問題。
代碼示例(Cache Aside + 延遲雙刪)
// 寫操作
public void updateUser(User user) {userRepository.save(user); // 更新數據庫redisService.delete("user:" + user.getId()); // 第一次刪除緩存CompletableFuture.runAsync(() -> { // 異步延遲雙刪try { Thread.sleep(100); } catch (InterruptedException e) {}redisService.delete("user:" + user.getId()); // 第二次刪除});
}// 讀操作
public User getUser(Long id) {String key = "user:" + id;User user = redisService.get(key);if (user == null) {user = userRepository.findById(id).orElse(null);if (user != null) { redisService.set(key, user); } // 寫入緩存}return user;
}
總結
- 無銀彈:一致性、性能和復雜度需權衡,根據業務場景選擇策略。
- 最終一致性:在分布式系統中,完全的強一致性難以保證,需通過異步任務、消息隊列等方式確保數據最終一致。
我正在程序員刷題神器面試鴨上高效準備面試,9000+ 高頻面試真題、800 萬字優質題解,覆蓋主流編程方向,跟我一起刷原題、過面試:
點擊進入