新聞中心
解決Redis中擊穿的方案

創(chuàng)新互聯(lián)公司專注于義烏企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城網(wǎng)站開(kāi)發(fā)。義烏網(wǎng)站建設(shè)公司,為義烏等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)
對(duì)于高并發(fā)系統(tǒng)中對(duì)緩存的依賴性越來(lái)越強(qiáng),緩存擊穿也成為了我們必須要面對(duì)和解決的一個(gè)問(wèn)題。而Redis是當(dāng)前最受歡迎的緩存服務(wù),它除了有著快速高效的讀寫(xiě)性能,還提供了多種數(shù)據(jù)結(jié)構(gòu)和豐富的功能。但是,Redis也存在著緩存擊穿的問(wèn)題。本文將為大家提出一些在Redis中解決緩存擊穿的方案。
一、緩存擊穿
所謂緩存擊穿就是緩存中沒(méi)有而業(yè)務(wù)又迫切需要的數(shù)據(jù),導(dǎo)致大量的請(qǐng)求同時(shí)落到數(shù)據(jù)庫(kù)上,使得系統(tǒng)的并發(fā)量出現(xiàn)了大量的提升,從而導(dǎo)致了數(shù)據(jù)庫(kù)的阻塞甚至宕機(jī)的問(wèn)題。
二、原因分析
導(dǎo)致Redis中緩存擊穿的原因在于:對(duì)于某些熱點(diǎn)數(shù)據(jù),其緩存可能因?yàn)槟承┰蛲蝗皇?,而此時(shí)又有大量的請(qǐng)求涌入,導(dǎo)致了緩存的不可用,而數(shù)據(jù)庫(kù)卻不得不被大量的請(qǐng)求所占用并進(jìn)行處理,最終導(dǎo)致了緩存擊穿的問(wèn)題。
三、解決方案
1. 應(yīng)用層緩存降級(jí)
當(dāng)Redis中某些熱點(diǎn)數(shù)據(jù)失效或者為空時(shí),我們可以通過(guò)在應(yīng)用層做一個(gè)簡(jiǎn)單的緩存降級(jí)處理來(lái)解決緩存擊穿的問(wèn)題。例如,我們可以使用雙重檢測(cè)鎖(Double-checking Locking)來(lái)解決這個(gè)問(wèn)題。
public Object getFromCache(String KEY) {
//從Redis中獲取緩存數(shù)據(jù)
Object result = getFromRedis(key);
if (result == null) {
//使用鎖,避免大量的請(qǐng)求同時(shí)落到數(shù)據(jù)庫(kù)上
synchronized (this) {
//再次從Redis中獲取數(shù)據(jù)
result = getFromRedis(key);
//如果Redis中沒(méi)有數(shù)據(jù),則從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)并緩存到Redis中
if (result == null) {
result = getFromDB(key);
putToRedis(key, result);
}
}
}
return result;
}
可以看到,雙重檢測(cè)鎖解決了請(qǐng)求搶占的問(wèn)題,一旦Redis中沒(méi)有數(shù)據(jù),請(qǐng)求會(huì)進(jìn)入同步塊中,此時(shí)只有一個(gè)請(qǐng)求會(huì)進(jìn)行Redis和數(shù)據(jù)庫(kù)的交互,其余的請(qǐng)求則會(huì)等待。
2. 對(duì)緩存設(shè)置過(guò)期時(shí)間
我們可以設(shè)置一個(gè)短期緩存與長(zhǎng)期緩存共同存儲(chǔ)數(shù)據(jù)。其中,短期緩存時(shí)間刻意定得比較短,以防止熱點(diǎn)數(shù)據(jù)在過(guò)期之后請(qǐng)求直接落到數(shù)據(jù)庫(kù)上。例如,我們可以將短期緩存設(shè)置為1分鐘,長(zhǎng)期緩存則設(shè)為1個(gè)小時(shí)。
public Object getFromCache(String key) {
//從短期緩存中獲取數(shù)據(jù)
Object result = getFromRedis(shortTermCacheKey);
if (result == null) {
//從長(zhǎng)期緩存中獲取數(shù)據(jù)
result = getFromRedis(longTermCacheKey);
if (result == null) {
//從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)并存儲(chǔ)到長(zhǎng)期和短期緩存中
result = getFromDB(key);
putToRedis(shortTermCacheKey, result, SHORT_TERM_CACHE_TIMEOUT);
putToRedis(longTermCacheKey, result, LONG_TERM_CACHE_TIMEOUT);
}
}
return result;
}
在這種情況下,熱點(diǎn)數(shù)據(jù)在失效后不會(huì)直接被請(qǐng)求落到數(shù)據(jù)庫(kù)上,而是會(huì)先去檢查短期緩存中是否有,如果沒(méi)有再去檢查長(zhǎng)期緩存中是否存在。
3. 對(duì)空值緩存設(shè)置過(guò)期時(shí)間
如果Redis中某些數(shù)據(jù)失效,其對(duì)應(yīng)的空值則應(yīng)該設(shè)置一個(gè)較短的過(guò)期時(shí)間。例如,我們可以將空值的緩存過(guò)期時(shí)間設(shè)置為5~10分鐘。
public Object getFromCache(String key) {
//從Redis中獲取緩存數(shù)據(jù)
Object result = getFromRedis(key);
if (result == null) {
//從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)
result = getFromDB(key);
if (result != null) {
//將數(shù)據(jù)緩存到Redis中
putToRedis(key, result);
} else {
//將空值緩存到Redis中
putToRedis(key, EMPTY_VALUE, EMPTY_VALUE_CACHE_EXPIRATION);
}
} else if (result == EMPTY_VALUE) {
//防止空值搶占Redis中位置,將空值的過(guò)期時(shí)間設(shè)為5~10分鐘
putToRedis(key, result, EMPTY_VALUE_CACHE_EXPIRATION);
}
return result;
}
在這種情況下,如果Redis中存儲(chǔ)的數(shù)據(jù)是空值并且沒(méi)有過(guò)期,那么短時(shí)間內(nèi)多次訪問(wèn)的請(qǐng)求都會(huì)直接返回空值,避免了對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求。只有當(dāng)空值過(guò)期之后,Redis才會(huì)將請(qǐng)求轉(zhuǎn)發(fā)至數(shù)據(jù)庫(kù)。
四、總結(jié)
緩存是提升系統(tǒng)性能的重要手段,而緩存擊穿問(wèn)題又是我們經(jīng)常要面對(duì)的挑戰(zhàn)。本文提出了三種常見(jiàn)的解決策略,可以根據(jù)具體情況選擇合適的方案。在應(yīng)用程序中使用這些策略,可以避免緩存擊穿問(wèn)題,提高系統(tǒng)的性能和可用性。
創(chuàng)新互聯(lián)成都網(wǎng)站建設(shè)公司提供專業(yè)的建站服務(wù),為您量身定制,歡迎來(lái)電(028-86922220)為您打造專屬于企業(yè)本身的網(wǎng)絡(luò)品牌形象。
成都創(chuàng)新互聯(lián)品牌官網(wǎng)提供專業(yè)的網(wǎng)站建設(shè)、設(shè)計(jì)、制作等服務(wù),是一家以網(wǎng)站建設(shè)為主要業(yè)務(wù)的公司,在網(wǎng)站建設(shè)、設(shè)計(jì)和制作領(lǐng)域具有豐富的經(jīng)驗(yàn)。
網(wǎng)頁(yè)名稱:解決Redis中擊穿的方案(redis的擊穿怎么解決)
網(wǎng)頁(yè)鏈接:http://fisionsoft.com.cn/article/coiscip.html


咨詢
建站咨詢
