新闻详情

新闻详情

首页 / 资讯中心 / 详情

黑马点评之缓存工具封装

发布时间:2026/9/2 6:15:13来源:尧图网络
黑马点评之缓存工具封装
1.1缓存工具的定位和选择方法1和方法3配对起来解决一些常见的缓存问题方法2和方法4配对起来是为了解决热点key的。1.2设置逻辑过期时间方法和设置TTL过期时间public class CacheClient { private StringRedisTemplate stringRedisTemplate; public CacheClient(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate stringRedisTemplate; } public void set(String key, Object value, Long time, TimeUnit unit){ stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value),time,unit); } public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit){ //设置逻辑过期,把value封装到redisData对象里面去存就能诞生逻辑过期时间了 RedisData redisData new RedisData(); redisData.setData(value); redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time))); //plusSeconds是加上时间的unit是单位time是传进来的时间参数但是不能确定是秒所以需要用toSeconds去转一下 //写入Redis stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData),time,unit); }1.2.1设置TTL过期时间public void set(String key, Object value, Long time, TimeUnit unit){stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value),time,unit);}因为stringRedisTemplate要求的类型是string而传value的类型是Object所以需要把对象序列化为json字符串。1.2.2设置逻辑过期时间方法public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit){//设置逻辑过期,把value封装到redisData对象里面去存就能诞生逻辑过期时间了RedisData redisData new RedisData();redisData.setData(value);redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));//plusSeconds是加上时间的unit是单位time是传进来的时间参数但是不能确定是秒所以需要用toSeconds去转一下//写入RedisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData),time,unit);}1.3用缓存空值解决缓存击穿public R,ID R queryWithPassThrough( String keyPrefix, ID id, ClassR type, FunctionID,R dbFallback, Long time, TimeUnit unit){ String key CACHE_SHOP_KEY id;//把这个转为字符串方便使用前面标明cache shop 方便区分id //1.从redis查缓存 String shopJson stringRedisTemplate.opsForValue().get(key);//以店铺id做为key,这样就得到店铺的json字符串 //2.判断是否存在 if (StrUtil.isNotBlank(shopJson)) { //3.存在直接返回 return JSONUtil.toBean(shopJson, type);//R的类型是type所以反序列化这边放的是type } //判断命中的是否是空值 if(shopJson !null){ //返回一个错误信息 return null; } //4.不存在根据id查询数据库 R r dbFallback.apply(id);//因为范型这边的查数据库语句不好写不像idname这种数据库都有的字段所以要定义一个函数从外面传 //5.不存在返回错误 if (rnull) { //将空值写入redis stringRedisTemplate.opsForValue().set(key,,CACHE_NULL_TTL,TimeUnit.MINUTES); //返回错误信息 return null; } //6.存在写入redis this.set(key,r, time, unit); //这个时间注意应该是传的时间而不是直接写死的 //因为用的是opsForValue所以是value是string类型的所以后面的shop还得转为string //7.返回 return r; }因为是封装的缓存工具所以不确定返回值类型是什么所以要用泛型用R来代表返回值 ClassR type这个是泛型的推荐方便将来告诉具体是什么类型R的类型就是type。id的类型不一定是long类型的不能写死所以id的类型也不确定所以也要用泛型。 R r dbFallback.apply(id);因为范型这边的查数据库语句不好写不像idname这种数据库都有的字段所以要定义一个函数从外面传所以这里的代码是一个数据库查询的逻辑。因为是个有参有返回的函数所以用的是FunctiondbFallback是数据库的后备逻辑在这段代码里面的意思是先查redisredis查失败了才走它所以是后备逻辑。Shop shop cacheClient.queryWithPassThrough (CACHE_SHOP_KEY,id,Shop.class, this::getById,CACHE_SHOP_TTL,TimeUnit.MINUTES);1.4利用逻辑过期时间解决缓存击穿private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10); //创建一个线程池 public R,ID R queryWithLogicalExpire( String keyPrefix, ID id, ClassR type , FunctionID ,R dbFallback,Long time, TimeUnit unit){ String key keyPrefix id;//把这个转为字符串方便使用前面标明cache shop 方便区分id //1.从redis查缓存 String json stringRedisTemplate.opsForValue().get(key);//以店铺id做为key,这样就得到店铺的json字符串 //2.判断是否存在 if (StrUtil.isBlank(json)) { //3.存在直接返回 return null; } //4.命中需要先把json反序列化为对象 RedisData redisData JSONUtil.toBean(json, RedisData.class); R r JSONUtil.toBean((JSONObject) redisData.getData(), type); LocalDateTime expireTime redisData.getExpireTime(); //5.判断是否过期 if (expireTime.isAfter(LocalDateTime.now())){ //5.1.未过期直接返回店铺信息 return r; } //5.2.已过期需要缓存重建 //6.缓存重建 //6.1获取互斥锁 String lockKey LOCK_SHOP_KEY id; boolean isLock tryLock(lockKey); //6.2判断是否获取锁成功 if (isLock){ //TODO 6.3成功开启独立线程实现缓存重建 //注意获取锁成功应该再次检测redis缓存是否过期做DoubleCheck。如果存在则无需重建缓存 CACHE_REBUILD_EXECUTOR.submit(() -{ try { //重建缓存 //查询数据库 R r1 dbFallback.apply(id); //写入Redis this.setWithLogicalExpire(key,r1,time,unit); } catch (Exception e) { throw new RuntimeException(e); }finally { //释放锁 unLock(lockKey); } }); } //6.4.失败返回过期商铺信息 return r; }Shop shop cacheClient.queryWithLogicalExpire (CACHE_SHOP_KEY, id,Shop.class,this::getById,20L,TimeUnit.SECONDS);
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

为什么这个前端设计 Skill 让我眼前一亮:它先让 AI 知道,平庸是不合格的 2026/9/2 6:57:20

为什么这个前端设计 Skill 让我眼前一亮:它先让 AI 知道,平庸是不合格的

很多前端设计 prompt 的第一句都是:“你是一位资深 UI/UX 设计师。” frontend-design 不是这样写的。它让模型把自己当成一家小型设计工作室的负责人——这家工作室以独特的视觉识别出名,而眼前这位客户,已经拒绝过好…为什么这个前端设计 S…

阅读更多 →
从零构建VOC格式挖掘机数据集:采集、标注与YOLOv8训练实战 2026/9/2 6:57:20

从零构建VOC格式挖掘机数据集:采集、标注与YOLOv8训练实战

简介:本资源是一套面向计算机视觉初学者与工程实践者的挖掘机目标检测专用数据集,适用于YOLO、Faster R-CNN等主流检测模型的训练与验证,特别适配建筑工地安全监控、工程机械智能识别等工业场景。压缩包共1364个文件,含679张已标注…

阅读更多 →
HTML5 Canvas 的完整渲染链路-Day33 2026/9/2 6:57:20

HTML5 Canvas 的完整渲染链路-Day33

本文面向有 HTML / CSS / JavaScript 基础、想系统掌握 Canvas 的开发者。读完你将理解:Canvas 究竟是一块什么样的“画布”、一条绘图命令如何一步步变成屏幕上的像素,并能写出高性能的动画与可视化代码。 前置知识:会用浏览器开发者工具、能…

阅读更多 →
DATASPACE3D AI 开放能力:一句话,生成可预览、可编辑、可发布的 3D 场景 2026/9/2 6:57:20

DATASPACE3D AI 开放能力:一句话,生成可预览、可编辑、可发布的 3D 场景

DATASPACE3D 是面向 3D 产品展示、数字孪生、在线展厅与交互演示的 Web3D 可视化搭建平台。 开放能力要做的事很具体:把工作台接到 Cursor / Claude Code 等 Agent——说清意图,空间里就出现可预览的真实项目;不满意就进编辑器继续改。生成是…

阅读更多 →
Python学习--DAY7条件语句 2026/9/2 6:57:20

Python学习--DAY7条件语句

条件分支格式:a int(input(请输入a:\n)) b int(input(请输入b:\n)) if a>b:aab #执行语句需要空格b #同一条件下的执行语句应该对齐,否则语法不认 else:a #另一分支也需要与主分支对齐,执行语句也是多分…

阅读更多 →
成都大巴哪家最靠谱 2026/9/2 6:54:19

成都大巴哪家最靠谱

在成都的商务出行与旅游接驳领域,大巴服务的可靠性是所有用车方关注的核心问题。由于涉及多车型协同、临时变更响应、服务标准统一等多个环节,单纯依赖经验驱动的传统模式难以应对高复杂度任务。本文以成都路景车队的实践为样本,从行业痛点、…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞