新聞中心
Redis過(guò)期場(chǎng)景:實(shí)現(xiàn)有效的自動(dòng)清理

赫章網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),赫章網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為赫章上千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的赫章做網(wǎng)站的公司定做!
Redis是一種非關(guān)系型數(shù)據(jù)庫(kù),被廣泛使用于緩存、計(jì)數(shù)器、消息隊(duì)列等場(chǎng)景。在使用Redis時(shí),為避免內(nèi)存過(guò)度占用,我們需要對(duì)數(shù)據(jù)進(jìn)行過(guò)期刪除,即當(dāng)數(shù)據(jù)過(guò)期后,Redis自動(dòng)將其刪除。本文將介紹如何實(shí)現(xiàn)有效的自動(dòng)清理Redis過(guò)期數(shù)據(jù)。
一、Redis過(guò)期策略
Redis提供了2種過(guò)期策略:定時(shí)刪除和惰性刪除。
1. 定時(shí)刪除
定時(shí)刪除是指Redis在設(shè)置鍵的過(guò)期時(shí)間時(shí),同時(shí)創(chuàng)建一個(gè)定時(shí)器,到達(dá)過(guò)期時(shí)間時(shí),由定時(shí)器主動(dòng)清除。
該過(guò)期策略優(yōu)點(diǎn)是及時(shí)刪除過(guò)期鍵,不會(huì)出現(xiàn)過(guò)期鍵占用內(nèi)存的問(wèn)題。但定時(shí)刪除需要在每個(gè)鍵上創(chuàng)建一個(gè)定時(shí)器,在鍵數(shù)較多時(shí),會(huì)增加CPU壓力,影響Redis響應(yīng)速度。
2. 惰性刪除
惰性刪除是指Redis在訪問(wèn)鍵時(shí),首先檢查鍵是否過(guò)期,如果過(guò)期則刪除,否則繼續(xù)訪問(wèn)。
該過(guò)期策略優(yōu)點(diǎn)是不需要為每個(gè)鍵創(chuàng)建定時(shí)器,避免了CPU壓力。但這也意味著過(guò)期鍵只有在訪問(wèn)時(shí)才刪除,如果沒(méi)有被訪問(wèn)到,則一直占用內(nèi)存,直到過(guò)期策略生效。
二、Redis過(guò)期實(shí)現(xiàn)方式
實(shí)現(xiàn)Redis過(guò)期需要用到Redis提供的過(guò)期機(jī)制:為鍵設(shè)置過(guò)期時(shí)間,到達(dá)過(guò)期時(shí)間時(shí),Redis將自動(dòng)刪除鍵。
我們需要為需要設(shè)置過(guò)期時(shí)間的鍵創(chuàng)建定時(shí)器,并將其添加到Redis過(guò)期時(shí)間字典中。定時(shí)器主要由Redis server.c中的expireifNeeded函數(shù)實(shí)現(xiàn)。
void expireIfNeeded(redisDb *db, robj *KEY) {
// 1. 獲取鍵的過(guò)期時(shí)間
mstime_t when = getExpire(db,key);
if (when
if (when
// 2. 刪除過(guò)期鍵
deleteKey(db,key);
} else {
// 3. 將過(guò)期鍵添加到過(guò)期時(shí)間字典中
if (activeExpireEnabled())
dictAdd(db->expires,key,(void*)when);
}
}
在Redis server.c中,expireIfNeeded函數(shù)被調(diào)用的地方主要有兩處:鍵值操作命令和定時(shí)器從定時(shí)器表中移除。
鍵值操作命令會(huì)調(diào)用lookupKey和expireIfNeeded函數(shù),獲取鍵的過(guò)期時(shí)間并添加到過(guò)期時(shí)間字典中;同時(shí),當(dāng)鍵值操作命令執(zhí)行完畢后,還需要調(diào)用activeExpireCycle函數(shù),掃描過(guò)期時(shí)間字典,并刪除過(guò)期鍵。
int expireIfNeeded(redisDb *db, robj *key) {
if (expireIfNeededByType(db, key, getExpire(db, key), ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP) == 1)
return 1;
return 0;
}
void activeExpireCycle(void) {
int j;
dictEntry *de;
// 1. 記錄掃描次數(shù)
long long now = mstime();
server.expire_cursor = (server.expire_cursor+1) % ACTIVE_EXPIRE_CYCLE_SLOW_TICKS_PER_FAST;
if (server.expire_cursor == 0) server.current_tick = getLRUClock();
// 2. 計(jì)算隨機(jī)值
int samples = server.active_expire_cycle_lookups_per_tick;
if (dictSize(server.db[0]->expires)
samples = dictSize(server.db[0]->expires);
// 3. 遍歷過(guò)期時(shí)間字典,刪除過(guò)期鍵
while(samples--) {
de = dictGetRandomKey(server.db[0]->expires);
if (!de) break;
robj *key = dictGetKey(de);
if (lookupKey(server.db[0], key) != NULL) {
time_t t;
// 4. 獲取鍵的過(guò)期時(shí)間
mstime_t when = (time_t) dictGetVal(de);
// 5. 隨機(jī)清除過(guò)期鍵
if (when
server.stat_expiredkeys++;
activeExpireCycleTryExpire(&t, key, de);
// 6. 記錄刪除操作
server.dirty++;
/* always re-hash here */
signalModifiedKey(NULL,key);
notifyKeyspaceEvent(NOTIFY_GENERIC,"expired",key,server.dbnum);
// 7. 如果刪除的鍵為AOF未記錄的鍵,則在AOF文件中記錄刪除命令
if (server.aof_state != AOF_OFF)
feedAppendOnlyFile(server.delCommand,server.dbnum,&key,1);
}
}
}
}
三、 redis過(guò)期場(chǎng)景
1. 緩存清理
在進(jìn)行緩存設(shè)計(jì)時(shí),我們通常將最近使用的數(shù)據(jù)緩存下來(lái),以提升系統(tǒng)讀取速度。但當(dāng)緩存中的數(shù)據(jù)過(guò)期時(shí),需要及時(shí)清除,否則會(huì)出現(xiàn)內(nèi)存占用過(guò)多的問(wèn)題。因此,我們需要使用Redis的過(guò)期機(jī)制,設(shè)置過(guò)期時(shí)間,在過(guò)期時(shí)間到達(dá)后,Redis自動(dòng)清除過(guò)期數(shù)據(jù)。
// 存入緩存數(shù)據(jù),并設(shè)定過(guò)期時(shí)間
redisTemplate.opsForValue().set("cache_key", "cache_value", 1, TimeUnit.MINUTES);
// 獲取緩存數(shù)據(jù)
String cacheValue = redisTemplate.opsForValue().get("cache_key");
2. 分布式鎖自動(dòng)釋放
在分布式應(yīng)用場(chǎng)景中,我們通常使用分布式鎖來(lái)避免多個(gè)線程訪問(wèn)共享資源的問(wèn)題。但當(dāng)某個(gè)線程因?yàn)榉?wù)器故障或異常退出時(shí),分布式鎖需要自動(dòng)釋放,否則會(huì)導(dǎo)致死鎖等問(wèn)題。因此,我們可以使用Redis的過(guò)期機(jī)制,為分布式鎖添加過(guò)期時(shí)間,當(dāng)分布式鎖過(guò)期時(shí),Redis自動(dòng)釋放分布式鎖。
// 獲取分布式鎖
Boolean locked = redisTemplate.execute(
new RedisCallback() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
// SETNX命令: 嘗試獲取分布式鎖
Boolean locked = redisConnection.setNX("my_lock".getBytes(), "true".getBytes());
if (locked) {
// 當(dāng)獲取到鎖后,為鎖添加過(guò)期時(shí)間60秒
redisConnection.expire("my_lock".getBytes(), 60);
}
return locked;
}
}
);
四、總結(jié)
Redis的過(guò)期機(jī)制可以在數(shù)據(jù)過(guò)期時(shí)自動(dòng)清除,避免了手動(dòng)清除過(guò)期數(shù)據(jù)的煩惱。在實(shí)際應(yīng)用中,我們需要選擇合適的過(guò)期策略,并根據(jù)實(shí)際場(chǎng)景對(duì)Redis過(guò)期策略進(jìn)行調(diào)優(yōu)。同時(shí),我們也需要注意分布式鎖的自動(dòng)釋放問(wèn)題,避免死鎖等問(wèn)題。
成都創(chuàng)新互聯(lián)科技公司主營(yíng):網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、小程序制作、成都軟件開(kāi)發(fā)、網(wǎng)頁(yè)設(shè)計(jì)、微信開(kāi)發(fā)、成都小程序開(kāi)發(fā)、網(wǎng)站制作、網(wǎng)站開(kāi)發(fā)等業(yè)務(wù),是專業(yè)的成都做小程序公司、成都網(wǎng)站建設(shè)公司、成都做網(wǎng)站的公司。創(chuàng)新互聯(lián)公司集小程序制作創(chuàng)意,網(wǎng)站制作策劃,畫(huà)冊(cè)、網(wǎng)頁(yè)、VI設(shè)計(jì),網(wǎng)站、軟件、微信、小程序開(kāi)發(fā)于一體。
當(dāng)前題目:Redis過(guò)期場(chǎng)景實(shí)現(xiàn)有效的自動(dòng)清理(redis過(guò)期場(chǎng)景)
當(dāng)前URL:http://www.5511xx.com/article/dpoeipj.html


咨詢
建站咨詢
