Spring-Cache替換Keys為Scan—負優化?

背景

使用ORM工具是往往會配合緩存框架實現三級緩存提高查詢效率,spring-cache配合redis是非常常規的實現方案,如未做特殊配置,@CacheEvict(allEntries = true) 的批量驅逐方式,默認使用keys的方式查詢歷史緩存列表而后delete,而keys是阻塞式的命令,cache的dbsize越大,效率越低進而形成redis慢查詢。而使用scan增量式迭代指令,配合自動游標批量掃描緩存匹配的緩存key,是一種非阻塞的方案,一般認為更適合用于大規模數據集的遍歷,因為它不會像 keys 那樣一次性加載所有的鍵,可能在性能上更具優勢。

現狀

某項目線上積累數據緩存80萬個key,使用spring-cache(2.7.x)+redis(6.0)作為緩存框架,redis監控中,頻繁出現keys慢日志

問題

改造springboot-cache配置,將keys替換為scan,貌似是一種替代keys減少慢日志的最優解,那到底能否提高效率呢,或者能否帶來其他改變?

結論

在一定數據量的緩存系統中,如本系統dbsize為80萬左右,使用scan替換keys能顯著減少redis慢日志,但讓redis的cpu驟增。這使得系統應對突發問題時會變得更加脆弱,優化顯得入不敷出。

實踐

更新方法

多數AI的QA或者線上搜索的"替換springboot-cache keys指令為scan"實現方式都是片面的,為什么呢,也許現實證明確實沒有必要這么更新所以答案就更加模糊。當然了,實踐是檢驗真理的唯一標準,我們嘗試一下更新。(spring-boot-starter-data-redis version=2.7.x)

@Slf4j
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport { //其他@Override和@Bean參考網絡或自己實現// ……/*** 配置一個CacheManager才能使用@Cacheable等注解*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {log.info("cacheManager(RedisConnectionFactory redisConnectionFactory):" + redisConnectionFactory);return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory)// 全局緩存配置.cacheDefaults(redisCacheConfiguration(20 * 60))// 指定特殊緩存過期時間.withCacheConfiguration("sys:config", redisCacheConfiguration(7 * 60))//指定scan匹配key作為驅逐查詢方式               .cacheWriter(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory, BatchStrategies.scan(5000))).transactionAware().build();}}

重點改動就在于這里的nonLockingRedisCacheWriter,至于scan的size=5000,是一個權衡的考慮,設置10000時,實踐發現庫夠大時scan的速度較慢,可能超過20毫秒;設置過小,游標搜索次數又會明顯增多,所以沒有一個合理的選擇。

主要就是定義這個CacheManager然后必須加入cacheWriter,根本不需要單獨寫Writer復雜實現或者僅寫個Writer實現也不在CacheManager中配置(都沒配置關聯上怎么可能生效)。

驗證更新后的指令執行日志如下(觀察sys:setting::*):

#之前
1745380521.036415 [2 192.1.5.172:57514] GET aodc:to-client
1745380521.044084 [0 192.1.5.165:49754] GET aodc:to-client
1745380521.118468 [0 192.1.5.145:64743] KEYS sys:setting::*
1745380521.122180 [0 192.1.5.145:64743] DEL sys:setting::get-values-by-name:ces_equipment_code_blacklist sys:setting::get-value-by-name:hex_msg_for_equipment_list
1745380521.130366 [0 192.1.5.145:64743] HGET user:online-info \xe9\x99\x88\xe6\xac\xa3\xe6\xac\xa3
1745380521.134822 [0 192.1.5.145:64743] HGET user:online-info \xe9\x99\x88\xe6\xac\xa3\xe6\xac\xa3
1745380521.140906 [2 192.1.5.172:57514] GET aodc:to-client
#之后
1745381648.269224 [2 192.1.5.172:57514] SCAN 462 MATCH ocpp:to-equip:*
1745381648.270222 [2 192.1.5.172:57514] SCAN 158 MATCH ocpp:to-equip:*
1745381648.271283 [2 192.1.5.172:57514] SCAN 830 MATCH ocpp:to-equip:*
1745381648.273144 [0 192.1.5.165:49673] SCAN 0 match ocpp:to-equip:*
1745381648.273730 [2 192.1.5.172:57514] SCAN 897 MATCH ocpp:to-equip:*
1745381648.271348 [0 192.1.5.145:49669] SCAN 0 match sys:setting::* count 10000
1745381648.274556 [0 192.1.5.145:49669] DEL sys:setting::get-values-by-name:evcs_anhui_monitor_operator sys:setting::get-values-by-name:amap_operator sys:setting::get-values-by-name:evcs_hubei_monitor_operator sys:setting::get-value-by-name:hex_msg_for_equipment_list sys:setting::get-values-by-name:evcs_lianlian_monitor_operator sys:setting::get-values-by-name:evcs_hunan_loudi_operator sys:setting::get-values-by-name:evcs_cqgw_monitor_operator sys:setting::get-values-by-name:evcs_jilin_monitor_operator sys:setting::get-value-by-name:ces_order_curve_period_seconds sys:setting::get-values-by-name:evcs_anhuishenran_operator sys:setting::get-value-by-name:evcs_result_verify_sign_switch sys:setting::get-values-by-name:evcs_guizhou_monitor_operator sys:setting::get-values-by-name:ces_equipment_code_blacklist sys:setting::get-value-by-name:cec102_special_format_operators
1745381648.275050 [2 192.1.5.172:57514] SCAN 993 MATCH ocpp:to-equip:*

看到keys已替換為scan并進行緩存清除操作。
?

更新效果

在更新上線后,這一段時間內,確實未再出現明顯多的KEYS慢指令,似乎朝著一個非常完美的方向發展。

但是,千萬不要大意,處理監控慢日志,還需要查看其他資源情況,這里就如“結論”中提到的,發布該更新后CPU竟然突增了,而且居高不下。

這里簡單做個分析:

keys雖然阻塞,每次幾十甚至上百毫秒完成一次key匹配和驅逐,但是流程簡單,對系統實質影響不高,對資源占用影響不大;而使用scan后,是非阻塞的游標輪詢,緩存系統中,總key越多,游標需要輪詢的次數就越多,當scan size越小,可能影響越大,這無形中加大了對資源的占用。

當然,這僅限當前項目,可能基于緩存數量、并發量、驅逐頻率、緩存命中率等因素影響,替換keys為scan優化整體效果權衡表現不佳,更多的是需要自行實踐,尋找最佳的方案,目前推薦的方案是,禁用@CacheEvict(allEntries = true),指定key來驅逐緩存,這要求查詢操作能指定對應key,是業務層的另一種優化方案這里就暫不討論。

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

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

相關文章

【N8N】Docker Desktop + WSL 安裝過程(Docker Desktop - WSL update Failed解決方法)

背景說明: 因為要用n8n,官網推薦這個就下載了,然后又是一堆卡的安裝問題記錄過程。 1. 下載安裝包 直接去官網Get Docker | Docker Docs下載 下載的是第一個windows - x86_64. (*下面那個beta的感覺是測試版) PS&am…

RT Thread 發生異常時打印輸出cpu寄存器信息和棧數據

打印輸出發生hardfault時,當前棧十六進制數據和cpu寄存器信息 在發生 HardFault 時,打印當前棧的十六進制數據和 CPU 寄存器信息是非常重要的調試手段。以下是如何實現這一功能的具體步驟和示例代碼。 1. 實現 HardFault 處理函數 我們需要在 HardFault 中捕獲異常上下文,…

【安裝neo4j-5.26.5社區版 完整過程】

1. 安裝java 下載 JDK21-windows官網地址 配置環境變量 在底下的系統變量中新建系統變量,變量名為JAVA_HOME21,變量值為JDK文件夾路徑,默認為: C:\Program Files\Java\jdk-21然后在用戶變量的Path中,添加下面兩個&am…

android jatpack Compose 多數據源依賴處理:從狀態管理到精準更新的架構設計

Android Compose 多接口數據依賴管理:ViewModel 狀態共享最佳實踐 📌 問題背景 在 Jetpack Compose 開發中,經常遇到以下場景: 頁面由多個獨立接口數據組成(如 Part1、Part2)Part2 的某些 UI 需要依賴 P…

面試之消息隊列

消息隊列場景 什么是消息隊列? 消息隊列是一個使用隊列來通信的組件,它的本質就是個轉發器,包含發消息、存消息、消費消息。 消息隊列怎么選型? 特性ActiveMQRabbitMQRocketMQKafka單機吞吐量萬級萬級10萬級10萬級時效性毫秒級…

GStreamer 簡明教程(十一):插件開發,以一個音頻生成(Audio Source)插件為例

系列文章目錄 GStreamer 簡明教程(一):環境搭建,運行 Basic Tutorial 1 Hello world! GStreamer 簡明教程(二):基本概念介紹,Element 和 Pipeline GStreamer 簡明教程(三…

Linux kernel signal原理(下)- aarch64架構sigreturn流程

一、前言 在上篇中寫到了linux中signal的處理流程,在do_signal信號處理的流程最后,會通過sigreturn再次回到線程現場,上篇文章中介紹了在X86_64架構下的實現,本篇中介紹下在aarch64架構下的實現原理。 二、sigaction系統調用 #i…

華為OD機試真題——簡易內存池(2025A卷:200分)Java/python/JavaScript/C++/C/GO最佳實現

2025 A卷 200分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C、C語言、GO六種語言的最佳實現方式! 本文收錄于專欄:《2025華為OD真題目錄全流程解析/備考攻略/經驗…

騰訊一面面經:總結一下

1. Java 中的 和 equals 有什么區別?比較對象時使用哪一個 1. 操作符: 用于比較對象的內存地址(引用是否相同)。 對于基本數據類型、 比較的是值。(8種基本數據類型)對于引用數據類型、 比較的是兩個引…

計算機網絡中的DHCP是什么呀? 詳情解答

目錄 DHCP 是什么? DHCP 的工作原理 主要功能 DHCP 與網絡安全的關系 1. 正面作用 2. 潛在安全風險 DHCP 的已知漏洞 1. 協議設計缺陷 2. 軟件實現漏洞 3. 配置錯誤導致的漏洞 4. 已知漏洞總結 舉例說明 DHCP 與網絡安全 如何提升 DHCP 安全性 總結 D…

2025 年導游證報考條件新政策解讀與應對策略

2025 年導游證報考政策有了不少新變化,這些變化會對報考者產生哪些影響?我們又該如何應對?下面就為大家詳細解讀新政策,并提供實用的應對策略。 最引人注目的變化當屬中職旅游類專業學生的報考政策。以往,中專學歷報考…

【物聯網】基于LORA組網的遠程環境監測系統設計(ThingsCloud云平臺版)

演示視頻: 基于LORA組網的遠程環境監測系統設計(ThingsCloud云平臺版) 前言:本設計是基于ThingsCloud云平臺版,還有另外一個版本是基于機智云平臺版本,兩個設計只是云平臺和手機APP的區別,其他功能都一樣。如下鏈接: 【物聯網】基于LORA組網的遠程環境監測系統設計(機…

SQL 函數進行左邊自動補位fnPadLeft和FORMAT

目錄 1.問題 2.解決 方式1 方式2 3.結果 1.問題 例如在SQL存儲過程中,將1 或10 或 100 長度不足的時候,自動補足長度。 例如 1 → 001 10→ 010 100→100 2.解決 方式1 SELECT FORMAT (1, 000) AS FormattedNum; SELECT FORMAT(12, 000) AS Form…

Nacos簡介—2.Nacos的原理簡介

大綱 1.Nacos集群模式的數據寫入存儲與讀取問題 2.基于Distro協議在啟動后的運行規則 3.基于Distro協議在處理服務實例注冊時的寫路由 4.由于寫路由造成的數據分片以及隨機讀問題 5.寫路由 數據分區 讀路由的CP方案分析 6.基于Distro協議的定時同步機制 7.基于Distro協…

中電金信聯合阿里云推出智能陪練Agent

在金融業加速數智化轉型的今天,提升服務效率與改善用戶體驗已成為行業升級的核心方向。面對這一趨勢,智能體與智能陪練的結合應用,正幫助金融機構突破傳統業務模式,開拓更具競爭力的創新機遇。 在近日召開的阿里云AI勢能大會期間&…

十分鐘恢復服務器攻擊——群聯AI云防護系統實戰

場景描述 服務器遭遇大規模DDoS攻擊,導致服務不可用。通過群聯AI云防護系統的分布式節點和智能調度功能,快速切換流量至安全節點,清洗惡意流量,10分鐘內恢復業務。 技術實現步驟 1. 啟用智能調度API觸發節點切換 群聯系統提供RE…

LLM量化技術全景:GPTQ、QAT、AWQ、GGUF與GGML

01 引言 本文介紹的是在 LLM 討論中經常聽到的各種量化技術。本文的目的是提供一步一步的解釋和代碼,讓大家可以自己使用這些技術來壓縮模型。 閑話少說,我們來研究一下吧! 02 Quantization 量化是指將高精度數字轉換為低精度數字。低精…

IP的基礎知識以及相關機制

IP地址 1.IP地址的概念 IP地址是分配給連接到互聯網或局域網中的每一個設備的唯一標識符 也就是說IP地址是你設備在網絡中的定位~ 2.IP版本~ IP版本分為IPv4和IPv6,目前我們最常用的還是IPv4~~但是IPv4有個缺點就是地址到現在為止,已經接近枯竭~~&…

本地使用Ollama部署DeepSeek

以下是在本地使用Ollama部署DeepSeek的詳細教程,涵蓋安裝、修改安裝目錄、安裝大模型以及刪除大模型的操作步驟。 安裝Ollama 1. 系統要求 確保你的系統滿足以下條件: 操作系統:macOS、Linux或者Windows。足夠的磁盤空間和內存。 2. 安裝…

開源項目實戰學習之YOLO11:ultralytics-cfg-datasets-Objects365、open-images-v7.yaml文件(六)

👉 點擊關注不迷路 👉 點擊關注不迷路 👉 點擊關注不迷路 medical - pills.yaml 通常用于配置與醫學藥丸檢測任務相關的參數和信息 Objects365.yaml 用于配置與 Objects365 數據集相關信息的文件。Objects365 數據集包含 365 個不同的物體類別…