新聞中心
Redis是一種高性能鍵值存儲系統(tǒng),以其快速、簡單的功能而受到開發(fā)人員的喜愛。但是在高并發(fā)環(huán)境下,Redis可能會出現(xiàn)過期鍵刪除不及時的問題。為了解決這個問題,Redis通過多線程機(jī)制來實(shí)現(xiàn)過期鍵的刪除。在本文中,我們將深入分析Redis的多線程過期機(jī)制,探索其中的原理和使用方法。

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比興安盟網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式興安盟網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋興安盟地區(qū)。費(fèi)用合理售后完善,十年實(shí)體公司更值得信賴。
一、Redis的過期鍵刪除機(jī)制
Redis通過使用定期器和惰性刪除機(jī)制來處理過期鍵的刪除問題。定期器是一個定時器,每隔一段時間就會遍歷整個鍵空間,判斷鍵是否過期,如果鍵過期,則刪除該鍵。但是,定期器的運(yùn)行時間比較隨機(jī),可能會造成過期鍵刪除不及時的問題。因此,Redis引入了惰性刪除機(jī)制。當(dāng)客戶端請求一個過期鍵時,Redis會檢查該鍵是否過期,如果過期,則刪除該鍵。這種方式雖然有效,但是仍然可能造成一定的延遲。因此,Redis引入了多線程過期機(jī)制來提高過期鍵刪除的效率。
二、Redis的多線程過期機(jī)制
Redis的多線程過期機(jī)制是使用多線程來實(shí)現(xiàn)過期鍵的刪除。當(dāng)需要刪除一個過期鍵時,Redis會將該鍵添加到一個專門的過期鍵列表中。過期鍵列表是一個內(nèi)存緩沖區(qū),Redis會對這個緩沖區(qū)進(jìn)行定期刷盤,把列表中的過期鍵持久化到磁盤。在實(shí)際刪除過期鍵時,Redis會啟動多個后臺線程來處理過期鍵列表中的鍵。當(dāng)一個線程完成一個鍵的刪除任務(wù)時,會重新從過期鍵列表中獲取一個鍵并開始刪除。這種方式可以充分利用CPU資源,提高過期鍵刪除的效率。
三、Redis的過期鍵刪除過程
1. 添加過期鍵
當(dāng)一個鍵過期時,Redis會將該鍵添加到過期鍵列表中,以備后續(xù)刪除。過期鍵列表是一個FifO隊(duì)列。
“`c
//redis/src/db.c
int expireIfNeeded(redisDb *db, robj *key) {
time_t when = getExpire(db,key);
mstime_t now;
long long delta;
/* 剩余時間 */
if (when
now = mstime();
if (now
/* 添加過期鍵 */
delta = (long long)(when-now);
/* milliseconds級別 */
addReplyProto(c,shared.colon,cshared.colonlen);
addReplyLongLong(c, delta);
addReplyNewline(c);
/* Add the key to the expiring_keys list if needed. */
if (server.active_expire_enabled) {
if (dictAdd(db->expires,key,(void*)REDIS_EXPIRE_DONT_SET) == DICT_OK) {
incrRefCount(key);
listAddNodeHead(server.delKeysSchedule, key);
}
}
return 1;
}
2. 定期刷盤
為了避免系統(tǒng)宕機(jī)導(dǎo)致過期鍵列表丟失,Redis會對過期鍵列表進(jìn)行定期刷盤操作。定期刷盤可以通過配置參數(shù)來設(shè)置,配置文件中的相關(guān)配置如下:
```bash
################################ SNAPSHOTTING ################################
# save
save 900 1
save 300 10
save 60 10000
#
# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save fled.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background save process will start working agn Redis will
# automatically allow writes agn.
#
# However if you have multiple Redis instances, disable this feature since
# it could trigger a network partition flure.
stop-writes-on-bgsave-error yes
#
# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes
在定期器中,Redis會對過期鍵列表進(jìn)行定時抽取和持久化操作。如下:
“`c
//redis/src/ae.c
void aeTimerProc(struct aeEventLoop *eventLoop, long long id, void *clientData) {
int j;
char buf[64];
if (cluster.enabled) clusterCron();
if (server.lua_timedout) handleLuaTimeout();
if (server.cluster_enabled) {
/* Make sure nodes are pinging or having PONG replies on time. */
clusterCheckPingTimeouts();
/* If a new node was recently added, join it to the cluster. */
clusterJoinCluster();
}
/* 定期器任務(wù) */
serverCron();
/* 更新系統(tǒng)時間 */
server.lruclock = getLRUClock();
/* Increment the fast memory allocator’s internal clock. */
if (server.use_tcmalloc) {
memory_tcmalloc_release_free_memory();
}
/* 刷盤 */
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
for (j = 0; j
struct saveparam *sp = server.saveparams+j;
time_t now = time(NULL);
char *reason;
int retval;
if (sp->lastsave
(now – sp->lastsave > sp->seconds ||
dirty >= sp->changes)) {
serverLog(LL_NOTICE,”Saving (%s)%s DB due to %s…”,
sp->forced?(“forced “):””,sp->kind,
sp->changes?”changes”:”time”);
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
reason = (sp->changes && sp->seconds) ?
“of DB changes exceed” : “of elapsed time”;
retval = rdbSaveBackground(server.rdb_filename);
if (retval == REDIS_OK) {
server.dirty = 0;
server.lastsave = time(NULL);
snprintf(buf,sizeof(buf),”%ld”,server.lastsave);
setGlobalKey(“redis:lastsave”,createStringObject(buf,strlen(buf)));
server.lastbgsave_status = REDIS_OK;
server.lastbgsave_time_start = server.unixtime;
server.lastbgsave_time_end = (time_t)-1;
if (sp->forced) serverLog(LL_WARNING,”Background save terminated by signal %d”, WTERMSIG(retval));
} else {
server.lastbgsave_status = REDIS_ERR;
if (sp->forced) {
serverLog(LL_WARNING,”Background save terminated by signal %d”, WTERMSIG(retval));
} else {
serverLog(LL_WARNING,”Background saving error”);
}
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
if (retval == REDIS_EIO) serverLog(LL_WARNING,”IO error background saving DB, can’t persist!”);
else if (retval == REDIS_EPERM) {
serverLog(LL_WARNING,”No permission to write on the disk, can’t persist! “\
“Check the permissions and ownership of the dump.rdb file and its parent directory.”);
} else {
serverLog(LL_WARNING,”Unknown error background saving DB”);
}
}
}
}
break;
}
}
}
/* Best effort handle of signals received by the parent while wting
* child processes in background. */
handleChildrenSignals();
}
3. 后臺刪除過期鍵
在Redis多線程過期機(jī)制中,后臺線程是負(fù)責(zé)刪除過期鍵的工作線程。后臺線程的數(shù)量可以通過配置文件中的`maxmemory-samples`參數(shù)來設(shè)置,該參數(shù)也可作為過期鍵列表的長度。配置文件中的相關(guān)配置如下:
```bash
################################## MEMORY MANAGEMENT ###################################
# Max number of fields per Redis hash
hash-max-ziplist-entries 512
# Max bytes of strings encoded with Redis on-heap datastructures
# (e.g. 'set foo "bar"') & hash keys. The limit is set (by default)
# at 512MB which is an insane amount. To use it a server with a lot
# of memory is needed, but such a server would waste a lot of memory
# if not used.
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
新聞標(biāo)題:深入分析Redis多線程過期機(jī)制(redis過期多線程)
鏈接地址:http://m.fisionsoft.com.cn/article/cdosooi.html


咨詢
建站咨詢
