【09】如何解决redis缓存穿透和缓存雪崩问题

您所在的位置:网站首页 redis集群存储数据策略 【09】如何解决redis缓存穿透和缓存雪崩问题

【09】如何解决redis缓存穿透和缓存雪崩问题

#【09】如何解决redis缓存穿透和缓存雪崩问题| 来源: 网络整理| 查看: 265

缓存穿透概述

缓存穿透是指客户端发送的请求在redis缓存和数据库中都无法查询到数据,如果有大量请求到来,那么redis无法被命中的情况下,大量的请求将会访问数据库,造成数据库崩溃。

缓存穿透的条件总结如下:

自身业务代码或者数据出现问题。 一些恶意攻击、 爬虫等造成大量空命中。 解决缓存穿透 缓存空对象

缓存空对象:假设有一个商品详情,当用户查询一个不存在的商品时,可以将这个商品的id作为key,一个空对象作为value写入缓存中,这样下次查询同样不存在的商品时,就可以从缓存中获取到这个空对象,而不是再次访问数据库。

public Product getProductById(int productId) {   String cacheKey = "product:" + productId;   // 从缓存中查询商品信息   Product cachedProduct = productCache.get(cacheKey, Product.class);      //如果缓存不为空直接返回   if (cachedProduct != null) {    return cachedProduct;   }   // 查询数据库获取商品信息,如果缓存为空查询数据库   Product product = productRepository.findById(productId);      if (product == null) {    // 如果数据库中也没有,将空对象缓存起来,设置一个较短的过期时间    productCache.put(cacheKey, NullProduct.INSTANCE, Duration.ofMinutes(5));   } else {    // 将商品信息缓存起来    productCache.put(cacheKey, product);   }   return product;  }  // 内部类表示空商品对象 private static class NullProduct extends Product {  // 空实现 }

需要注意的地方就是,任然可能有缓存穿透风险,因为没有用读写锁,仍然有可能在同一时间大量的请求同一时间打到数据库中。

布隆过滤器

布隆过滤器的核心思想是使用多个独立的哈希函数和一个位数组。当要添加一个元素到布隆过滤器中时,先经过多个哈希函数的计算得到多个哈希值,然后将对应的位数组位置标记为1。当要判断一个元素是否存在于布隆过滤器中时,同样进行多次哈希计算,检查对应的位数组位置是否都为1,若存在任意一个位置为0,则可以确定元素一定不存在于集合中,若全部位置都为1,则说明元素可能存在于集合中。

布隆过滤器

布隆过滤器

可以用redisson实现布隆过滤器

public static void main(String[] args) {   Config config = new Config();   config.useSingleServer().setAddress("redis://localhost:6379");   //构造Redisson   RedissonClient redisson = Redisson.create(config);   RBloomFilter bloomFilter = redisson.getBloomFilter("nameList");   //初始化布隆过滤器:预计元素为100000000L,误差率为3%,根据这两个参数会计算出底层的bit数组大小   bloomFilter.tryInit(100000000L, 0.03);   //将茄子插入到布隆过滤器中   bloomFilter.add("茄子");   //判断下面号码是否在布隆过滤器中   System.out.println(bloomFilter.contains("茄子1"));   System.out.println(bloomFilter.contains("茄子2"));   System.out.println(bloomFilter.contains("茄子3")); }

布隆过滤器在初始化的时候需要把所有的数据导入进去,每次新增数据需要往里边添加,但是修改和删除不能操作商品不能操作,只能重新初始化布隆过滤器。

「缓存失效(击穿)」

由于大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库,可能会造成数据库瞬间压力过大甚至挂掉,对于这种情况我们在批量增加缓存时最好将这一批数据的缓存过期时间设置为一个时间段内的不同时间。过期时间设置个随机数。

//设置一个过期时间(300到600之间的一个随机数) int expireTime = new Random().nextInt(300) + 300; 缓存雪崩概述和预防

缓存雪崩是指当缓存层出现故障、超负荷或宕机等情况时,大量的请求无法从缓存中获取到数据,导致这些请求直接打到后端存储层,造成存储层的负载激增,甚至可能导致存储层的宕机。

为了预防和解决缓存雪崩问题,可以采取以下几个方面的措施:

提高缓存层的可用性:使用高可用的缓存架构,如Redis Sentinel或Redis Cluster,确保缓存层能够提供稳定可靠的服务。 依赖隔离和限流:引入依赖隔离组件,如Sentinel或Hystrix,对后端的访问进行限流和熔断,防止大量请求打到后端存储层,避免存储层的过载。 缓存数据的过期时间设置:合理设置缓存数据的过期时间,避免所有缓存同时失效。可以采用随机的过期时间设置,避免大量缓存同时过期导致的雪崩效应。 缓存数据的热点分散:将热点数据分散到不同的缓存节点上,避免某一个缓存节点成为热点集中的地方,减轻单点压力。 缓存数据的预加载:提前将热门数据预先加载到缓存中,避免在缓存失效时大量请求同时打到后端存储层。 备份存储方案:在缓存失效时,可以考虑使用备份存储方案,如数据库或其他持久化存储,作为缓存失效时的后备方案。

重要的是在项目上线前进行缓存雪崩的演练和预案设定,了解应用和后端的负载情况,并制定相应的应对措施。及时监控缓存层和后端存储层的性能指标,以便及时发现和处理潜在的问题。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3