开发者

详解Redis缓存预热的实现方法

开发者 https://www.devze.com 2023-11-19 09:59 出处:网络 作者: vker
目录什么是缓存预热?实现缓存抽象类Spring上下文工具类缓存预热使用技术栈:
目录
  • 什么是缓存预热?
  • 实现
    • 缓存抽象类
    • Spring上下文工具类
    • 缓存预热
  • 使用

    技术栈:

    • SpringBoot 3.0.2
    • Redis4
    • mysql8
    • MyBATis-Plus 3.5.3.1
    • Druid 1.2.18

    工具:

    • lombok

    什么是缓存预热?

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

    实现

    缓存抽象类

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

    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();
        }
    }

    Spring上下文工具类

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

    @Component
    public class ApplicationContextUjavascripttil implements ApplicationContextAware {
        private static ApplicationContext applicationContext;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            ApplicationContextUtil.applicationContext = applicationContext;
        }
        /**
         * 获取上下文
         * @return
         */
        public static ApplicationContext getContext() {
            return applicationContext;
        }
    }

    缓存预热

    然后我们来实现,在程序启动后,直接进行数据的缓存加载,这个类需要实现CommandLineRunner接口,这个接口提供的方法作用就是在程序启动后自动运行。这个实现类里,我们使用ApplicationContextUtil工具类来获取上下文,然后通过getBeansOfType方法获取实现AbstractCache抽象类的子类,返回的是一个Map类型的集合,接下来通过getBean方法以多态的方式实例化子类,最后我们调用抽象类的init方法即可。如果有多个实现类,使用@Order注解标注先后运行就可以了。

    @Component
    @ConditijavascriptonalOnProperty(name = {"cache.init.enable"}, havingValue = "true", matchIfMissing = false)
    public class CachePreheatHandler implements CommandLineRunner {
        /**
         * 缓存预热
         * @param args
         * @throwww.devze.comws 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());
               javascript cache.init();
            }
        }
    }

    解释:

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

    cache.initjavascript.enable=true

    使用

    我们就以新闻热点为例,数据库中有一张tb_news新闻表,均为微博热搜体育榜内容。

    详解Redis缓存预热的实现方法

    接下来创建一个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中已经存好了热点数据

    详解Redis缓存预热的实现方法

    最后可以通过get方法获取数据了,也不用担心数据过期了。

    @RestController
    @RequestMapping("/news")
    @RequiredArgsConstructor
    public class NewsController {
        private final NewsCache newsCache;
        @GetMapping("/cache")
        public List<News> list() {
            return newsCache.get();
        }
    }

    好了,小伙伴们,今天的分享就到此结束了,欢迎留出建议,如果觉得内容可以,还请来个点赞和关注吧!

    以上就是详解Redis缓存预热的实现方法的详细内容,更多关于Redis缓存预热的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消