Redis缓存预热,该如何实现

news/2024/7/8 0:45:23

一、什么是缓存预热

缓存预热是一种在程序启动或缓存失效之后,主动将热点数据加载到缓存中的策略。这样,在实际请求到达程序时,热点数据已经存在于缓存中,从而减少了缓存穿透和缓存击穿的情况,也缓解了SQL服务器的压力。

二、实现

1 、缓存抽象类

首先我们先来实现一个缓存抽象类,这个抽象类的作用就是在将来我们需要将某个模块的数据需要提前加载到缓存中的时候,我们可以创建一个它的实现类,来进行数据的缓存与加载,具体使用方式请看后边我写的例子。

public abstract class AbstractCache {

    /**
     * 缓存
     */
    protected abstract void init();

    /**
     * 获取缓存
     *
     * @param <T>
     * @return
     */
    public abstract <T> T get();

    /**
     * 清理缓存
     */
    public abstract void clear();

    /**
     * 重新加载
     */
    public void reload() {
        clear();
        init();
    }
}

2、Spring上下文工具类

接下来我们实现一个Spring的上下文工具类,这个工具类需要实现ApplicationContextAware,作用就是负责管理bean的加载与实例化的,具体如何使用,请往下继续阅读。

@Component
public class ApplicationContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    /**
     * 获取上下文
     * @return
     */
    public static ApplicationContext getContext() {
        return applicationContext;
    }
}

3、缓存预热

然后我们来实现,在程序启动后,直接进行数据的缓存加载,这个类需要实现CommandLineRunner接口,这个接口提供的方法作用就是在程序启动后自动运行。

这个实现类里,我们使用ApplicationContextUtil工具类来获取上下文,然后通过getBeansOfType方法获取实现AbstractCache抽象类的子类,返回的是一个Map类型的集合,接下来通过getBean方法以多态的方式实例化子类,最后我们调用抽象类的init方法即可。

如果有多个实现类,使用@Order注解标注先后运行就可以了。

@Component
@ConditionalOnProperty(name = {"cache.init.enable"}, havingValue = "true", matchIfMissing = false)
public class CachePreheatHandler implements CommandLineRunner {

    /**
     * 缓存预热
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        ApplicationContext context = ApplicationContextUtil.getContext();
        Map<String, AbstractCache> beansOfType = context.getBeansOfType(AbstractCache.class);
        for (Map.Entry<String, AbstractCache> cacheEntry : beansOfType.entrySet()) {
            AbstractCache cache = context.getBean(cacheEntry.getValue().getClass());
            cache.init();
        }
    }
}

解释:

@ConditionalOnProperty这个注解在这里的作用是,需要在配置文件开启cache.init.enable,理想值是true,默认值是false。

cache.init.enable=true

4、使用

我们就以新闻热点为例,数据库中有一张tb_news新闻表,均为微博热搜体育榜内容。
在这里插入图片描述

接下来创建一个AbstractCache的实现类,来实现具体的实现

@Component
@RequiredArgsConstructor
public class NewsCache extends AbstractCache {

    private static final String NEWS_KEY = "news";

    private final RedisTemplate<String, Object> redisTemplate;

    private final NewsService newsService;

    @Override
    protected void init() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(NEWS_KEY))) {
            redisTemplate.opsForValue().set(NEWS_KEY, newsService.list(), 30, TimeUnit.MINUTES);
        }
    }

    @Override
    public <T> T get() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(NEWS_KEY))) {
            reload();
        }
        return (T) redisTemplate.opsForValue().get(NEWS_KEY);
    }

    @Override
    public void clear() {
        redisTemplate.delete(NEWS_KEY);
    }
}

然后启动项目,我们就发现,Redis中已经存好了热点数据
在这里插入图片描述
最后可以通过get方法获取数据了,也不用担心数据过期了。

@RestController
@RequestMapping("/news")
@RequiredArgsConstructor
public class NewsController {

    private final NewsCache newsCache;

    @GetMapping("/cache")
    public List<News> list() {
        return newsCache.get();
    }
}

http://lihuaxi.xjx100.cn/news/2125449.html

相关文章

node-fs(fileSystem)文件系统-write--02

1.简介 实现与硬盘的交互&#xff0c;文件创建&#xff0c;删除与重命名&#xff0c;移动以及文件内容的写入与读取以及文件夹相关操作。 2.fs 模块的常见用法 2.1fs.writeFile() 方法用于异步地将数据写入文件。 新建一个文件xxx.txt 写入内容 哟哟 实际应用场景&#xff0c…

【linux深入剖析】基础IO操作 | 使用Linux库函数实现读写操作 | 文件相关系统调用接口

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.复习C文件IO相关操…

文献阅读工具-->Adobe pdf + 有道词典

Adobe pdf 有道词典 最近一直在考虑用什么文献阅读工具&#xff0c;痛点无非就是想用翻译功能&#xff0c;Adobe pdf的添加注释已经很好用了&#xff0c;使用了zotero&#xff0c;感觉不行&#xff08;不能直接对原文件修改&#xff0c;有副本&#xff0c;麻烦&#xff09;。…

基于nodejs+vue物业管理系统python-flask-django-php

课题主要分为四大模块&#xff1a;即管理员模块&#xff0c;物业管理模块、业主模块和维修员模块&#xff0c;主要功能包括&#xff1a;个人中心、物业管理、业主管理、维修员管理、小区公告管理、小区信息管理、房产信息管理、车位信息管理、停车位管理、停车信息管理、缴费信…

Python 中处理JSON文件的方法

用 Python 读取、写入和操作 JSON 文件 JSON&#xff08;JavaScript Object Notation&#xff09;是一种流行的数据交换格式&#xff0c;易于人类阅读和编写。在编程领域中&#xff0c;与网络API或HTTP请求交互时经常会用到 JSON。Python 通过 json 模块提供了对 JSON 文件的内…

解决华为云服务器宝塔面板无法访问显示“此站点的连接不安全”问题

已经配置好安全组以及初始化宝塔面板&#xff0c;还是无法访问镜像管理页面&#xff0c;提示此站点的连接不安全。 解决方案 将地址https改为http即可进入。 成功登录后&#xff0c;开启面板SSL即可。

python爬虫-----输入输出与流程控制语句(第四天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

Java编程练习之类的多态

类的多态可以从两方面体现&#xff1a;一是方法的重载&#xff0c;二是类的上下转型。 1&#xff09;方法的重载 方法的重载就是在同一个类中允许同时存在多个同名方法&#xff0c;只要这些方法的参数个数或类型不同即可。 练习1&#xff1a; 使用方法的重载描述所有的超市…