4-Redis篇-4

简介: 本文详解Redis三大核心问题:缓存雪崩(大量key同时失效,需加随机过期时间)、热点数据保障(采用LFU淘汰策略)、分布式锁实现(基于SETNX,解决死锁、超时、归一、可重入及阻塞等问题),并附实战应用案例。

16- 什么是缓存雪崩 ? 怎么解决 ?

缓存雪崩/缓存失效 指的是大量的缓存在同一时间失效,大量请求落到数据库 导致数据库瞬间压力飙升。

造成这种现象的 原因是,key的过期时间都设置成一样了。

解决方案是,key的过期时间引入随机因素

17- 数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的数据都是热点数据 ?

配置Redis的内容淘汰策略为LFU算法 , 这样会把使用频率较低的数据淘汰掉 , 留下的数据都是热点数据

18- Redis分布式锁如何实现 ?

Redis分布式锁主要依靠一个SETNX指令实现的 , 这条命令的含义就是“SET if Not Exists”,即不存在的时候才会设置值。

只有在key不存在的情况下,将键key的值设置为value。如果key已经存在,则SETNX命令不做任何操作。

这个命令的返回值如下。

  • 命令在设置成功时返回1。
  • 命令在设置失败时返回0。

假设此时有线程A和线程B同时访问临界区代码,假设线程A首先执行了SETNX命令,并返回结果1,继续向下执行。而此时线程B再次执行SETNX命令时,返回的结果为0,则线程B不能继续向下执行。只有当线程A执行DELETE命令将设置的锁状态删除时,线程B才会成功执行SETNX命令设置加锁状态后继续向下执行

Boolean isLocked = stringRedisTemplate.opsForValue().setIfAbsent(PRODUCT_ID, "binghe");

当然我们在使用分布式锁的时候也不能这么简单, 会考虑到一些实际场景下的问题 , 例如 :

  1. 死锁问题在使用分布式锁的时候, 如果因为一些原因导致系统宕机, 锁资源没有被释放, 就会产生死锁解决的方案 : 上锁的时候设置锁的超时时间 Boolean isLocked = stringRedisTemplate.opsForValue().setIfAbsent(PRODUCT_ID, "binghe", 30, TimeUnit.SECONDS);
  2. 锁超时问题如果业务执行需要的时间, 超过的锁的超时时间 , 这个时候业务还没有执行完成, 锁就已经自动被删除了其他请求就能获取锁, 操作这个资源 , 这个时候就会出现并发问题 , 解决的方案 :
  1. 引入Redis的watch dog机制, 自动为锁续期
  2. 开启子线程 , 每隔20S运行一次, 重新设置锁的超时时间
  1. 归一问题如果一个线程获取了分布式锁, 但是这个线程业务没有执行完成之前 , 锁被其他的线程删掉了 , 又会出现线程并发问题 , 这个时候就需要考虑归一化问题就是一个线程执行了加锁操作后,后续必须由这个线程执行解锁操作,加锁和解锁操作由同一个线程来完成。为了解决只有加锁的线程才能进行相应的解锁操作的问题,那么,我们就需要将加锁和解锁操作绑定到同一个线程中,可以使用ThreadLocal来解决这个问题 , 加锁的时候生成唯一标识保存到ThreadLocal , 并且设置到锁的值中 , 释放锁的时候, 判断线程中的唯一标识和锁的唯一标识是否相同, 只有相同才会释放
public class RedisLockImpl implements RedisLock{
 @Autowired
 private StringRedisTemplate stringRedisTemplate;
 private ThreadLocal<String> threadLocal = new ThreadLocal<String>();
 @Override
 public boolean tryLock(String key, long timeout, TimeUnit unit){
     String uuid = UUID.randomUUID().toString();
     threadLocal.set(uuid);
     return stringRedisTemplate.opsForValue().setIfAbsent(key, uuid, timeout, unit);
 }
 @Override
 public void releaseLock(String key){
     //当前线程中绑定的uuid与Redis中的uuid相同时,再执行删除锁的操作
     if(threadLocal.get().equals(stringRedisTemplate.opsForValue().get(key))){
       stringRedisTemplate.delete(key);   
     }
 }
}
  1. 可重入问题当一个线程成功设置了锁标志位后,其他的线程再设置锁标志位时,就会返回失败。还有一种场景就是在一个业务中, 有个操作都需要获取到锁, 这个时候第二个操作就无法获取锁了 , 操作会失败例如 : 下单业务中, 扣减商品库存会给商品加锁, 增加商品销量也需要给商品加锁 , 这个时候需要获取二次锁第二次获取商品锁就会失败 , 这就需要我们的分布式锁能够实现可重入实现可重入锁最简单的方式就是使用计数器 , 加锁成功之后计数器 + 1 , 取消锁之后计数器 -1 , 计数器减为0 , 真正从Redis删除锁
public class RedisLockImpl implements RedisLock{
 @Autowired
 private StringRedisTemplate stringRedisTemplate;
 private ThreadLocal<String> threadLocal = new ThreadLocal<String>();
 private ThreadLocal<Integer> threadLocalInteger = new ThreadLocal<Integer>();
 @Override
 public boolean tryLock(String key, long timeout, TimeUnit unit){
     Boolean isLocked = false;
     if(threadLocal.get() == null){
         String uuid = UUID.randomUUID().toString();
      threadLocal.set(uuid);
         isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key, uuid, timeout, unit);
     }else{
         isLocked = true;   
     }
     //加锁成功后将计数器加1
     if(isLocked){
         Integer count = threadLocalInteger.get() == null ? 0 : threadLocalInteger.get();
         threadLocalInteger.set(count++);
     }
     return isLocked;
 }
 @Override
 public void releaseLock(String key){
     //当前线程中绑定的uuid与Redis中的uuid相同时,再执行删除锁的操作
     if(threadLocal.get().equals(stringRedisTemplate.opsForValue().get(key))){
         Integer count = threadLocalInteger.get();
         //计数器减为0时释放锁
         if(count == null || --count <= 0){
           stringRedisTemplate.delete(key);      
         }
     }
 }
}
  1. 阻塞与非阻塞问题在使用分布式锁的时候 , 如果当前需要操作的资源已经加了锁, 这个时候会获取锁失败, 直接向用户返回失败信息 , 用户的体验非常不好 , 所以我们在实现分布式锁的时候, 我们可以将后续的请求进行阻塞,直到当前请求释放锁后,再唤醒阻塞的请求获得分布式锁来执行方法。具体的实现就是参考自旋锁的思想, 获取锁失败自选获取锁, 直到成功为止 , 当然为了防止多条线程自旋带来的系统资料消耗, 可以设置一个自旋的超时时间 , 超过时间之后, 自动终止线程 , 返回失败信息

19- 你的项目中哪里用到了分布式锁

在我最近做的一个项目中 , 我们在任务调度的时候使用了分布式锁

早期我们在进行定时任务的时候我们采用的是SpringTask实现的 , 在集群部署的情况下, 多个节点的定时任务会同时执行 , 造成重复调度 , 影响运算结果, 浪费系统资源

这里为了防止这种情况的发送, 我们使用Redis实现分布式锁对任务进行调度管理 , 防止重复任务执行

后期因为我们系统中的任务越来越多 , 执行规则也比较多 , 而且单节点执行效率有一定的限制 , 所以定时任务就切换成了XXL-JOB , 系统中就没有再使用分布式锁了

相关文章
|
2月前
|
Java 应用服务中间件 Maven
5-微服务篇-1
本文详解SpringBoot核心机制:①自动装配原理——通过@SpringBootApplication→@EnableAutoConfiguration→AutoConfigurationImportSelector→spring.factories加载条件化配置类;②启动流程三阶段:初始化、上下文创建、自动配置;③常用起步依赖、配置文件类型(properties/YAML)及加载优先级;④四种运行方式。
|
2月前
|
存储 NoSQL 算法
4-Redis篇-2
本文详解Redis集群架构与核心机制:采用哨兵集群(1主2从+3哨兵)保障高可用;对比主从复制、哨兵、Cluster分片三大方案;解析主从同步的全量/增量复制流程;说明Cluster基于16384哈希槽的分片存储原理;简述MULTI/EXEC等事务命令及实际使用情况。(239字)
|
2月前
|
Linux API 数据安全/隐私保护
OpenClaw怎么部署?OpenClaw 阿里云/本地Win11/MacOS/Linux部署教程+千问/百炼Coding Plan API配置全指南
OpenClaw(曾用名Clawdbot、Moltbot)作为2026年开源AI智能体领域的标杆工具,凭借“本地优先、全场景自动化、多模型兼容”的核心优势,成为个人与轻量团队提升效率的首选。它无需复杂编程,仅通过自然语言指令,即可完成文件管理、代码生成、网页抓取、办公协同等重复性任务,所有数据可本地存储,隐私安全性拉满。其核心价值在于打破传统AI“只说不做”的局限,实现“指令输入-任务拆解-执行落地”的完整闭环。
832 10
|
2月前
|
存储 缓存 NoSQL
4-Redis篇-1
本文详解Redis在项目中的三大应用:热点缓存、业务数据存储(如验证码、排行榜)及分布式锁;涵盖5种基础数据类型、RDB/AOF双持久化机制、惰性+定期混合过期策略,以及8种内存淘汰策略。
|
2月前
|
SQL 前端开发 Java
【分层架构】Spring MVC三层架构 / DDD领域驱动四层架构 / 微服务分布式架构(DAO/Mapper/Repository/Service/Controller/Manager)
本文系统解析Java企业级分层架构(Controller/Service/Manager/Repository/DAO/Mapper),阐明各层职责边界、设计原则与典型误区,强调单一职责、依赖倒置、关注点分离等核心思想,助力构建高内聚、低耦合、易维护的可扩展系统。
877 11
|
4月前
|
机器学习/深度学习 算法 自动驾驶
基于YOLOv8模型的行人车辆多目标检测计数与跟踪系统
本研究基于YOLOv8模型,针对智能交通与公共安全需求,开展行人车辆多目标检测、计数与跟踪技术研究。通过融合YOLOv8高精度检测与DeepSORT稳定跟踪,实现复杂场景下目标的实时定位、统计与轨迹追踪,提升交通管理效率与公共安全保障能力,推动智慧城市发展。
|
4月前
|
人工智能 自然语言处理 供应链
深度揭秘 RPA:从录屏脚本到智能员工,它的进化之路有多惊艳?
RPA机器人是能自动处理重复性工作的“数字员工”,通过模拟人工操作,实现数据录入、报表填报等任务的自动化。它非实体、不需编程,广泛应用于金融、制造、医疗等领域,提升效率、降低错误。未来,AI赋能的RPA将更智能、普惠,推动人机协同新变革。(239字)
1081 1
|
4月前
|
人工智能 自然语言处理 监控
告别无效加班!2026 企业高效 Agent 工具 TOP5,跨系统操作零门槛
Agent工具正成为企业降本增效的核心利器。2025年全球市场规模突破2000亿美元,中国占比达40%。从电商运营到财务对账,实在智能·实在Agent凭借“一句话生成流程”、跨系统操作与自主纠错能力,实现效率飞跃,是企业智能化升级的优选方案。
831 1
|
4月前
|
人工智能 自然语言处理 监控
个人 / 企业 / 科研全覆盖!2025 智能体盘点,5 款工具适配全职场需求
AI智能体正从辅助工具进化为“数字同事”,实在Agent凭借一句话生成流程、跨平台操作和高稳定性,成为企业降本增效的得力助手。本文盘点2025年5款实用智能体,助力职场人高效办公。
1039 10
|
5月前
|
人工智能 自然语言处理 供应链
电商运营需频繁跨平台操作?实在 Agent 能否实现 “一键自动化”?
RPA(机器人流程自动化)并非物理机器人,而是模拟人类操作的“数字员工”。它通过自动化重复性工作,如数据录入、报表处理等,解放人力,提升效率。从财务对账到人力资源管理,RPA已广泛应用于各行各业。随着AI加持,第三代RPA如实在Agent具备视觉识别与自然语言理解能力,实现“说句话就能干活”的智能自动化。它不是替代人类,而是让人专注创造与决策,成为数字化转型的核心力量。
315 1