【redis】使用redis作為緩存時所注意事項

緩存更新策略

在 Redis 緩存中,緩存的更新策略主要有**定期生成(定時更新)實時生成(即時更新)**兩種方式。不同的策略適用于不同的業務場景,涉及性能、數據一致性和系統負載等方面的權衡。


1. 定期生成(定時更新)

是什么?

定期生成指的是按照固定的時間間隔,主動更新緩存,而不是在數據發生變化時立即更新。這種方式適用于數據變化不頻繁、對實時性要求不高的場景。

優點:

? 降低數據庫壓力:緩存可以批量更新,避免頻繁查詢數據庫。
? 提高查詢性能:查詢時直接讀取緩存,響應速度快。
? 數據一致性較好(相對于長期不更新的緩存):定期更新可以保證數據不會長期過時。

缺點:

? 數據可能不夠實時:在緩存下一次更新前,數據可能已經變化,但緩存仍然返回舊數據。
? 不適合高實時性業務:如果業務需要頻繁變更數據,定期更新可能導致緩存數據滯后。
? 可能會引起短時流量沖擊:如果所有緩存數據同時更新,可能會對數據庫造成瞬間壓力。

常見實現方式:

  • 定時任務更新緩存Time-based Refresh

    • 使用 Spring Task、Quartz、Crontab 等定時任務,每隔一段時間刷新緩存。
    • 例如,每 10 分鐘更新一次緩存:
      @Scheduled(fixedRate = 600000) // 每 10 分鐘執行一次
      public void updateCache() {// 查詢數據庫并更新緩存List<Data> dataList = databaseService.getData();redisTemplate.opsForValue().set("cache:data", dataList);
      }
      

  • 數據庫變更時觸發緩存更新Database-triggered Refresh

    • 監聽 數據庫變更事件(MySQL Binlog、PostgreSQL 觸發器),檢測到數據變化后批量刷新緩存。
  • 異步任務更新

    • 使用消息隊列(Kafka、RabbitMQ)通知服務更新緩存,避免定時任務導致的瞬時數據庫壓力過大。
適用場景:

📌 統計數據、排行榜、熱門商品列表等(更新頻率較低,數據稍有延遲也無大問題)。
📌 日志分析、報表數據等(數據量大,但對實時性要求不高)。


2. 實時生成(即時更新)

是什么?

實時生成指的是數據發生變更時立即更新緩存,確保緩存數據始終是最新的。這種方式適用于對數據一致性要求高、變更較頻繁的場景。

優點:

? 數據實時性高:緩存的數據始終與數據庫保持一致,適用于高實時性需求的應用。
? 避免緩存不一致問題:數據庫變更后立即同步緩存,減少數據不匹配的情況。

缺點:

? 更新成本高:每次數據變更都需要更新緩存,可能會導致數據庫壓力增大。
? 可能導致緩存頻繁更新:對于高頻變更的數據,頻繁更新可能會導致 Redis 負載過重,甚至影響整體性能。
? 并發問題:多個并發請求可能會導致緩存不一致緩存擊穿,需要加鎖或使用雙寫策略。

常見實現方式:

  1. 數據庫更新時主動更新緩存Write-through Strategy

    • 在 **數據更新(新增、修改、刪除)**時,同時更新數據庫和緩存
      public void updateData(Data data) {databaseService.updateData(data); // 更新數據庫redisTemplate.opsForValue().set("cache:data:" + data.getId(), data); // 同步更新緩存
      }
      

    • 適用于數據變更不頻繁,且一致性要求較高的場景。
  2. 緩存淘汰(Cache Eviction)

    • 在數據庫更新后,刪除緩存,讓下一次查詢時重新加載數據:
      public void updateData(Data data) {databaseService.updateData(data); // 更新數據庫redisTemplate.delete("cache:data:" + data.getId()); // 刪除緩存
      }
      

    • 適用于緩存數據不是熱點,數據變更后不需要立即被查詢的情況。
  3. 訂閱數據庫變更Event-based Strategy

    • 使用 消息隊列(Kafka、RabbitMQ)Redis 訂閱/發布機制,監聽數據庫變更事件,變更后更新緩存。
  4. 分布式鎖(避免緩存并發寫入問題)

    • 解決多個請求同時更新緩存導致數據不一致的問題:
      RLock lock = redissonClient.getLock("cache:lock:data:" + data.getId());
      try {if (lock.tryLock(5, TimeUnit.SECONDS)) {databaseService.updateData(data);redisTemplate.opsForValue().set("cache:data:" + data.getId(), data);}
      } finally {lock.unlock();
      }
      

    • 適用于高并發寫入場景,防止緩存同時被多個請求覆蓋。
適用場景:

📌 訂單系統、支付系統、庫存管理等(數據必須實時更新,不能有延遲)。
📌 直播、彈幕系統(數據實時變化,需要確保一致性)。


總結:定期生成 vs. 實時生成

策略定期生成(定時更新)實時生成(即時更新)
數據實時性低(有一定延遲)高(數據庫更新即緩存更新)
數據庫壓力低(定期批量更新)高(頻繁更新緩存)
緩存命中率高(查詢時直接命中緩存)可能較低(某些情況需刪除緩存)
適用場景排行榜、統計數據、報表等訂單、庫存、支付等高一致性業務

總結

  • 定期生成(定時更新) 適用于數據變化不頻繁對實時性要求不高的場景,如排行榜、日志分析等。
  • 實時生成(即時更新) 適用于數據變化頻繁對一致性要求高的場景,如支付、庫存、訂單管理等。
  • 在實際應用中,可以結合兩種策略,例如:
    • 定期更新 + 變更觸發更新:大部分數據定期刷新,關鍵數據實時更新。
    • 讀時更新 + 寫時淘汰:查詢時自動更新緩存,寫入時刪除緩存,防止數據不一致。

合理選擇緩存更新策略,可以有效提升系統性能,降低數據庫壓力,并保證數據的一致性。

Redis 作為緩存,存儲空間有限,因此需要淘汰數據來保證新數據的存入。Redis 提供了多種緩存淘汰策略(Eviction Policy),用于決定哪些數據需要被刪除。下面介紹幾種常見的淘汰策略,包括它們的適用場景和優缺點。


緩存淘汰策略

1. 不淘汰策略

1.1 noeviction(拒絕寫入)

概念:

當 Redis 內存占滿時,不會刪除任何已有數據,而是直接返回錯誤,拒絕新的寫入請求。

適用場景:
  • 適用于嚴格不能丟數據的場景,如任務隊列(消息隊列)、金融交易等。
  • 適用于 Redis 作為純數據存儲而非緩存時。
優缺點:

? 數據不會被誤刪除,保證數據完整性。
? 可能導致寫入失敗,影響系統穩定性。


2. 基于 TTL(過期時間)的淘汰策略

2.1 volatile-lru(最近最少使用,TTL 限定)

概念:
  • 只淘汰**設置了過期時間(TTL)**的鍵。
  • 在這些鍵中,優先刪除最近最少使用(LRU, Least Recently Used)的數據。
適用場景:
  • 適用于部分數據可丟棄的場景,比如 session、短期緩存數據。
  • 適用于需要自動過期控制,但仍希望盡可能保留熱點數據的情況。
優缺點:

? 優先保留常用數據,減少緩存擊穿的概率。
? 如果大部分 key 沒有 TTL,可能導致 Redis 直接拒絕寫入(相當于 noeviction)。


2.2 volatile-ttl(優先淘汰即將過期的鍵)

概念:
  • 只淘汰**設置了過期時間(TTL)**的鍵。
  • 其中剩余壽命最短的鍵優先被刪除。
適用場景:
  • 適用于對數據有明確的生命周期需求的業務,如訂單緩存、驗證碼緩存等。
優缺點:

? 優先刪除即將過期的數據,保證短期緩存的更新。
? 可能誤刪仍然有價值的熱點數據。


3. 基于數據訪問頻率的淘汰策略

3.1 allkeys-lru(全局最近最少使用)

概念:
  • 無視 TTL,從所有鍵中(包括沒有設置 TTL 的鍵),優先淘汰最近最少使用的鍵。
適用場景:
  • 適用于熱點數據更新頻繁的場景,如推薦系統、排行榜、搜索結果緩存等。
優缺點:

? 可以確保常用數據長期保留,提高緩存命中率。
? 如果熱點數據突然減少訪問,可能會被錯誤淘汰。


3.2 allkeys-random(全局隨機淘汰)

概念:
  • 無視 TTL,在所有 key 中隨機刪除某些數據。
適用場景:
  • 適用于緩存數據均勻訪問,不需要特定優先級的場景。
優缺點:

? 簡單高效,減少淘汰策略的計算開銷。
? 不夠智能,可能淘汰熱點數據,降低緩存命中率。


4. 基于數據訪問頻次的淘汰策略

4.1 volatile-lfu(基于訪問頻率,TTL 限定)

概念:
  • 只淘汰設置了 TTL 的 key
  • 訪問次數最少的鍵優先被刪除(LFU, Least Frequently Used)。
適用場景:
  • 適用于需要根據訪問次數保留數據的業務,如熱點文章緩存、用戶歷史記錄等。
優缺點:

? 能夠長期保留高頻訪問數據,淘汰低頻數據。
? 如果大部分數據沒有 TTL,可能導致 Redis 拒絕寫入(類似 noeviction)。


4.2 allkeys-lfu(全局最不常使用淘汰)

概念:
  • 無視 TTL,從所有鍵中優先淘汰訪問次數最少的鍵
適用場景:
  • 適用于熱點數據訪問有明顯差異的情況,如新聞熱點推薦、熱門產品緩存等。
優缺點:

? 能保留長期熱點數據,提高緩存命中率。
? 短期熱點數據可能無法及時替換,導致數據更新滯后。


總結

策略機制適用場景優點缺點
noeviction拒絕寫入不能丟數據(消息隊列、金融)數據安全容易寫滿導致錯誤
volatile-lru僅淘汰 TTL 數據,LRU需自動過期,保留熱點數據減少緩存擊穿僅適用于部分數據有 TTL
volatile-ttl僅淘汰 TTL 數據,剩余壽命短的優先訂單緩存、驗證碼優先清理即將失效的緩存可能誤刪熱點數據
allkeys-lru全局 LRU 淘汰訪問頻率高的緩存(推薦系統)提高緩存命中率可能誤刪突然冷卻的熱點數據
allkeys-random隨機淘汰數據訪問均勻的緩存計算開銷小可能淘汰重要數據
volatile-lfu僅淘汰 TTL 數據,訪問最少的優先需要根據訪問頻率保留數據長期熱點數據保留僅適用于有 TTL 的 key
allkeys-lfu全局 LFU 淘汰熱點明顯的數據(新聞、直播)緩存命中率高短期熱點更新慢

如何選擇淘汰策略?

1. 數據不能丟失(消息隊列、金融)

? noeviction(拒絕寫入)

2. 僅淘汰過期數據(業務數據自動失效)

? volatile-lru(保留熱點)
? volatile-ttl(優先清理快過期數據)

3. 需要智能保留高頻訪問數據

? allkeys-lru(最近最少使用淘汰)
? allkeys-lfu(最少使用淘汰)

4. 訪問數據均勻,不關心淘汰順序

? allkeys-random(隨機刪除)

5. 業務需要權衡 LRU 和 LFU

  • 短期熱點多,選 LRU
  • 長期熱點多,選 LFU

結論

  • 如果數據有 TTL,且希望優先淘汰冷數據,選 volatile-lru / volatile-lfu
  • 如果所有數據都可以被淘汰,選 allkeys-lru / allkeys-lfu
  • 如果只允許寫滿后拒絕寫入,選 noeviction
  • 如果對淘汰規則無特別要求,選 allkeys-random

正確選擇淘汰策略,可以有效提高緩存命中率,降低數據庫壓力,保障系統穩定性。

常見緩存問題

在 Redis 中,緩存預熱、緩存穿透、緩存雪崩和緩存擊穿是常見的緩存問題。下面分別描述它們的概念及解決方案:


1. 緩存預熱(Cache Warming)

是什么?

緩存預熱是指在系統啟動或運行之前,提前將熱點數據加載到緩存中,以減少數據庫的查詢壓力,提高系統訪問速度。

如何解決?
  • 手動加載:在服務啟動時,手動將熱點數據寫入緩存。
  • 定時刷新:通過定時任務(如 Spring Task、Quartz 等)定期加載熱點數據到緩存。
  • 數據變更同步:監聽數據庫更新(如 MySQL binlog、Redis 訂閱發布機制),在數據變化時同步更新緩存。
  • 批量加載:使用 Redis 的 pipelinemset 命令批量寫入緩存,提高加載效率。

2. 緩存穿透(Cache Penetration)

是什么?

緩存穿透指的是大量請求查詢不存在的數據,導致每次請求都要查詢數據庫,緩存完全失效,給數據庫帶來巨大壓力。

如何解決?
  • 緩存空值:如果查詢的數據不存在,可以將空值(如 null{})存入緩存,并設置較短的過期時間,避免重復查詢數據庫。
  • 布隆過濾器(Bloom Filter):使用布隆過濾器提前判斷某個 key 是否可能存在,如果一定不存在,則直接返回,不查詢數據庫。
  • 參數校驗:在請求層對參數進行校驗,避免無效請求進入系統。
  • 限流與黑名單:對異常請求 IP 進行封禁或限流,避免惡意攻擊。

3. 緩存雪崩(Cache Avalanche)

是什么?

緩存雪崩指的是大量緩存同時失效,導致短時間內大量請求直接打到數據庫,造成數據庫壓力激增,甚至宕機。

如何解決?
  • 緩存過期時間隨機化:為緩存設置不同的過期時間,避免大量緩存同時失效,例如使用 TTL = 基礎時間 ± 隨機時間
  • 熱點數據提前預加載:在緩存即將過期前,主動刷新緩存,保證熱點數據始終可用。
  • 雙層緩存:使用 Redis + 本地緩存(如 Caffeine、Guava Cache),降低對 Redis 的依賴。
  • 流量削峰
    • 限流:使用限流算法(如令牌桶、漏桶)限制訪問速率。
    • 降級:當數據庫壓力過大時,返回默認值或降級處理。

4. 緩存擊穿(Cache Breakdown)

是什么?

緩存擊穿指的是某個熱點 key 突然失效,導致大量并發請求直接打到數據庫,造成數據庫短時間內壓力劇增。

如何解決?
  • 設置熱點數據永不過期:對于熱點數據,直接不設置過期時間,而是由業務邏輯主動更新緩存。
  • 互斥鎖(分布式鎖)
    • 當緩存失效時,多個請求只允許一個線程查詢數據庫并更新緩存,其他線程等待緩存更新完成后再讀取。
    • 具體實現:使用 SETNX(Redis 分布式鎖) 或 Redisson。
  • 提前刷新緩存
    • 通過異步線程提前更新即將過期的熱點緩存,防止突然失效。
    • 例如:使用 Redis + 過期監聽,在 key 即將過期前主動更新緩存。

總結

問題現象解決方案
緩存預熱緩存剛啟動時,沒有數據手動加載、定時刷新、監聽數據變更
緩存穿透查詢的 key 在數據庫中不存在,每次都查數據庫緩存空值、布隆過濾器、參數校驗、黑名單
緩存雪崩大量 key 同時失效,數據庫壓力激增過期時間隨機化、雙層緩存、限流、降級
緩存擊穿某個熱點 key 失效,大量請求打到數據庫熱點數據永不過期、分布式鎖、提前刷新

這四個緩存問題都是分布式系統中必須重點關注的,合理的緩存策略可以有效提升系統的性能和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/73182.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/73182.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/73182.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡:計算機網絡的分類

按分布范圍分類&#xff1a;廣域網&#xff0c;城域網&#xff0c;局域網&#xff0c;個域網 按傳輸技術分類&#xff1a;廣播式網絡&#xff0c;點對點網絡 按拓撲結構分類&#xff1a;總線型&#xff0c;環形&#xff0c;星形&#xff0c;網狀 按傳輸介質分類&#xff1a;…

解決pip安裝uv時下載速度慢

驗證優化效果 方案 1&#xff1a;臨時使用國內鏡像源&#xff08;推薦&#xff09; pip install uv -i https://pypi.tuna.tsinghua.edu.cn/simple 速度提升&#xff1a;鏡像源服務器位于國內&#xff0c;帶寬充足&#xff0c;通常可達 1-10MB/s 支持源列表&#xff1a; # 清…

SpringCloud Alibaba——入門簡介

一、是什么 &#xff08;1&#xff09;誕生 2018.10.31&#xff0c;Spring Cloud Alibaba 正式入駐了 Spring Cloud 官方孵化器&#xff0c;并在 Maven 中央庫發布了第一個版本 &#xff08;2&#xff09;介紹 &#xff08;3&#xff09;&#xff1f;何為必須組件 二、能干嘛…

Python完全指南:從基礎到實踐的編程藝術

引言&#xff1a;數字時代的瑞士軍刀 在人工智能與大數據浪潮中&#xff0c;Python如同編程世界的"瑞士軍刀"&#xff0c;以其優雅的語法和強大的生態征服全球開發者。本文將從語言哲學到實戰應用&#xff0c;為您展開Python編程的全景畫卷&#xff0c;揭示這門語言…

Docker 運行 GPUStack 的詳細教程

GPUStack GPUStack 是一個用于運行 AI 模型的開源 GPU 集群管理器。它具有廣泛的硬件兼容性&#xff0c;支持多種品牌的 GPU&#xff0c;并能在 Apple MacBook、Windows PC 和 Linux 服務器上運行。GPUStack 支持各種 AI 模型&#xff0c;包括大型語言模型&#xff08;LLMs&am…

完整例子和調用關系qt OpenGL

項目結構 首先&#xff0c;你需要在 Qt 項目中創建一個類&#xff0c;繼承自 QOpenGLWidget 來進行 OpenGL 渲染。文件結構如下&#xff1a; - main.cpp - MyOpenGLWidget.h - MyOpenGLWidget.cpp - vertex_shader.glsl - fragment_shader.glsl 1. main.cpp 這是 Qt 項目的入口…

VSCode 配置優化指南:打造極致高效的前端開發環境

VSCode 配置優化指南&#xff1a;打造極致高效的前端開發環境 一、基礎環境配置&#xff1a;讓開發更流暢 1. 性能優化設置 // settings.json {"files.autoSave": "afterDelay", // 自動保存&#xff08;延遲1秒&#xff09;"files.exclud…

源IP泄露后如何涅槃重生?高可用架構與自動化防御體系設計

一、架構層解決方案 1. 高防代理架構設計 推薦架構&#xff1a; 用戶 → CDN&#xff08;緩存靜態資源&#xff09; → 高防IP&#xff08;流量清洗&#xff09; → 源站集群&#xff08;真實IP隱藏&#xff09; ↑ Web應用防火墻&#xff08;WAF&#xff09; 實施要點&a…

【英偉達AI論文】多模態大型語言模型的高效長視頻理解

摘要&#xff1a;近年來&#xff0c;基于視頻的多模態大型語言模型&#xff08;Video-LLMs&#xff09;通過將視頻處理為圖像幀序列&#xff0c;顯著提升了視頻理解能力。然而&#xff0c;許多現有方法在視覺主干網絡中獨立處理各幀&#xff0c;缺乏顯式的時序建模&#xff0c;…

無障礙閱讀(Web Accessibility)NVDA打開朗讀查看器后,enter鍵不生效的原因

用NVDA測試Web Accessibility時&#xff0c;打開朗讀查看器&#xff0c;enter鍵會無效&#xff0c;而不打開測試器&#xff0c;就沒有問題&#xff0c;很大原因是被應用的元素不是可聚焦的&#xff0c;解決方法嘗試&#xff1a; 將標簽改為可聚焦的語義化標簽&#xff0c;如 b…

2Android中的AIDL是什么以及如何使用它

一、Android中的AIDL概述 AIDL&#xff08;Android Interface Definition Language&#xff09;是Android系統中用于定義和實現跨進程通信&#xff08;IPC&#xff09;接口的語言。它允許一個進程向另一個進程發送請求并獲取響應&#xff0c;是Android中實現進程間通信的一種重…

Python繪制數據分析中經典的圖形--列線圖

Python繪制數據分析中經典的圖形–列線圖 列線圖是數據分析中的經典圖形&#xff0c;通過背后精妙的算法設計&#xff0c;展示線性模型&#xff08;logistic regression 和Cox&#xff09;中各個變量對于預測結果的總體貢獻&#xff08;線段長短&#xff09;&#xff0c;另外&…

leetcode【面試經典150系列】(一)

目錄 121.買賣股票最佳時機 題目描述 示例 算法分析 代碼(python3) 122.買賣股票最佳時機II 題目描述 示例 算法分析 代碼&#xff08;python3&#xff09; 55.跳躍游戲 題目描述 示例 算法分析 代碼 45.跳躍游戲II 題目描述 示例 算法分析 代碼 121.買賣股票…

為什么會出現redis數據庫?redis是什么?

什么是 Redis? 為什么要用 Redis? 下面我將從 Redis 出現的背景、Redis 的解決方案個來回答。 1、Redis 出現的背景 互聯網的應用越來越多&#xff0c;例如社交網絡、電商、實時服務發展的十分迅速&#xff0c;這就導致了傳統技術棧&#xff08;如關系型數據庫&#xff09;…

Windows 11下Git Bash執行cURL腳本400問題、CMD/PowerShell不能執行多行文本等問題記錄及解決方案

問題 在Postman里可成功執行的POST請求&#xff1a; 找到Postman的Code 因為cURL基本上算是行業標準&#xff0c;所以Postman默認選中cURL&#xff0c;支持切換不同的開發語言&#xff1a; 點擊上圖右上角的復制按鈕&#xff0c;得到cURL腳本。 Windows 11家庭版&#xff…

Docker基礎入門(一)

初識Docker 什么是Docker Docker是一個快速交付應用、運行應用的技術&#xff1a; 可以將程序及其依賴、運行環境一起打包為一個鏡像&#xff0c;可以遷移到任意Linux操作系統運行時利用沙箱機制形成隔離容器&#xff0c;各個應用互不干擾啟動、移除都可以通過一行命令完成&…

容器編排革命:從 Docker Run 到 Docker Compose 的進化之路20250309

容器編排革命&#xff1a;從 Docker Run 到 Docker Compose 的進化之路 一、容器化部署的范式轉變 在 Docker 生態系統的演進中&#xff0c;容器編排正從“手動操作”走向“自動化管理”。根據 Docker 官方 2023 年開發者調查報告&#xff0c;78% 的開發者已采用 Docker Compo…

c++ 嵌入匯編的方式實現int型自增

x86/x86_64 實現 x86 平臺上&#xff0c;使用 LOCK XADD 指令來實現原子自增&#xff1a; #include <iostream>inline int atomic_increment_x86(int* value) {int result;__asm__ __volatile__("lock xaddl %1, %0": "m"(*value), "r"(…

區塊鏈與去中心化技術

區塊鏈與去中心化技術 核心進展 區塊鏈從加密貨幣&#xff08;如比特幣&#xff09;擴展至智能合約和供應鏈管理。以太坊2.0引入分片技術提升交易吞吐量&#xff0c;而零知識證明&#xff08;ZKP&#xff09;增強了隱私保護15。企業級應用如IBM的Food Trust平臺通過區塊鏈追蹤…

逐夢DBA:Linux環境下 MySQL 的卸載

1. 查看是否安裝過MySQL&#xff0c;如果不存在&#xff0c;則不顯示任何內容 rpm -qa | grep -i mysql # -i 忽略大小寫 2. 查看MySQL服務狀態 systemctl status mysqld.service 3. 關閉 mysql 服務 systemctl stop mysqld.service 4. 查看當前 mysql 卸載狀況 rpm -qa…