【Redis 开发】缓存雪崩和缓存击穿

发布于:2024-05-01 ⋅ 阅读:(27) ⋅ 点赞:(0)

缓存雪崩

缓存雪崩是指在同一时间段,大量的缓存key同时失效或者Redis服务器宕机,导致大量请求到达数据库,带来巨大压力

解决方案

  1. 给不同的Key的TTL添加随机值

使得不容易在同一个时间段大量的缓存失效

  1. 利用Redis集群提高服务的可用性

如果Redis宕机了我们可以通过微服务将其他从服务器中调用及时弥补

  1. 给缓存业务添加降级限流策略

快要到达一个限制的时候进行降级,拒绝服务来保护缓存

  1. 给业务添加多级缓存

在其他层面也添加缓存,比如说nginx服务器中

缓存击穿

缓存击穿问题也叫热点key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效,无数的请求访问会在瞬间给数据库带来巨大的冲击

缓存重建业务复杂:从数据库操作写入缓存操作比较复杂,耗时可能会很多

解决方案:互斥锁逻辑过期

在这里插入图片描述

互斥锁

在这里插入图片描述
假若有很多线程进来,访问这个被击穿的数据,这是线程1先进来,拿到互斥锁,进行后面的数据库查询,写入缓存操作,其他线程在这个期间就不会拿到互斥锁,拿不到就会进行等待过一段时间重新在缓存中进行访问

缺点:性能低,线程需要进行不断地重复等待

逻辑时间

在这里插入图片描述

给一些及时地数据设置逻辑时间,不设置key的TTL时间

就是假如说我有一条数据,需要在一段时间内进行高并发的访问,那我们人工给他设置一个逻辑的过期时间,可以是永不过期,在使用完成后手动的将过期时间删除

在使用逻辑数据的时候同时也用到了互斥锁,但是处理不同,在线程获得互斥锁后,再创建一个新的线程来进行写入缓存的操作,这时候先返回过期的数据,其他没有拿到互斥锁的线程也是先返回过期数据

基于互斥锁解决缓存击穿问题

在服务层中创建互斥锁方法:

private boolean tryLock(String Key){
   Boolean flag = StringRedisTemplate.opsForValue().setIfAbsent(key,"1",10,TimeUnit.SECONDS);
return BooleanUtil.isTrue(flag);
}

这里是添加一个锁功能,其意思是使用setIfAbsent方法进行插入数据,这样其他的线程就不能够再次添加数据

private void unlock(String key){
    stringRedisTemplate.delete(key);
}

用来删除这个锁

基于逻辑过期方式解决缓存击穿问题

在这里插入图片描述
逻辑时间实例:(设置逻辑过期时间方法)

private void luoji(Long id,Long expireSeconds){
   //1.查询店铺信息
   Shop shop=getById(id);
   //2.封装逻辑过期时间
   RedisData redisdata=new RedisData();
   redisdata.setdata(shop);
   redisdata.setexpiretime(LocalDateTime.now().plusSeconds(expireSeconds));
   //写入Redis
   StringRedisTemplate.opsForValue().set(id,JSONUtil.toJsonStr(redisd ata));
}

网站公告

今日签到

点亮在社区的每一天
去签到