Java缓存穿透、击穿、雪崩解决方案

这篇具有很好参考价值的文章主要介绍了Java缓存穿透、击穿、雪崩解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java缓存穿透、击穿、雪崩解决方案

在互联网高并发的场景下,对于数据库查询频率高的数据,为了提高查询效率,常常会采用缓存技术进行优化。然而,缓存技术也会带来一些问题,比如缓存穿透、缓存击穿和缓存雪崩等。

缓存穿透

当我们从缓存中查询一个不存在的数据时,请求就会穿透缓存直接查询数据库,这样就会导致缓存无法起到应有的作用,并且大量的查询请求会直接打到数据库上,造成了数据库压力的增加,甚至会导致宕机等问题。

解决方案

可以使用布隆过滤器(Bloom Filter)来解决缓存穿透问题,它是一种快速判断某个数据是否存在的数据结构。具体步骤如下:

  1. 在缓存层增加布隆过滤器模块,将所有可能存在的数据先存储在布隆过滤器中;
  2. 当一个查询请求进来时,先通过布隆过滤器进行判断,如果该数据肯定不存在,则直接返回;
  3. 如果该数据可能存在,则再去缓存中查找,如果缓存中不存在,则继续去数据库中查找,并将该数据放入缓存中。

代码实践

我们可以使用Google Guava库中的BloomFilter类来实现布隆过滤器。示例代码如下:

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterDemo {

    private static final int capacity = 1000000; // 预计元素数量
    private static final double false_positive_rate = 0.01; // 允许的误判率

    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity, false_positive_rate);

    public static void main(String[] args) {
        // 将所有可能存在的数据存放到布隆过滤器中
        for (int i = 0; i < capacity; i++) {
            bloomFilter.put(i);
        }

        // 查询一个不存在的数据
        int testNum = -1;
        if (!bloomFilter.mightContain(testNum)) {
            System.out.println("该数据肯定不存在");
            return;
        }

        // 查询一个存在的数据
        int existNum = 999999;
        if (bloomFilter.mightContain(existNum)) {
            System.out.println("该数据可能存在");
            // TODO: 去缓存中查找,如果缓存中不存在则去数据库中查找
        }
    }
}

缓存击穿

在高并发场景下,当某个热点数据失效时,大量查询请求会直接打到数据库上,造成了数据库压力的增加,甚至会导致宕机等问题。

解决方案

可以使用分布式锁解决缓存击穿问题。具体步骤如下:

  1. 查询数据前,先使用分布式锁对该数据进行加锁;
  2. 如果此时有大量的查询请求进来,则只有一个请求能够获得锁并去查询数据库;
  3. 其他请求则等待锁释放后再从缓存中获取数据。

代码实践

我们可以使用Redis的分布式锁来实现分布式锁。示例代码如下:

import redis.clients.jedis.Jedis;

public class RedisLockDemo {

    private static final String REDIS_LOCK_KEY = "redis_lock_key";
    private static final int EXPIRE_TIME = 60; // 锁的过期时间为60秒

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        String requestId = String.valueOf(System.currentTimeMillis()); // 请求标识,用于释放锁时判断是否是同一请求
        boolean lockSuccess = false;
        try {
            // 加锁
            String result = jedis.set(REDIS_LOCK_KEY, requestId, "NX", "EX", EXPIRE_TIME);
            if ("OK".equals(result)) {
                lockSuccess = true;
                // TODO: 去数据库中查询数据,并将数据存入缓存中
            } else {
                // 未获取到锁,等待一段时间后重新尝试获取锁
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            if (lockSuccess && requestId.equals(jedis.get(REDIS_LOCK_KEY))) {
                jedis.del(REDIS_LOCK_KEY);
            }
            jedis.close();
        }
    }
}

缓存雪崩

在高并发场景下,当某个时间段内大量的缓存失效时,所有查询请求都会直接打到数据库上,造成了数据库压力的极度增加,甚至会导致宕机等问题。

解决方案

可以采用多级缓存策略来解决缓存雪崩问题。具体步骤如下:

  1. 分为多个层级的缓存,包括本地缓存、分布式缓存等;
  2. 针对不同的缓存层级,设置不同的过期时间,较短的过期时间设置在高层级的缓存中,较长的过期时间设置在低层级的缓存中;
  3. 当请求进来时,先从低层级的缓存中查找,如果存在数据则直接返回;如果不存在,则逐级向高层级的缓存查询,遇到有效的缓存则返回,并将数据存入低层级的缓存中。

代码实践

我们可以使用Spring Boot框架中的Cache注解以及Redis作为分布式缓存来实现多级缓存策略。示例代码如下:

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
@CacheConfig(cacheNames = "goods")
public class GoodsService {

    @Cacheable(key = "#id", unless = "#result == null")
    public Goods getGoodsById(int id) {
        // TODO: 查询数据库获取商品信息
        return new Goods(id, "商品" + id, BigDecimal.valueOf(100));
    }
}

在上述代码中,我们使用了@Cacheable注解,同时指定了缓存名称为"goods",并根据id设置缓存的key。在方法调用时,会先从缓存中查找是否存在对应的数据,如果存在则直接返回;如果不存在,则会调用方法体内的逻辑去数据库中查询数据,并将查询结果存入缓存中。由于我们使用了unless参数来判断返回的结果是否为空,因此当查询结果为null时,不会将对应的数据存入缓存中,避免了缓存雪崩问题。

此外,我们还需要在配置文件中设置缓存的过期时间,并将Redis作为分布式缓存。示例配置如下:

spring:
  cache:
    type: redis # 使用Redis作为分布式缓存
    redis:
      time-to-live: 60s # 过期时间为60秒

总结

针对缓存穿透、击穿和雪崩问题,我们可以采用布隆过滤器、分布式锁和多级缓存策略等技术手段来进行优化。在实际项目中,需要根据具体情况选择合适的解决方案,并进行适当的调整和配置,以达到最佳的性能和稳定性。文章来源地址https://www.toymoban.com/news/detail-417999.html

到了这里,关于Java缓存穿透、击穿、雪崩解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • redis中缓存雪崩,缓存穿透,缓存击穿的原因以及解决方案

    在redis中,新,旧数据交替时候,旧数据进行了删除,新数据没有更新过来,造成在高并发环境下,大量请求查询redis没有数据,直接查询mysql,造成mysql的压力骤增,给mysql造成极大的压力,造成一连串的后续异常反应。 1.大多数系统设计者 考虑用加锁 (最多的解决方案)或

    2024年02月15日
    浏览(39)
  • redis实战-缓存三剑客穿透击穿雪崩解决方案

    缓存穿透 :缓存穿透是指客户端请求的 数据在缓存中和数据库中都不存在 ,这样缓存永远不会生效,这些请求都会打到数据库, 造成数据库压力 ,也让缓存没有发挥出应有的作用 缓存空对象 当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时

    2024年02月11日
    浏览(34)
  • Redis中的缓存穿透、雪崩、击穿的原因以及解决方案

    是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。 我们可以简单的

    2024年02月12日
    浏览(32)
  • 【Redis从入门到进阶】第 6 讲:缓存雪崩、击穿、穿透场景与解决方案

    本文已收录于专栏 🍅《Redis从入门到进阶》🍅    本专栏开启,目的在于帮助大家更好的掌握学习 Redis ,同时也是为了记录我自己学习 Redis 的过程,将会从基础的数据类型开始记录,直到一些更多的应用,如缓存击穿还有分布式锁以及 Redis 持久化等。希望大家有问题也可

    2023年04月12日
    浏览(25)
  • Redis缓存雪崩、穿透、击穿原因分析和解决方案,附Redis管道使用技巧

    先给大家附上其他几篇文章,感兴趣的自行开车导航 Redis过期策略和持久化机制全面揭秘,教你如何合理配置 【深入浅出Redis 一】从版本特性到数据类型到线程模型,带你了解Redis的核心特性和应用场景! 一次redis OOM问题分析解决,rdbtools安装分析redis内存 Redis管道(pipelin

    2024年02月16日
    浏览(33)
  • 探讨Redis缓存问题及解决方案:缓存穿透、缓存击穿、缓存雪崩与缓存预热(如何解决Redis缓存中的常见问题并提高应用性能)

    Redis是一种非常流行的开源缓存系统,用于缓存数据以提高应用程序性能。但是,如果我们不注意一些缓存问题,Redis也可能会导致一些性能问题。在本文中,我们将探讨Redis中的一些常见缓存问题,并提供解决方案。 缓存穿透指的是当一个请求尝试访问一个不存在于缓存中的

    2024年02月03日
    浏览(49)
  • redis的缓存穿透,缓存并发,缓存雪崩,缓存问题及解决方案

    缓存穿透 问题原因 解决方案 缓存并发 缓存雪崩 缓存失效时间设置一致导致的。 解决方案: 1)方案一 2)方案二 如何设计一个缓存策略,缓存热点数据?

    2024年02月21日
    浏览(29)
  • 缓存雪崩、缓存击穿、缓存穿透原因及解决办法

    缓存雪崩是指在缓存中的大量数据在同一个时刻全部过期,导致原本这些可以由缓存中间件处理的高并发请求,一下子全部打到数据库,导致数据库服务器崩溃的一种现象。那么出现缓存雪崩的原因可以有①:缓存中间件宕机。②:缓存中大部分key都设置了相同的时间,导致

    2024年02月08日
    浏览(37)
  • Redis 如何解决缓存雪崩、缓存击穿、缓存穿透难题

    Redis 作为一门热门的缓存技术,引入了缓存层,就会有缓存异常的三个问题,分别是缓存击穿、缓存穿透、缓存雪崩。我们用本篇文章来讲解下如何解决! 缓存击穿 : 指的是缓存中的某个热点数据过期了,但是此时大量的并发请求访问这个key的值,此时因为缓存过期无法从

    2024年02月14日
    浏览(32)
  • [Redis]缓存穿透、缓存击穿、缓存雪崩问题及解决方法

    缓存穿透就是指在高并发的情况下大量的请求去查询一个不存在于缓存中的数据,导致这些请求都直接访问数据库,给数据库造成压力。例如:我存储在缓存中的key是数字类型(123),但是网络攻击者频繁地用字符串(abc)去获取缓存。导致永远都无法命中缓存,请求最终都

    2024年02月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包