當前位置: 妍妍網 > 碼農

Redis緩存預熱,該如何實作?

2024-03-16碼農

點選「 IT碼徒 」, 關註,置頂 公眾號

每日技術幹貨,第一時間送達!

1

什麽是緩存預熱?

緩存預熱是一種在程式啟動或緩存失效之後,主動將熱點數據載入到緩存中的策略。這樣,在實際請求到達程式時,熱點數據已經存在於緩存中,從而減少了緩存穿透和緩存擊穿的情況,也緩解了SQL伺服器的壓力。

2

實作

緩存抽象類

首先我們先來實作一個緩存抽象類,這個抽象類的作用就是在將來我們需要將某個模組的數據需要提前載入到緩存中的時候,我們可以建立一個它的實作類,來進行數據的緩存與載入,具體使用方式請看後邊我寫的例子。

publicabstract classAbstractCache {
/**
* 緩存
*/

protectedabstractvoidinit();
/**
* 獲取緩存
*
* @param <T>
* @return
*/

publicabstract <T> T get();
/**
* 清理緩存
*/

publicabstractvoidclear();
/**
* 重新載入
*/

publicvoidreload() {
clear();
init();
}
}


Spring上下文工具類

接下來我們實作一個Spring的上下文工具類,這個工具類需要實作ApplicationContextAware,作用就是負責管理bean的載入與例項化的,具體如何使用,請往下繼續閱讀。

@Component
public classApplicationContextUtilimplementsApplicationContextAware{
privatestatic ApplicationContext applicationContext;
@Override
publicvoidsetApplicationContext(ApplicationContext applicationContext)throws BeansException {
ApplicationContextUtil.applicationContext = applicationContext;
}
/**
* 獲取上下文
* @return
*/

publicstatic ApplicationContext getContext(){
return applicationContext;
}
}


緩存預熱

然後我們來實作,在程式啟動後,直接進行數據的緩存載入,這個類需要實作CommandLineRunner介面,這個介面提供的方法作用就是在程式啟動後自動執行。

這個實作類裏,我們使用ApplicationContextUtil工具類來獲取上下文,然後透過getBeansOfType方法獲取實作AbstractCache抽象類的子類別,返回的是一個Map型別的集合,接下來透過getBean方法以多型的方式例項化子類別,最後我們呼叫抽象類的init方法即可。

如果有多個實作類,使用@Order註解標註先後執行就可以了。

@Component
@ConditionalOnProperty(name = {"cache.init.enable"}, havingValue = "true", matchIfMissing = false)
public classCachePreheatHandlerimplementsCommandLineRunner{
/**
* 緩存預熱
* @param args
* @throws Exception
*/

@Override
publicvoidrun(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().get class());
cache.init();
}
}
}

解釋:

@ConditionalOnProperty這個註解在這裏的作用是,需要在配置檔開啟cache.init.enable,理想值是true,預設值是false。

cache.init.enable=true

使用

我們就以新聞熱點為例,資料庫中有一張tb_news新聞表,均為微博熱搜體育榜內容。

接下來建立一個AbstractCache的實作類,來實作具體的實作

@Component
@RequiredArgsConstructor
public classNewsCacheextendsAbstractCache{
privatestaticfinal String NEWS_KEY = "news";
privatefinal RedisTemplate<String, Object> redisTemplate;
privatefinal NewsService newsService;
@Override
protectedvoidinit(){
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
publicvoidclear(){
redisTemplate.delete(NEWS_KEY);
}
}





然後啟動計畫,我們就發現,Redis中已經存好了熱點數據

最後可以透過get方法獲取數據了,也不用擔心數據過期了。

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

好了,小夥伴們,今天的分享就到此結束了,歡迎留出建議,如果覺得內容可以,還請來個點贊和關註吧!

來源:juejin.cn/post/7287907117336526863

END

PS:防止找不到本篇文章,可以收藏點贊,方便翻閱尋找哦。

往期推薦