Redis 应用实践:缓存预热与缓存穿透解决方案

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

一、简介

1.1 简介

Redis是一个用于数据缓存、消息代理、持久化存储的内存型数据库。Redis的特点是高性能、高并发、支持丰富的数据类型,可以实现多种应用场景。

1.2 缓存预热 穿透

缓存预热是在系统开始运行之前,将数据加入缓存中。这样在后续的请求中,可以直接从缓存中读取数据,提高了系统的性能和响应速度。

缓存穿透是指查询一个不存在的数据,这会导致大量请求直接打到数据库上,影响数据库的性能。缓存穿透可以通过在缓存层增加布隆过滤器等进行解决。

二、缓存预热

2.1 缓存预热基本原理

缓存预热的基本原理:程序启动或重启的时候,将需要经常访问的数据,提前加载到缓存当中,以便后续直接读取。

2.2 Redis 缓存预热实现

2.2.1 基于数据量预热

根据数据量的大小进行预热,比较常见的方法是在程序启动时,读取所有的数据,将数据全部写入缓存当中,以此实现缓存预热。其优点是预热完成后,可以避免缓存穿透;缺点是数据量大的时候,预热的时间较长。

2.2.2 基于时间预热

根据数据最近的更新时间和访问频率,对数据进行预热。比如最近7天读取频率比较高的数据,在程序启动时就可以进行预热。其优点是可以提高预热效率;缺点是无法避免缓存穿透。

2.2.3 周期性预热

周期性预热是指定期间内进行缓存预热,以保证系统的高效性。比如每天凌晨1点进行缓存预热,以此保证当系统高峰期到来时,能够有足够的缓存支持。其优点是预热时间可控,缺点是可能不能覆盖到所有的数据。


public class RedisCachePreheating {

    /**
     * 缓存预热:基于数据量预热
     */
    public void preheatByDataSize(){
        // 读取所有数据
        List<Data> dataList = readAllData();
        for(Data data : dataList){
            // 将数据写入缓存
            writeToCache(data);
        }
    }
  
    /**
     * 缓存预热:基于时间预热
     */
    public void preheatByTime(){
        // 获取最近7天的数据列表
        List<Data> dataList = readDataByTime(7);
        for(Data data : dataList){
            // 将数据写入缓存
            writeToCache(data);
        }
    }

    /**
     * 缓存预热:周期性预热
     */
    public void periodPreheat(){
        // 每隔1小时预热一次
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                // 预热操作,类似于preheatByDataSize()或preheatByTime()
            }
        }, 0, 60 * 60 * 1000);
    }
}

三、缓存穿透

3.1 缓存穿透基本原理

缓存穿透是指当一个查询不存在于缓存中,而且每次查询也都不会被缓存时,就会直接访问数据库。如果出现大量查询结果不存在的情况,就可能导致数据库崩溃。缓存穿透的原因可能是因为查询的条件非常特殊或者恶意攻击。

3.2 Redis 缓存穿透解决方案

以下是常见的 Redis 缓存穿透解决方案:

3.2.1 布隆过滤器

布隆过滤器是一种内存型、不可逆的数据结构。它使用哈希函数来判断一个元素是否在集合中。因为它的计算量小且运行速度快,所以通常被用作解决缓存穿透和大数据去重等问题。

在 Redis 中,我们可以使用 RedisBloom 模块来实现布隆过滤器。

Java 实现布隆过滤器的代码示例:

// 创建布隆过滤器并将其添加到 Redis 中
Jedis jedis = new Jedis("localhost", 6379);
RedisBloomFilter<Integer> bloomFilter = RedisBloomFilter.create(jedis, "bloom", 1000, 0.01);
bloomFilter.add(42);
// 检查元素是否存在于集合中
bloomFilter.contains(42); // 返回 true
bloomFilter.contains(666); // 返回 false

3.2.2 缓存空对象

当缓存查询结果为空时,我们可以将这个空对象添加到缓存中。这样下次同样的查询就会命中缓存,而不用去访问数据库了。

Java 实现缓存空对象的代码示例:

// 查询缓存。
Object result = redisTemplate.opsForValue().get(key);
if(result == null) {
    // 查询数据库。
    result = dao.query(key);
    // 将查询结果添加到缓存,有效期设置为 5 分钟。
    redisTemplate.opsForValue().set(key, result, Duration.ofMinutes(5));
}

3.2.3 限流

使用限流可以防止恶意攻击。

可以使用 Redis 的计数器和时间窗口算法来将高并发请求控制在一个较低的速率内。

Java 实现简单限流的代码示例:

// 获取当前时间戳。
long now = Instant.now().getEpochSecond();
// 在 Redis 中记录这 1 秒钟内的请求次数。
long current = redisTemplate.opsForValue().increment(key, 1);
// 设置有效期为 1 秒钟。
redisTemplate.expire(key, 1, TimeUnit.SECONDS);
if(current > maxRequests) {
    // 请求次数超限,返回失败。
    return new Response(false, "too many requests");
} else {
    // 请求次数未超限。
    // 如果是第一个请求,设置过期时间为 1 秒钟。
    redisTemplate.opsForValue().setIfAbsent(key, "", Duration.ofSeconds(1));
    return new Response(true, "");
}

四、应用实践

4.1 在 Spring Boot 中使用 Redis 缓存预热和缓存穿透解决方案

在 Spring Boot 中,我们可以使用注解来实现缓存预热和缓存穿透解决方案。

首先,我们需要添加 Spring Cache 和 Redis 相关的依赖,并配置 RedisTemplate 和缓存管理器。然后,我们可以在 Service 层的方法上使用 @Cacheable 注解来开启缓存,例如:

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private RedisTemplate<String, User> redisTemplate;

    @Cacheable(value = "user", key = "#id")
    public User get(int id) {
        // 直接从数据库中获取用户。
        return userDao.get(id);
    }
}

4.2 在分布式系统中使用 Redis 缓存预热和缓存穿透解决方案

在分布式系统中,我们可以使用 Redisson 或者其他类似的分布式锁来避免重复预热和处理缓存穿透。

例如,我们可以在所有服务器都停止服务前,将缓存数据写入 Redis 中,并加上分布式锁来保证只有一个服务能够进行预热。另外,我们也可以使用分布式锁来避免缓存穿透导致的数据库崩溃等问题。文章来源地址https://www.toymoban.com/news/detail-649254.html

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

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

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

相关文章

  • Redis 缓存预热+缓存雪崩+缓存击穿+缓存穿透

    面试题: 缓存预热、雪萌、穿透、击穿分别是什么?你遇到过那几个情况? 缓存预热你是怎么做的? 如何造免或者减少缓存雪崩? 穿透和击穿有什么区别?他两是一个意思还是载然不同? 穿适和击穿你有什么解决方案?如何避免? 假如出现了缓存不一致,你有哪些修补方

    2024年02月10日
    浏览(35)
  • Redis 之 缓存预热 & 缓存雪崩 & 缓存击穿 & 缓存穿透

    目录 一、缓存预热 1.1 缓存预热是什么? 1.2 解决方案: 二、缓存雪崩 2.1 缓存雪崩是什么?怎么发生的? 2.2 怎么解决 三、缓存穿透 3.1 是什么?怎么产生的呢? 3.2 解决方案  3.2.1、采用回写增强,  3.2.2、加上一个布隆过滤器, 四、缓存击穿 4.1 是什么? 4.2 怎么解决 五

    2024年02月13日
    浏览(25)
  • Redis 缓存雪崩、穿透、击穿、预热

            在实际工程中,Redis 缓存问题常伴随高并发场景出现。例如, 电商大促、活动报名、突发新闻 时,由于缓存失效导致大量请求访问数据库,导致 雪崩 、 击穿 、 穿透 等问题。因此,新系统上线前需 预热 缓存,以应对高并发,减轻数据库压力。本章主要围绕这

    2024年04月12日
    浏览(34)
  • 第十八章_Redis缓存预热+缓存雪崩+缓存击穿+缓存穿透

    缓存预热 缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据。 可以通过@PostConstruct初始化白名单数据 缓存雪崩 发生  redis主机挂了,Redis 全盘崩溃

    2024年02月07日
    浏览(38)
  • Redis7之缓存预热 + 缓存雪崩 + 缓存击穿 + 缓存穿透(八)

    缓存预热就是系统上线后,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据! 使用 @PostConstruct 初始化白名单数据 缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造

    2023年04月08日
    浏览(35)
  • Redis:缓存击穿、缓存穿透与缓存雪崩的区别、解决方案

            近期学习redis相关原理,记录一下开发过程中Redis的一些常见问题及应对方法。 一句话总结:先查 redis发现没数据 ,再去 数据库查发现还是没数据 。 这种情况下 缓存永远不会生效 ,数据库将承担巨大压力。         我们知道,redis的缓存作用,是在客户端发起查

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

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

    2024年02月21日
    浏览(28)
  • redis缓存雪崩、穿透、击穿解决方案

    关于缓存异常,我们常见的有三个问题:缓存雪崩、缓存击穿、缓存穿透。这三个问题一旦发生,会导致大量请求直接落到数据库层面。如果请求的并发量很大,会影响数据库的运行,严重的会导致数据库宕机。 为了避免缓存异常带来的损失,我们需要了解每种异常的原因以

    2024年02月10日
    浏览(40)
  • redis中缓存雪崩,缓存穿透,缓存击穿的原因以及解决方案

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

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

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

    2024年02月11日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包