掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Redis緩沖擊穿技術(shù)是一個(gè)成熟的緩存架構(gòu)來(lái)解決高并發(fā)請(qǐng)求情境下的緩存失效問(wèn)題。本文旨在介紹redis緩沖擊穿技術(shù),并通過(guò)Java代碼實(shí)現(xiàn)以幫助開(kāi)發(fā)人員更好地理解該技術(shù)。

成都創(chuàng)新互聯(lián)公司成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目做網(wǎng)站、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元松原做網(wǎng)站,已為上家服務(wù),為松原各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108
一、緩存失效的問(wèn)題
在高并發(fā)的Web應(yīng)用中,我們經(jīng)常需要使用緩存來(lái)優(yōu)化系統(tǒng)性能以減小數(shù)據(jù)庫(kù)訪問(wèn)壓力。但是,當(dāng)一個(gè)緩存的鍵過(guò)期后,下一個(gè)請(qǐng)求將無(wú)法從緩存中獲取數(shù)據(jù),最終必須從數(shù)據(jù)庫(kù)中檢索。在Web應(yīng)用程序有高并發(fā)負(fù)載的情況下,這種失效情況會(huì)變得更加嚴(yán)重,可能導(dǎo)致數(shù)據(jù)庫(kù)性能問(wèn)題。
二、緩解緩存失效問(wèn)題的手段
為回避上述的問(wèn)題,我們可以采取以下三種方法較好地解決問(wèn)題:
1.設(shè)置過(guò)期時(shí)間:緩存數(shù)據(jù)具有過(guò)期時(shí)間,一旦一條緩存數(shù)據(jù)過(guò)期則將其從緩存中刪除,同時(shí)從數(shù)據(jù)源重新加載數(shù)據(jù)到緩存中。但是這種方法容易產(chǎn)生緩存雪崩問(wèn)題,即在某一時(shí)段內(nèi)緩存集中失效,在下一時(shí)段內(nèi)又會(huì)多次查詢數(shù)據(jù)源。
2.加鎖:在緩存失效之后,將需要更新的數(shù)據(jù)進(jìn)行加鎖,只讓一個(gè)線程查詢數(shù)據(jù)庫(kù),同時(shí)其他的線程等待該線程的查詢結(jié)果并獲取到加鎖之后的數(shù)據(jù),并釋放鎖。但是加鎖也有一些問(wèn)題,如死鎖、中心化瓶頸等。
3.緩存穿透:緩存穿透是指查詢不存在的緩存數(shù)據(jù),緩存為空,沒(méi)有在數(shù)據(jù)庫(kù)中查到值,導(dǎo)致每個(gè)請(qǐng)求都到數(shù)據(jù)庫(kù)中獲取數(shù)據(jù),可能導(dǎo)致宕機(jī)。解決這種情況可以采用偽造緩存值、布隆過(guò)濾器、緩存空值等方式。
三、Redis 解決緩存擊穿
為了解決緩存擊穿問(wèn)題,我們可以使用Redis緩存技術(shù)。Redis是一種互聯(lián)網(wǎng)高并發(fā)應(yīng)用程序緩存的首選解決方案,因?yàn)樗梢员4娲罅績(jī)?nèi)存操作數(shù)據(jù),使用高效的數(shù)據(jù)結(jié)構(gòu)和算法,有效降低數(shù)據(jù)訪問(wèn)速度。
Redis提供互斥鎖(setnx),高效地“set if not exist”,可以看做分布式環(huán)境中實(shí)現(xiàn)Mutex的一種方式。Redis可以使用SET命令為在redis中存儲(chǔ)的具有特定鍵的值設(shè)置過(guò)期時(shí)間。在此過(guò)期時(shí)間之前,該值將保持在內(nèi)存中;一旦鍵過(guò)期,數(shù)據(jù)就會(huì)從存儲(chǔ)中刪除,同時(shí)執(zhí)行回調(diào)函數(shù)來(lái)更新緩存數(shù)據(jù)。
實(shí)現(xiàn)示例:
public String getData(String KEY) {
String value;
ValueOperations operations = redisTemplate.opsForValue();
if (redisTemplate.hasKey(key)) {
value = operations.get(key);
log.info(“Get Data from Redis”);
return value;
}
//為避免”緩存穿透”問(wèn)題(即緩存中不存在相關(guān)鍵,導(dǎo)致每個(gè)請(qǐng)求都到數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)),我們可以設(shè)置一個(gè)較短的過(guò)期時(shí)間,例如3秒。
synchronized (this) {
if (redisTemplate.hasKey(key)) {
value = operations.get(key);
log.info(“Get Data from Redis after synchronization”);
return value;
}
//如果緩存沒(méi)有命中,我們將打一個(gè)標(biāo)記,避免進(jìn)行緩存穿透操作。
//參數(shù)“nx”表示當(dāng)鍵不存在時(shí),才會(huì)執(zhí)行SET命令。
Boolean target = operations.setIfAbsent(key, “true”, 3, TimeUnit.SECONDS);
if (target) {
log.info(“Get Data from DataBase”);
value = getDataFromDataBase(key);
operations.set(key, value, 30, TimeUnit.MINUTES);
return value;
}
}
//如果多個(gè)請(qǐng)求都從緩存中獲取數(shù)據(jù),Redis將返回null。
//參數(shù)“not null”表示為空時(shí)不會(huì)執(zhí)行下一步操作,否則會(huì)直接調(diào)用下一步代碼,其中包含查詢數(shù)據(jù)庫(kù),以保證多個(gè)線程可以查詢到最新數(shù)據(jù),并永遠(yuǎn)不會(huì)產(chǎn)生緩存穿透問(wèn)題。
value = operations.get(key, StringUtils.EMPTY);
if (StringUtils.isBlank(value)) {
log.info(“The value of the key {} does not exist”, key);
} else {
log.info(“The value of the key {} exists”, key);
}
return value;
}
四、Redis緩沖擊穿技術(shù)總結(jié)
Redis緩沖擊穿技術(shù)是解決高并發(fā)情境中緩存失效的一種成熟技術(shù),通過(guò)采用Redis緩存技術(shù),我們可以靈活設(shè)置過(guò)期時(shí)間,實(shí)現(xiàn)緩存及時(shí)清除,有效避免緩存失效問(wèn)題的出現(xiàn)。通過(guò)加鎖、設(shè)置過(guò)期時(shí)間以及使用操作指令等方式,我們可以避免緩存失效導(dǎo)致數(shù)據(jù)庫(kù)性能問(wèn)題帶來(lái)的查詢壓力。
成都創(chuàng)新互聯(lián)科技有限公司,是一家專注于互聯(lián)網(wǎng)、IDC服務(wù)、應(yīng)用軟件開(kāi)發(fā)、網(wǎng)站建設(shè)推廣的公司,為客戶提供互聯(lián)網(wǎng)基礎(chǔ)服務(wù)!
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡(jiǎn)單好用,價(jià)格厚道的香港/美國(guó)云服務(wù)器和獨(dú)立服務(wù)器。創(chuàng)新互聯(lián)成都老牌IDC服務(wù)商,專注四川成都IDC機(jī)房服務(wù)器托管/機(jī)柜租用。為您精選優(yōu)質(zhì)idc數(shù)據(jù)中心機(jī)房租用、服務(wù)器托管、機(jī)柜租賃、大帶寬租用,可選線路電信、移動(dòng)、聯(lián)通等。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流