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。第…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
