Springboot实现缓存预热

很多时候我们代码中使用缓存时都是先判断缓存中没有数据我们再读取数据库而有则直接使用缓存数据,而在系统冷启动(当系统重启或新启动时,缓存是空的,这被称为冷启动)时,我们毫无意外都是直接获取数据库的内容,这时候缓存的命中率几乎为0,这时候我们需要考虑业务系统的缓存预热功能,在系统启动之前通过预先将常用数据加载到缓存中,以提高缓存命中率和系统性能的过程。缓存预热的目的是尽可能地避免缓存击穿和缓存雪崩。

一、系统启动时加载

1、CommandLineRunner和ApplicationRunner是SpringBoot中用于在应用程序启动后执行特定逻辑的接口。

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * 缓存预热器(CommandLineRunner方式)
 */
@Component
@Slf4j
public class CacheCLRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        //TODO 缓存预热逻辑
        log.info("CommandLineRunner方式完成缓存预热");
    }
}
java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 缓存预热器(ApplicationRunner方式)
 */
@Component
@Slf4j
public class CacheAppRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        //TODO 缓存预热逻辑
        log.info("ApplicationRunner方式完成缓存预热");
    }
}

2、实现InitializingBean接口,并在afterPropertiesSet方法中执行缓存预热的逻辑。这样Spring在初始化Bean时会调用afterPropertiesSet方法

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * 缓存预热器(InitializingBean方式)
 */
@Component
@Slf4j
public class CacheInitializing implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        //TODO 缓存预热逻辑
        log.info("InitializingBean方式完成缓存预热");
    }
}

3、基于ApplicationReadyEvent,我们可以在应用程序完全启动并处于可用状态后执行一些初始化逻辑。使用@EventListener注解或实现ApplicationListener接口来监听这个事件。

4、@PostConstruct注解标注一个方法,该方法将在 Bean 的构造函数执行完毕后立即被调用。

这里3、4点的例子写在一起

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 缓存预热器(ApplicationReadyEvent和@PostConstruct方式)
 */
@Component
@Slf4j
public class CacheLoader {

    @EventListener(ApplicationReadyEvent.class)
    public void loadCache1() {
        //TODO 缓存预热逻辑
        log.info("@EventListener方式完成缓存预热");
    }

    @PostConstruct
    public void loadCache2() {
        //TODO 缓存预热逻辑
        log.info("@PostConstruct方式完成缓存预热");
    }
}

启动项目大致看一下4种方式的加载顺序,可根据自己的需求选择对应的方式

二、定时任务加载

使用Spring的@Scheduled,quartz,xxl-job都可以,@Scheduled为例

java 复制代码
@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
public void scheduledCachePreload() {
	//TODO 缓存预热逻辑
	log.info("定时任务方式完成缓存预热");
}
相关推荐
懒羊羊不懒@23 分钟前
Java基础语法—最小单位、及注释
java·c语言·开发语言·数据结构·学习·算法
ss27326 分钟前
手写Spring第4弹: Spring框架进化论:15年技术变迁:从XML配置到响应式编程的演进之路
xml·java·开发语言·后端·spring
DokiDoki之父38 分钟前
MyBatis—增删查改操作
java·spring boot·mybatis
兩尛1 小时前
Spring面试
java·spring·面试
Java中文社群1 小时前
服务器被攻击!原因竟然是他?真没想到...
java·后端
Full Stack Developme1 小时前
java.nio 包详解
java·python·nio
零千叶1 小时前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
代码充电宝2 小时前
LeetCode 算法题【简单】290. 单词规律
java·算法·leetcode·职场和发展·哈希表
li3714908902 小时前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
摇滚侠2 小时前
Spring Boot 项目, idea 控制台日志设置彩色
java·spring boot·intellij-idea