Java延时定时刷新Redis缓存
延时定时刷新Redis缓存
一、背景
- 项目需求:订阅接收一批实时数据,每分钟最高可接收120万条数据,并且分别更新到redis和数据库中;而用户请求查询消息只是低频操作。
- 资源限制:由于项目预算有限,只有4台4C16G的主机用于消费处理这些消息;
- 需求容忍程度:当http请求查询消息时,可以接受查询到几秒钟内的数据,及延时一定时间的消息。
二、方案设计
- 缓存更新策略:先更新本地缓存,然后定时刷新到redis中
- 代码实现设计:
(1)技术选型:使用caffeine或者guava缓存管理工具
(2)代码设计:设置缓存过期时间,并在实现过期时的处理接口,在该接口中将本地缓存过期的key刷新到redis缓存中;
三、代码实现
- maven引用
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.9.3</version></dependency>
2.代码实现
- 定义接口 DelayedCache
package com.zzc.component.cache;
public interface DelayedCache<K, V> {V get(K key);void put(K key, V value);void remove(K key);}
- 定义抽象类 AbstractDelayedCache 实现通用本地缓存策略
package com.zzc.component.cache;import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Expiry;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;import java.util.concurrent.TimeUnit;public abstract class AbstractDelayedCache<K, V> implements DelayedCache<K, V> {/*** 延时刷新到redis的时间*/private final long delayMillis;private final int initialCapacity;private final int maximumSize;private final LoadingCache<K, V> LOCAL_CACHE;public AbstractDelayedCache(int initialCapacity, int maximumSize, long delayMillis) {this.initialCapacity = initialCapacity;this.maximumSize = maximumSize;this.delayMillis = delayMillis;LOCAL_CACHE = initLocalCache();}private LoadingCache<K, V> initLocalCache() {return Caffeine.newBuilder().expireAfter(new Expiry<K, V>() {@Overridepublic long expireAfterCreate(@NonNull K key, @NonNull V value, long currentTime) {return TimeUnit.MILLISECONDS.toNanos(delayMillis);}@Overridepublic long expireAfterUpdate(@NonNull K key, @NonNull V value, long currentTime, @NonNegative long currentDuration) {return currentDuration;}@Overridepublic long expireAfterRead(@NonNull K key, @NonNull V value, long currentTime, @NonNegative long currentDuration) {return currentDuration;}}).removalListener((key, value, cause) -> {switch (cause) {case EXPLICIT://当缓存项被显式地调用 invalidate 或 invalidateAll 方法删除时触发afterExplicit(key, value);break;case REPLACED://当一个新的值通过 put、replace 等方法替换现有的值时触发。afterReplaced(key, value);break;case COLLECTED://如果缓存使用了弱引用(weak keys 或 weak values)或软引用(soft values),并且这些引用的对象被垃圾回收器回收时触发。afterCollected(key, value);break;case EXPIRED://当缓存项达到其设定的有效期(TTL, TTI)而被自动移除时触发。afterExpired(key, value);break;case SIZE://当缓存项因为缓存大小超过限制(如最大容量或权重限制),根据驱逐策略(通常是 LRU、LFU 等)被移除时触发afterSize(key, value);break;default:break;}}).initialCapacity(initialCapacity).maximumSize(maximumSize).build(new CacheLoader<K, V>() {@Overridepublic @Nullable V load(@NonNull K key) throws Exception {return loadCache(key);}});}/*** 当缓存被显示调用 invalidate 或 invalidateAll 方法删除时触发* @param key* @param value*/protected abstract void afterExplicit(K key, V value);/*** 当缓存项被替换时触发* @param key* @param value*/protected void afterReplaced(K key, V value) {}/*** 如果缓存使用了弱引用(weak keys 或 weak values)或软引用(soft values),并且这些引用的对象被垃圾回收器回收时触发。* @param key* @param value*/protected void afterCollected(K key, V value) {}/*** 当缓存项达到其设定的有效期(TTL, TTI)而被自动移除时触发。* @param key* @param value*/protected abstract void afterExpired(K key, V value);/*** 当缓存项因为缓存大小超过限制(如最大容量或权重限制),根据驱逐策略(通常是 LRU、LFU 等)被移除时触发* @param key* @param value*/protected abstract void afterSize(K key, V value);/*** 初始化本地缓存数据,从远程获取* @param key*/protected abstract V loadCache(K key);@Overridepublic V get(K key) {return LOCAL_CACHE.get(key);}@Overridepublic void put(K key, V value) {LOCAL_CACHE.put(key, value);}@Overridepublic void remove(K key) {LOCAL_CACHE.invalidate(key);}}
- 继承实现缓存和redis的关系
package com.zzc.component.cache;
public class TestRedisCache extends AbstractDelayedCache<String, String> {/*** 初始缓存数量大小为 1000* 最大缓存数量 10000* 缓存过期时间 10000ms*/public TestRedisCache() {super(1000, 10000, 10000);}@Overrideprotected void afterExplicit(String key, String value) {//TODO 删除redis缓存 redisTemplate.del(key);}@Overrideprotected void afterExpired(String key, String value) {//TODO 更新到redis缓存 redisTemplate.setValue(key, value);}@Overrideprotected void afterSize(String key, String value) {//TODO 更新到redis缓存 redisTemplate.setValue(key, value);}@Overrideprotected String loadCache(String key) {//TODO 从redis缓存中获取key的valuereturn null;}
}
- Demo
package com.zzc.component.cache;
public class Demo {public static void main(String[] args) {TestRedisCache cache = new TestRedisCache();cache.put("key", "value");cache.get("key");cache.remove("key");}}相关文章:
Java延时定时刷新Redis缓存
延时定时刷新Redis缓存 一、背景 项目需求:订阅接收一批实时数据,每分钟最高可接收120万条数据,并且分别更新到redis和数据库中;而用户请求查询消息只是低频操作。资源限制:由于项目预算有限,只有4台4C16…...
智能硬件定位技术发展趋势
在科技飞速进步的当下,智能硬件定位技术作为众多领域的关键支撑,正沿着多元且极具创新性的路径蓬勃发展,持续重塑我们的生活与工作方式。 一、精度提升的极致追求 当前,智能硬件定位精度虽已满足诸多日常应用,但未来…...
全单模矩阵及其在分支定价算法中的应用
全单模矩阵及其在分支定价算法中的应用 目录 全单模矩阵的定义与特性全单模矩阵的判定方法全单模矩阵在优化中的核心价值分支定价算法与矩阵单模性的关系非全单模问题的挑战与系统解决方案总结与工程实践建议 1. 全单模矩阵的定义与特性 关键定义 单模矩阵(Unimo…...
DeepSeek 的创新融合:多行业应用实践探索
引言 在数字化转型的浪潮中,技术的融合与创新成为推动各行业发展的关键力量。蓝耘平台作为行业内备受瞩目的创新平台,以其强大的资源整合能力和灵活的架构,为企业提供了高效的服务支持。而 DeepSeek 凭借先进的人工智能技术,在自然…...
利用SkinMagic美化MFC应用界面
MFC(Microsoft Foundation Class)应用程序的界面设计风格通常比较保守,而且虽然MFC框架的控件功能强大且易于集成,但视觉效果较为朴素,缺乏现代感。尤其是MFC应用程序的设计往往以功能实现为核心,界面设计可能显得较为简洁甚至略显呆板,用户体验可能不如现代应用程序流畅…...
IMX6ULL的公板的以太网控制器(MAC)与物理层(PHY)芯片(KSZ8081RNB)连接的原理图分析(包含各引脚说明以及工作原理)
目录 什么叫以太网?它与因特网有何区别?公板实现以太网的原理介绍(MII/RMII协议介绍)公板的原理图下载地址公板中IMX6ULL处理器与MAC(以太网控制器)有关的原理图IMX6ULL处理器的MAC引脚说明1. **ENET1_TX_DATA0**2. **ENET1_TX_DATA1**3. **ENET1_TX_EN*…...
采用分布式部署deepseek
分布式部署DeepSeek涉及使用多个计算节点来加速模型训练或提升推理效率。下面是一个基本的指南,帮助您了解如何进行分布式部署。 1. 环境准备 硬件需求:确保您的集群环境中有足够的GPU资源,并且所有机器之间可以通过高速网络互联。软件依赖…...
Cloud: aws:network: limit 含有pps这种限制
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/troubleshooting-ena.html#statistics-ena 这个是调查网络问题的一个网页; 在里面,竟然含有pps这种限制:ethtool -S;其实是比较苛刻的安全相关的策略? [ec2-user ~]$ ethtool -S ethN NIC statistics:tx_timeout: …...
PaddlePaddle的OCR模型转onnx-转rknn模型_笔记4
一、PaddlePaddle的OCR模型转onnx 1、首先建立一个新的虚拟环境 conda create -n ppocr python3.10 -y conda activate ppocr 2、进入paddlepaddle官网输入以下指令安装paddlepaddle GPU版本 (我的cuda版本是11.8,根据你电脑装合适版本) pip instal…...
OpenHarmony 系统性能优化——默认关闭全局动画
笔者最近发现,关闭OpenHarmony全局动画,系统UI的响应速度会极大的提升 1.全局动画的开关由系统属性persist.sys.arkui.animationscale来控制,默认为1。也就是 动画缩放 1x 2.如果让persist.sys.arkui.animationscale默认为0,也就是关闭的状态…...
【Linux】Ubuntu Linux 系统——Node.js 开发环境
ℹ️大家好,我是练小杰,今天星期五了,同时也是2025年的情人节,今晚又是一个人的举个爪子!! 🙂 本文是有关Linux 操作系统中 Node.js 开发环境基础知识,后续我将添加更多相关知识噢&a…...
LC-搜索二维矩阵II、相交链表、反转链表、回文链表、环形链表、环形链表ll
搜索二维矩阵II 方法:从右上角开始搜索 我们可以从矩阵的右上角开始进行搜索。如果当前元素 matrix[i][j] 等于 target,我们直接返回 true。如果 matrix[i][j] 大于 target,说明 target 只能出现在左边的列,所以我们将列指针向左…...
小米平板怎么和电脑共享屏幕
最近尝试使用小米平板和电脑屏幕分屏互联 发现是需要做特殊处理的,需要下载一款电脑安装包:小米妙享 关于这个安装包,想吐槽的是: 没有找到官网渠道,是通过其他网络方式查到下载的 不附录链接,原因是因为地…...
Python elasticsearch客户端连接常见问题整理
python 访问 elasticsearch 在python语言中,我们一般使用 pip install elasticsearch 软件包,来访问es服务器。 正确用法 本地安装elasticsearch时,应指定与服务端相同的大版本号: pip install elasticsearch7.17.0然后就可以…...
目标检测IoU阈值全解析:YOLO/DETR模型中的精度-召回率博弈与工程实践指南
一、技术原理与数学本质 IoU计算公式: IoU \frac{Area\ of\ Overlap}{Area\ of\ Union} \frac{A ∩ B}{A ∪ B}阈值选择悖论: 高阈值(0.6-0.75):减少误检(FP↓)但增加漏检(FN↑…...
算法——数学建模的十大常用算法
数学建模的十大常用算法在数学建模竞赛和实际问题解决中起着至关重要的作用。以下是这些算法的具体信息、应用场景以及部分算法的C语言代码示例(由于篇幅限制,这里只给出部分算法的简要代码或思路,实际应用中可能需要根据具体问题进行调整和扩…...
Electron:使用electron-react-boilerplate创建一个react + electron的项目
使用 electron-react-boilerplate git clone --depth 1 --branch main https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name cd your-project-name npm install npm start 安装不成功 在根目录加上 .npmrc文件 内容为 electron_…...
在linux系统中安装Anaconda,并使用conda
系统 : ubuntu20.04 显卡:NVIDIA GTX1650 目录 安装Anaconda第一步:下载合适版本的Anconda1. 查看自己Linux的操作系统及架构命令:uname -a2. 下载合适版本的Anconda 第二步:安装Aanconda1. 为.sh文件设置权限2. 执行.sh文件2.1 .…...
渗透测试--文件包含漏洞
文件包含漏洞 前言 《Web安全实战》系列集合了WEB类常见的各种漏洞,笔者根据自己在Web安全领域中学习和工作的经验,对漏洞原理和漏洞利用面进行了总结分析,致力于漏洞准确性、丰富性,希望对WEB安全工作者、WEB安全学习者能有所帮助…...
Go入门之语言变量 常量介绍
func main(){var a int8 10var b int 5var c int 6fmt.Println("a", a, "b", b, "c", c)d : 10fmt.Printf("a%v leixing%T\n", d, d) } main函数是入口函数,fmt包有三个打印的函数Println,Print,Printf。第…...
告别龟速下载!手把手教你用最新淘宝镜像加速npm安装(附新旧域名切换指南)
极速开发实战:2024年npm国内镜像配置全攻略与避坑指南 每次执行npm install时盯着缓慢滚动的进度条,你是否也经历过那种焦灼?特别是在紧急修复生产环境bug时,每一秒的等待都像被无限拉长。作为国内开发者,我们完全没必…...
华为OD机试真题 新系统 2026-04-26 JavaGoC语言 实现【端口流量统计】
目录 题目 思路 Code 题目 给定一个整数数组 portRates,portRates[i] 表示该端口第 i 分钟端口流量速率(单位:bps)。 返回一个数组 ratesStat,ratesStat[i] 表示多少分钟以后出现比当前更大的流量速率,如果没有出现更大的流量速率,则值为 0。 输入描述:输入给定的整…...
别再死记寄存器了!图解STM32F407输入捕获:从信号跳变到CCR1存值的完整流程
STM32F407输入捕获实战:用视觉化思维理解信号捕获全流程 从脉冲信号到寄存器数值的奇妙旅程 想象一下,你正在观察一条跳动的脉搏线——每当信号从低电平跃升到高电平,就像心脏的一次跳动。STM32F407的输入捕获功能,本质上就是在记…...
RLHF-V:如何验证与改进大模型对齐中的奖励模型?
1. 项目概述:从“对齐”到“对齐对齐者”如果你在AI领域,特别是大语言模型(LLM)的微调与对齐方向上有所涉猎,那么“RLHF”这个词对你来说一定不陌生。RLHF,即基于人类反馈的强化学习,是让ChatGP…...
深蓝词库转换:20+输入法格式一键互通的终极解决方案
深蓝词库转换:20输入法格式一键互通的终极解决方案 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 你是否曾因为更换设备而不得不重新学习输入法…...
BBDown终极方案:专业级B站视频下载深度解析
BBDown终极方案:专业级B站视频下载深度解析 【免费下载链接】BBDown Bilibili Downloader. 一个命令行式哔哩哔哩下载器. 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown BBDown作为一款开源命令行工具,为Bilibili视频下载提供了企业级的解…...
如何用ROFL-Player解决英雄联盟回放分析难题:3步实现专业级比赛复盘
如何用ROFL-Player解决英雄联盟回放分析难题:3步实现专业级比赛复盘 【免费下载链接】ROFL-Player (No longer supported) One stop shop utility for viewing League of Legends replays! 项目地址: https://gitcode.com/gh_mirrors/ro/ROFL-Player 想象一下…...
Chapter 5:深度章 - AI 编程思维转变
Chapter 5:深度章 - AI 编程思维转变 学习目标 理解从传统开发到 AI Engineering 的角色重塑 掌握 SDD(规格驱动开发)的核心理念 理解从"写代码"到"设计系统"的思维转变 能够用新思维指导日常工作 一、工程师角色的重塑 1.1 传统开发中的工程师角色 …...
高性能硬字幕提取架构解析:基于GPU加速的实时OCR技术实现
高性能硬字幕提取架构解析:基于GPU加速的实时OCR技术实现 【免费下载链接】SubtitleOCR 快如闪电的硬字幕提取工具。仅需苹果M1芯片或英伟达3060显卡即可达到10倍速提取。A very fast tool for video hardcode subtitle extraction 项目地址: https://gitcode.com…...
人工智能核心—大语言模型技术解密,从入门到精通(全攻略)
技术导读:大语言模型是人工智能的核心引擎,OpenAI Agents SDK模型层正是AI智能体的大脑!本文将为你深度剖析大语言模型如何工作、API怎么使用、模型怎么切换,保证通俗易懂,让你零基础也能玩转大模型。话不多说…...
