詳解Redis緩存預熱的實現方法
技術棧:
- SpringBoot 3.0.2
- Redis4
- MySQL8
- Mybatis-Plus 3.5.3.1
- Druid 1.2.18
工具:
- lombok
什么是緩存預熱?
緩存預熱
是一種在程序啟動或緩存失效之后,主動將熱點數據加載到緩存中的策略。 這樣,在實際請求到達程序時,熱點數據已經存在于緩存中,從而減少了緩存穿透和緩存擊穿的情況,也緩解了SQL服務器的壓力。
實現
緩存抽象類
首先我們先來實現一個緩存抽象類
,這個抽象類的作用就是在將來我們需要將某個模塊的數據需要提前加載到緩存中的時候,我們可以創(chuàng)建一個它的實現類,來進行數據的緩存與加載,具體使用方式請看后邊我寫的例子。
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的加載與實例化的,具體如何使用,請往下繼續(xù)閱讀。
@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; } }
緩存預熱
然后我們來實現,在程序啟動后,直接進行數據的緩存加載,這個類需要實現CommandLineRunner
接口,這個接口提供的方法作用就是在程序啟動后自動運行。這個實現類里,我們使用ApplicationContextUtil
工具類來獲取上下文,然后通過getBeansOfType
方法獲取實現AbstractCache
抽象類的子類,返回的是一個Map類型的集合,接下來通過getBean
方法以多態(tài)的方式實例化子類,最后我們調用抽象類的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
使用
我們就以新聞熱點為例,數據庫中有一張tb_news
新聞表,均為微博熱搜體育榜內容。
接下來創(chuàng)建一個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); } }
然后啟動項目,我們就發(fā)現,Redis中已經存好了熱點數據
最后可以通過get
方法獲取數據了,也不用擔心數據過期了。
@RestController @RequestMapping("/news") @RequiredArgsConstructor public class NewsController { private final NewsCache newsCache; @GetMapping("/cache") public List<News> list() { return newsCache.get(); } }
好了,小伙伴們,今天的分享就到此結束了,歡迎留出建議,如果覺得內容可以,還請來個點贊和關注吧!
以上就是詳解Redis緩存預熱的實現方法的詳細內容,更多關于Redis緩存預熱的資料請關注腳本之家其它相關文章!