行业资讯 2025年08月6日
0 收藏 0 点赞 114 浏览 2381 个字
摘要 :

文章目录 1.定义缓存抽象类 2.spring boot生命周期的监控 3.创建AbstractCache的具体实现类 4.测试 在业务系统中,为了降低对业务数据库的负载压力,我们需要在程序启……




  • 1.定义缓存抽象类
  • 2.spring boot生命周期的监控
  • 3.创建AbstractCache的具体实现
  • 4.测试

在业务系统中,为了降低对业务数据库的负载压力,我们需要在程序启动时将一些常用数据主动加载到内存数据库,这就是我们通常所说的缓存预热策略。

官方定义如下:

缓存预热是一种策略,它在程序启动或缓存失效后主动将热点数据加载到缓存中。通过这种方式,当实际请求到达程序时,热点数据已经存在于缓存中,从而有助于减少缓存穿透和缓存击穿的情况,同时减轻了SQL服务器的负载。

为了实现这一策略,我们结合业务系统并进行了相关设计,以下是设计代码的详细描述:

1.定义缓存抽象类

定义了一个抽象类,用于执行缓存操作,包括初始化缓存、从缓存中获取数据、清理缓存以及刷新缓存等操作。这个抽象类与Spring Boot的生命周期监控相关联。

public abstract class AbstractCache {
    /**
     * 缓存
     */
     protected abstract void init();
     /**
     * 获取缓存
     * @return 缓存列表
     */
    public abstract <T> T get();
    /**
     *清理缓存
     */
    public abstract void clear();
    /**
     *重新加载*/
    public void reload() {
        clear();
        init();
    }
}

2.spring boot生命周期的监控

在Spring Boot项目启动后,立即执行初始化缓存操作。而在项目结束时,缓存被立即删除。

@Component
public class MyFullLifecycle implements SmartLifecycle {
    @Resource
    private ApplicationContext applicationContext;
    private boolean isRunning = false;

    public AbstractCache getAbstractCache() {
        Map<String, AbstractCache> beansOfType = applicationContext.getBeansOfType(AbstractCache.class);
        for (Map.Entry<String, AbstractCaches> cacheEntry : beansOfType.entrySet()) {
            return applicationContext.getBean(cacheEntry.getValue().getClass());
        }
        return null;
    }

    @Override
    public void start() {
        //编写程序启动时的逻辑
        System.out.println(\"应用程序启动\");
        isRunning = true;
        AbstractCache cache = getAbstractCache();
        cache.init();
    }

    @Override
    public void stop() {
        //编写程序停止时的逻辑
        System.out.println(\"应用程序停止\");
        isRunning = false;
        AbstractCache cache = getAbstractCache();
        cache.clear();
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

}

3.创建AbstractCache的具体实现类

创建了继承该抽象类的具体实现类,其中包括以下核心方法的重写:

  • 初始化:将所有热点数据缓存到Redis中。
  • 查询:如果缓存中不存在特定key的数据,就执行初始化缓存;否则,直接从缓存中获取数据。
  • 删除:用于在服务关闭时清除缓存。这里采用了直接删除key的方法,但对于大量key的情况,建议使用游标或Lua脚本来删除。
@Component
@RequiredArgsConstructor
public class UserCache extends AbstractCache {
    private static final String USERS_KEY = \"users\" ;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private UserService userService;
    @Override
    protected void init() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(USERS_KEY))) {
            redisTemplate.opsForValue().set(USERS_KEY, userService.list(), 30, TimeUnit.MINUTES);
            
        }
    }
    @Override
    public <T> T get() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(USERS_KEY))){
            init();
        }
        return (T) redisTemplate.opsForValue().get(USERS_KEY);
    }
    @Override
    public void clear() {
        redisTemplate.delete(USERS_KEY);
    }
}

4.测试

提供了一个接口类,用于测试实现效果。

@GetMapping(value = \"users \")
public List<User> getUsers() {
    return userCache.get();
}

以上核心的代码完成后我们启动服务测试一下效果:Redis如何实现缓存预热功能

相关的时间段redis的日志如下图,当服务启动之后,缓存中就有了数据,接口测试可以直接拿到相关数据;当服务关闭之后,缓存数据也一起的清空了。Redis如何实现缓存预热功能

需要注意的是,这种设计方式适用于单机模式,而对于多实例和分布式服务,必须考虑数据同步的问题。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9374.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号