当前位置: 首页 > news >正文

封装Redis工具类

基于StringRedisTemplate封装一个缓存工具类,满足下列需求:

  • 方法1:将任意Java对象序列化为json并存储在string类型的key中,并且可以设置TTL过期时间

  • 方法2:将任意Java对象序列化为json并存储在string类型的key中,并且可以设置逻辑过期时间,用于处理缓

存击穿问题

  • 方法3:根据指定的key查询缓存,并反序列化为指定类型,利用缓存空值的方式解决缓存穿透问题

  • 方法4:根据指定的key查询缓存,并反序列化为指定类型,需要利用逻辑过期解决缓存击穿问题

将逻辑进行封装

CacheClient.java
@Slf4j
@Component
public class CacheClient {private final StringRedisTemplate stringRedisTemplate;public CacheClient(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}/*** 设置指定key对应的value值,使用JSON格式化字符串转换value对象为字符串进行存储。* @param key 要设置的key值* @param value 要设置的value值* @param time 过期时间* @param unit 过期时间的单位*/public void set(String key, Object value, Long time, TimeUnit unit) {stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);}/*** 设置具有逻辑过期时间的值到指定的 key 中。** @param key 要设置的 key* @param value 要设置的值* @param time 过期时间(单位:秒)* @param unit 过期时间的单位*/public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit) {// 创建 RedisData 对象,用于存储数据和过期时间RedisData redisData = new RedisData();redisData.setData(value);// 设置过期时间为当前时间加上传入的秒数redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));// 将 RedisData 对象转换成 JSON 字符串,并设置到指定的 key 中stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));}/*** 通过传递的参数进行查询操作,并使用PassThroughExecutor进行缓存查询和数据库查询的 fallback 处理。** @param keyPrefix 键的前缀* @param id        对应的ID值* @param type      查询结果的目标类型* @param dbFallback 数据库查询的 fallback 函数* @param time       缓存有效时间* @param unit       时间单位* @return 查询结果*/public <R, T> R queryWithPassThrough(String keyPrefix, T id, Class<R> type, Function<T, R> dbFallback, Long time, TimeUnit unit) {String key = keyPrefix + id;// 从Redis中查询缓存String json = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(json)) {return JSONUtil.toBean(json, type);}if (json != null) {return null;}R r = dbFallback.apply(id);if (r == null) {stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "", RedisConstants.CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}this.set(key, r, time, unit);return r;}private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);/*** 使用逻辑过期时间查询缓存* @param keyPrefix 键的前缀* @param id 对应的id* @param type 缓存对象的类型* @param dbFallback 数据库回退函数* @param time 过期时间* @param unit 时间单位* @return 查询结果*/public <R, T> R queryWithLogicalExpire(String keyPrefix, T id, Class<R> type, Function<T, R> dbFallback, Long time, TimeUnit unit) {// 从Redis查询缓存String key = keyPrefix + id;String json = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isBlank(json)) {return null;}// 判断过期时间RedisData redisData = JSONUtil.toBean(json, RedisData.class);R r = JSONUtil.toBean((JSONObject) redisData.getData(), type);LocalDateTime expireTime = redisData.getExpireTime();if (expireTime.isAfter(LocalDateTime.now())) {return r;}String locKey = LOCK_SHOP_KEY + id;boolean isLock = tryLock(locKey);if (isLock) {// 开启线程重建缓存CACHE_REBUILD_EXECUTOR.submit(() -> {try {R r1 = dbFallback.apply(id);this.setWithLogicalExpire(key, r1, time, unit);} catch (Exception e) {throw new RuntimeException(e);} finally {unLock(locKey);}});}return r;}/*** 尝试获取锁* @param key 锁的键值* @return 如果成功获取锁返回true,否则返回false*/private boolean tryLock(String key) {Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}/*** 删除指定key对应的value值** @param key 要删除的key值*/private void unLock(String key) {Boolean flag = stringRedisTemplate.delete(key);}}

相关文章:

封装Redis工具类

基于StringRedisTemplate封装一个缓存工具类&#xff0c;满足下列需求&#xff1a; 方法1&#xff1a;将任意Java对象序列化为json并存储在string类型的key中&#xff0c;并且可以设置TTL过期时间 方法2&#xff1a;将任意Java对象序列化为json并存储在string类型的key中&…...

使用 millis() 函数作为延迟的替代方法(电位器控制延迟时间)

接线图&#xff1a; 代码&#xff1a; unsigned long currentMillis 0; unsigned long previousMillis_LED1 0; unsigned long LED1_delay0; unsigned long previousMillis_LED2 0; unsigned long LED2_delay0; #define LED1 3 #define LED2 9 #define P1 A2 …...

MySQL之BETWEEN AND包含范围查询总结

一、时间范围 查询参数格式与数据库类型相对应时&#xff0c;between and包含头尾&#xff0c;否则依情况 当数据库字段中存储的是yyyy-MM-dd格式&#xff0c;即date类型&#xff1a; 用between and查询&#xff0c; 参数yyyy-MM-dd格式时&#xff0c;包含头尾&#xff0c;相当…...

4.3、Linux进程(2)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 通过系统调用创建进程--fork函数 结果是什么呢&#xff1f; 为什么会出来三个打印呢? 就是因为父进程调用了fork函数创建出了子进程的task_struct,但是一个进程不止task_struct&#xff0c;还有代码和数据&#xff0c;他们…...

element-ui组件输入框之放大镜(搜索图标)

element-ui组件输入框之放大镜(搜索图标 前言一、解决suffix-icon"el-icon-search"绑定事件问题 前言 在使用element-ui组件时想给输入框组件中的放大镜图标也就是搜索图标绑定事件&#xff0c;可以进行如下操作&#xff1a; 一、解决suffix-icon"el-icon-sear…...

[oeasy]python001_先跑起来_python_三大系统选择_windows_mac_linux

先跑起来 &#x1f94a; Python 什么是 Python&#xff1f; Python [ˈpaɪθɑ:n]是 一门 适合初学者 的编程语言 类库 众多 几行代码 就能 出 很好效果 应用场景丰富 在 各个应用领域 都有 行内人制作的 python 工具类库 非常专业、 好用 特别是 人工智能领域 pytho…...

吴恩达《机器学习》9-4-9-6:实现注意:展开参数、梯度检验、随机初始化

一、实现注意:展开参数 在上一个视频中&#xff0c;讨论了使用反向传播算法计算代价函数的导数。在本视频中&#xff0c;将简要介绍一个实现细节&#xff0c;即如何将参数从矩阵展开为向量。这样做是为了在高级最优化步骤中更方便地使用这些参数。 二、梯度检验 在神经网络中…...

软信天成:如何利用大数据提高客户体验?

当今社会&#xff0c;市场均势正在发生变化&#xff0c;消费者拥有更多的选择和更高的决定权&#xff0c;传统的市场营销技巧注重提高品牌认知度和吸引潜在客户&#xff0c;现在早已过时。经济不确定性弥漫&#xff0c;数字化转型仍是大多数企业的优先选择&#xff0c;新的竞争…...

Vue 路由缓存 防止路由切换数据丢失 路由的生命周期

在切换路由的时候&#xff0c;如果写好了一丢数据在去切换路由在回到写好的数据的路由去将会丢失&#xff0c;这时可以使用路由缓存技术进行保存&#xff0c;这样两个界面来回换数据也不会丢失 在 < router-view >展示的内容都不会被销毁&#xff0c;路由来回切换数据也…...

基于ubuntu20.04安装ros系统搭配使用工业相机

基于ubuntu20.04安装ros系统搭配使用工业相机 1. ROS系统安装部署1.1更新镜像源1.1.1 备份源文件1.1.2 更新阿里源1.1.3 更新软件源 1.2 ros系统安装1.2.1 添加ros软件源1.2.2 添加秘钥1.2.3 更新软件源1.2.4 配置及更换最佳软件源1.2.5 ROS安装1.2.6 初始化rosdep1.2.7 设置环…...

网络运维与网络安全 学习笔记2023.11.20

网络运维与网络安全 学习笔记 第二十一天 今日目标 交换网路径选择、Eth-Trunk原理、动态Eth-Trunk配置 Eth-Trunk案例实践、MUX VLAN原理、MUX VLAN配置 交换网路径选择 STP的作用 在交换网络中提供冗余/备份路径 提供冗余路径的同时&#xff0c;防止环路的产生 影响同网…...

银行业数据分析算法应用汇总

数据分析在银行业的应用及具体案例 一、欺诈检测二、客户细分三、风险建模四、营销优化五、信用评分六、客户流失预测七、推荐引擎八、客户生命周期价值预测 一、欺诈检测 欺诈检测即通过分析交易模式&#xff0c;检测可能的欺诈行为&#xff0c;主要有以下几个方面 1.跨机构开…...

搜索引擎trick:成为搜索高手的秘籍

诸神缄默不语-个人CSDN博文目录 文章目录 1. 搜索指令1.1 "完全匹配搜索"1.2 -1.3 site1.4 filetype1.5 * 模糊搜索1.6 intitle1.7 inurl1.8 related1.9 inanchor 2. 组合搜索技巧3. 搜索引擎的选择4. 使用高级搜索功能4.1 时间限定搜索4.2 语言限定搜索4.3 使用搜索…...

基于springboot实现冬奥会科普平台系统【项目源码+论文说明】计算机毕业设计

基于SpringBoot实现冬奥会科普平台系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理平台应运而生&…...

用C++标准库生成制定范围内的整数随机数

2023年11月22日&#xff0c;周三上午 #include <iostream> #include <random>int main() {std::random_device rd; // 随机设备&#xff0c;用于获取种子值std::mt19937 gen(rd()); // 使用 Mersenne Twister 引擎作为随机数生成器std::uniform_int_distribution&…...

使用ExLlamaV2量化并运行EXL2模型

量化大型语言模型(llm)是减少这些模型大小和加快推理速度的最流行的方法。在这些技术中&#xff0c;GPTQ在gpu上提供了惊人的性能。与非量化模型相比&#xff0c;该方法使用的VRAM几乎减少了3倍&#xff0c;同时提供了相似的精度水平和更快的生成速度。 ExLlamaV2是一个旨在从…...

【ARM AMBA AXI 入门 15 -- AXI-Lite 详细介绍】

请阅读【ARM AMBA AXI 总线 文章专栏导读】 文章目录 AXI LiteAXI-Full 介绍AXI Stream 介绍AXI Lite 介绍AXI Full 与 AIX Lite 差异总结AXI Lite AMBA AXI4 规范中包含三种不同的协议接口,分别是: AXI4-FullAXI4-LiteAXI4-Stream 上图中的 AXI FULL 和 AIX-Lite 我们都把…...

【开源】基于Vue.js的天然气工程业务管理系统的设计和实现

项目编号&#xff1a; S 021 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S021&#xff0c;文末获取源码。} 项目编号&#xff1a;S021&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四…...

SpringBoot : ch04 整合数据源

前言 Spring Boot 是当今最流行的 Java 开发框架之一&#xff0c;它以简洁、高效的特点帮助开发者快速构建稳健的应用程序。在实际项目中&#xff0c;涉及到数据库操作的需求时&#xff0c;我们需要对数据源进行整合。本文将重点介绍如何在 Spring Boot 中整合数据源&#xff…...

Docker Swarm总结

目录 1、swarm 理论基础 1.1 简介 1.2 节点架构 1.3 服务架构 1.4 服务部署模式 2、swarm 集群搭建 2.1 需求 ​2.2 克隆主机 2.3 启动5个docker宿主机 2.4 查看 swarm 激活状态 2.5 关闭防火墙 2.6 swarm 初始化 2.7 添加 worker 节点 2.8 添加 manager 节点 3…...

跨行业求职,AI工具如何帮你转型?2026年深度横评

测评说明&#xff1a;本文基于公开资料整理及产品实测体验&#xff0c;从多维度对适用于跨行业求职的AI工具进行横向对比&#xff0c;供求职者参考。一、摘要 2026年&#xff0c;跨行业求职已成为职场新常态。据统计&#xff0c;超过 40%的求职者 在职业生涯中会至少跨行业求职…...

基于UDP协议与TEA加密的QQ手机号反向查询系统架构解析

基于UDP协议与TEA加密的QQ手机号反向查询系统架构解析 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 在数字化身份验证与账号管理领域&#xff0c;手机号与QQ账号的关联查询一直是一个具有技术挑战性的课题。Phone2QQ项目通过逆向工…...

RISC-V向量扩展VMXDOTP技术解析与AI加速应用

1. RISC-V向量扩展VMXDOTP技术解析在AI计算硬件领域&#xff0c;我们正面临一个关键转折点。现代Transformer模型已经彻底改变了传统神经网络的计算模式——从规整的矩阵乘加运算转向了注意力机制、归一化和数据相关控制流的复杂交织。这种转变对硬件加速器提出了前所未有的灵活…...

事件驱动AI智能体开发:基于inngest/agent-kit构建可靠应用

1. 项目概述&#xff1a;为什么我们需要一个“事件驱动”的智能体开发框架&#xff1f; 最近在折腾AI应用开发&#xff0c;特别是想把大语言模型&#xff08;LLM&#xff09;的能力真正嵌入到业务流程里&#xff0c;而不是简单地做个聊天机器人。相信很多同行都遇到过类似的困…...

纯CSS动画状态检测终极指南:10个实用技巧让你告别JavaScript依赖

纯CSS动画状态检测终极指南&#xff1a;10个实用技巧让你告别JavaScript依赖 【免费下载链接】You-Dont-Need-JavaScript CSS is powerful, you can do a lot of things without JS. 项目地址: https://gitcode.com/gh_mirrors/yo/You-Dont-Need-JavaScript 在现代网页开…...

一名女性程序员迈向技术SEO的人生之书

这本书也就简简单单的看了3~5遍而已吧~ &#x1f604; 可以算是我人生谷底、重建信心、触底反弹的人生之书吧~ AEO&GEO当道&#xff0c;为什么要看SEO这本书&#xff1f; AEO 和 GEO的参考文档是 姚金刚的GEO白皮书 同时在youtube 上看 Nathan Gotch &#xff0c;他同时经…...

Arm Cortex-A75系统寄存器架构与编程实践

1. Cortex-A75系统寄存器架构概述Arm Cortex-A75作为一款高性能应用处理器核心&#xff0c;其系统寄存器设计体现了Armv8-A架构的精髓。系统寄存器是处理器内部用于控制和监控CPU运行状态的特殊寄存器&#xff0c;不同于通用寄存器&#xff0c;它们通常通过特定的指令&#xff…...

李飞飞做AI游戏,拿了4个亿

Jay 发自 凹非寺量子位 | 公众号 QbitAI 李飞飞又拿到钱了。5600万美元。 不是做世界模型的World Labs&#xff0c;是她联创的一家AI游戏公司&#xff0c;叫Astrocade。 你可能没听过这个名字。 我第一反应也是&#xff0c;等等&#xff0c;飞飞老师什么时候还搞了个游戏公司&a…...

AI编程助手指令统一工具brief:告别手动同步,实现智能管理

1. 项目概述&#xff1a;告别手动同步&#xff0c;一键统一你的AI编程助手如果你和我一样&#xff0c;日常开发中同时用着Claude Projects、GitHub Copilot和Cursor&#xff0c;那你肯定也遇到过这个烦人的问题&#xff1a;每个工具都有自己的“指令文件”&#xff0c;你得一遍…...

Tauri 2.0 + Next.js 16 桌面应用开发模板全解析

1. 项目概述与核心价值 如果你正在寻找一个能快速启动桌面应用开发的现代技术栈模板&#xff0c;那么 kvnxiao/tauri-nextjs-template 绝对值得你花时间研究。这个模板将两个看似不同领域的技术——用于构建现代Web前端的Next.js和用于创建跨平台桌面应用的Tauri——巧妙地结…...