尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
redis--007
一、逻辑过期解决缓存击穿缓存击穿含义热点高频访问的缓存 key 过期大量并发请求同时涌向数据库。逻辑过期核心思想Redis 不设置真实的过期删除时间把过期时间保存在缓存 value 内部就算数据逻辑上过期依旧返回旧缓存数据后台异步去更新缓存用户请求不会等待数据库查询。业务执行流程根据商铺 id 查询 Redis 缓存如果缓存未命中直接返回结果结束。逻辑过期方案需要提前预热热点数据存入 Redis不会自动访问数据库加载。缓存命中读取 value 内部存储的逻辑过期时间未过期直接返回缓存中的业务数据已逻辑过期尝试获取互斥锁获取锁成功开启独立后台线程由后台线程访问数据库更新 Redis 缓存并写入新的逻辑过期时间更新完成释放锁主线程直接返回旧缓存不等待更新完成获取锁失败直接返回旧缓存数据优缺点✅优点并发性能高用户请求不会阻塞。 ⚠️缺点会短暂返回过期旧数据数据短暂不一致必须提前预热热点 key。private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10); public Shop queryWithLogicalExpire(Long id) { //查ID String shopJson stringRedisTemplate.opsForValue().get(cache:shop id); //存在返回不存在查数据库 if(StrUtil.isBlank(shopJson)) { Shop shop JSONUtil.toBean(shopJson, Shop.class); return shop; } //Json反序列话为对象 RedisData redisData JSONUtil.toBean(shopJson, RedisData.class); JSONObject data (JSONObject) redisData.getData(); Shop shop JSONUtil.toBean(data, Shop.class); LocalDateTime expireTime redisData.getExpireTime(); //判断过期 if (expireTime.isAfter(LocalDateTime.now())) { return shop; } String lockKey LOCK_SHOP_KEY id; boolean b tryLock(lockKey); if (b) { CACHE_REBUILD_EXECUTOR.submit(()-{ try { this.saveShop2Redis(id,20L); } catch (Exception e) { throw new RuntimeException(e); } finally { unlock(lockKey); } }); } return shop; }对比互斥锁方案互斥锁让请求阻塞等待新数据数据一致性更好但并发能力差。二、缓存三大问题回顾表格问题现象主流解决思路缓存穿透查询数据库不存在的数据缓存不生效请求直达 DB缓存空值、布隆过滤器缓存击穿热点 key 失效大量并发打数据库互斥锁、逻辑过期缓存雪崩大量缓存 key 集中同时过期压力全部落到数据库过期时间打散随机、Redis 集群、多级缓存三、缓存工具封装需求梳理基于StringRedisTemplate封装通用缓存工具4 个方法分工普通存入缓存Java 对象转为 JSON 存入 Redis设置真实 TTL 物理过期时间。用于普通业务缓存。逻辑过期存入对象包装内部记录逻辑过期时间Redis 本身不设置过期时间。专门用于处理缓存击穿。普通查询缓存读取缓存反序列化缓存查询不到时往 Redis 存入空值并设置短 TTL解决缓存穿透。逻辑过期查询缓存完整执行逻辑过期整套流程判断内部过期时间过期就异步更新缓存返回旧数据解决缓存击穿。Component 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) { //设置逻辑过期 RedisData redisData new RedisData(); redisData.setData(value); redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time))); stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData), time); } public R, ID R queryWithPassThrough( String keyPrefix, ID id, ClassR type, FunctionID, R dbFallback, Long time, TimeUnit unit ) { String key keyPrefix id; //查ID String json stringRedisTemplate.opsForValue().get(key); //存在返回不存在查数据库 if (StrUtil.isNotBlank(json)) { return JSONUtil.toBean(json, type); } if (json ! null) { return null; } R byId dbFallback.apply(id); //数据库结果 if (byId null) { //将空值写入redis stringRedisTemplate.opsForValue().set(key, , 10, TimeUnit.MINUTES); return null; } this.set(key, byId, time, unit); return byId; } 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; //查ID String json stringRedisTemplate.opsForValue().get(key); //存在返回不存在查数据库 if (StrUtil.isBlank(json)) { return JSONUtil.toBean(json, type); } //Json反序列话为对象 RedisData redisData JSONUtil.toBean(json, RedisData.class); JSONObject data (JSONObject) redisData.getData(); R r JSONUtil.toBean(data, type); LocalDateTime expireTime redisData.getExpireTime(); //判断过期 if (expireTime.isAfter(LocalDateTime.now())) { return r; } String lockKey LOCK_SHOP_KEY id; boolean b tryLock(lockKey); if (b) { 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(lockKey); } }); } return r; } private boolean tryLock(String key) { Boolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, 10, TimeUnit.MINUTES); return BooleanUtil.isTrue(flag); } private void unlock(String key) { stringRedisTemplate.delete(key); } }
RELATED

相关推荐

PADS 中添加泪滴

PADS 中添加泪滴

对于绝大多数的常规PCB设计,无论你是2层板、4层板还是更复杂的多层板,都建议给导线与过孔或引脚的连接处添加泪滴。不过,更严谨的说法是:这不是一个强制性的“硬性规则”,而是一项性价比极高的“最佳实践”。我们可以从…

📅 2026/9/26 1:23:10
G-Helper 完整指南:免费单文件华硕笔记本控制工具,三分钟学会性能模式与风扇曲线

G-Helper 完整指南:免费单文件华硕笔记本控制工具,三分钟学会性能模式与风扇曲线

G-Helper 完整指南:免费单文件华硕笔记本控制工具,三分钟学会性能模式与风扇曲线 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix,…

📅 2026/9/26 3:02:06
涉密企业向国外申请专利必须过保密审查

涉密企业向国外申请专利必须过保密审查

一、技术在中国研发,出国申请专利前少了一道关一家企业在中国研发了一项技术,想在美国和欧洲申请专利保护。直接找了国外代理机构提交了申请,没做任何国内手续。后来回国想补申请中国专利,被国知局告知:该技术向外国申…

📅 2026/9/28 6:27:16
MORE NEWS

更多资讯

📰

微信社群机器人开发指南:从协议解析到企业微信实战

1. 微信社群机器人开发概述微信社群机器人是一种基于微信生态的自动化工具,能够帮助群主或管理员高效管理微信群。这类机器人通常具备自动回复、关键词触发、内容推送、数据统计等功能,广泛应用于电商客服、知识付费、社群运营等场景。在实际开发中&…

📰

金融AI安全治理:从成本中心到增长引擎的转型

1. 金融AI收入增长背后的安全治理逻辑金融行业正在经历一场由AI技术驱动的深刻变革。去年某国际银行通过AI风控系统将信贷审批效率提升40%,同时降低15%的坏账率——这个典型案例揭示了安全治理与AI创收的共生关系。当算法模型开始直接处理客户的资金流时&#xff0c…

📰

互联网医院解决方案:在线问诊系统与AI智慧分诊开发

1. 互联网医院解决方案概述互联网医院正在重塑传统医疗服务的交付模式。这套在线问诊系统源码AI智慧分诊APP开发方案,为医疗机构提供了从患者接入到诊疗服务的全流程数字化解决方案。核心价值在于通过技术手段突破时空限制,将三甲医院的优质医疗服务延伸…

📰

蒙特卡洛方法实战CartPole:从回报设计到策略改进的完整落地

CartPole 这个环境几乎是每个接触强化学习的人绕不开的第一道坎。倒立摆本身不复杂:一根杆子铰接在小车上,小车左右移动,目标是让杆子别倒。但真动手写代码的时候,很多人会卡在同一个地方——策略到底怎么评估?回报怎么…

📰

微信社群机器人开发指南:从技术选型到合规实践

1. 微信社群机器人开发概述微信社群机器人是一种基于微信生态的自动化工具,能够模拟人类在微信群中的交互行为,实现自动回复、消息管理、数据统计等功能。这类机器人通常通过微信官方接口或第三方技术方案实现,主要服务于社群运营、客户服务、…

📰

多模态大模型中的System 2认知架构与工程实践

1. 多模态大模型中的System 2认知架构解析当GPT-4V能够看着一张破损自行车图片说"需要更换链条"时,它真的理解机械原理吗?这触及了当前多模态大模型最关键的认知鸿沟——感知能力(System 1)与真实推理(Syste…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬