redis數(shù)據(jù)過(guò)期時(shí)間設(shè)置

redis數(shù)據(jù)過(guò)期時(shí)間設(shè)置

1、redis中key的的過(guò)期時(shí)間

通過(guò)EXPIRE key seconds命令來(lái)設(shè)置數(shù)據(jù)的過(guò)期時(shí)間。返回1表明設(shè)置成功,返回0表明key不存在或者不能成功設(shè)置過(guò)期時(shí)間。在key上設(shè)置了過(guò)期時(shí)間后key將在指定的秒數(shù)后被自動(dòng)刪除。被指定了過(guò)期時(shí)間的key在Redis中被稱為是不穩(wěn)定的。

推薦:redis入門(mén)教程

當(dāng)key被DEL命令刪除或者被SET、GETSET命令重置后與之關(guān)聯(lián)的過(guò)期時(shí)間會(huì)被清除

127.0.0.1:6379>?setex?s?20?1 OK 127.0.0.1:6379>?ttl?s (integer)?17 127.0.0.1:6379>?setex?s?200?1 OK 127.0.0.1:6379>?ttl?s (integer)?195 127.0.0.1:6379>?setrange?s?3?100 (integer)?6 127.0.0.1:6379>?ttl?s (integer)?152 127.0.0.1:6379>?get?s "1x00x00100" 127.0.0.1:6379>?ttl?s (integer)?108 127.0.0.1:6379>?getset?s?200 "1x00x00100" 127.0.0.1:6379>?get?s "200" 127.0.0.1:6379>?ttl?s (integer)?-1

使用PERSIST可以清除過(guò)期時(shí)間

127.0.0.1:6379>?setex?s?100?test OK 127.0.0.1:6379>?get?s "test" 127.0.0.1:6379>?ttl?s (integer)?94 127.0.0.1:6379>?type?s string 127.0.0.1:6379>?strlen?s (integer)?4 127.0.0.1:6379>?persist?s (integer)?1 127.0.0.1:6379>?ttl?s (integer)?-1 127.0.0.1:6379>?get?s "test"

使用rename只是改了key值

127.0.0.1:6379>?expire?s?200 (integer)?1 127.0.0.1:6379>?ttl?s (integer)?198 127.0.0.1:6379>?rename?s?ss OK 127.0.0.1:6379>?ttl?ss (integer)?187 127.0.0.1:6379>?type?ss string 127.0.0.1:6379>?get?ss "test"

說(shuō)明:Redis2.6以后expire精度可以控制在0到1毫秒內(nèi),key的過(guò)期信息以絕對(duì)unix時(shí)間戳的形式存儲(chǔ)(Redis2.6之后以毫秒級(jí)別的精度存儲(chǔ)),所以在多服務(wù)器同步的時(shí)候,一定要同步各個(gè)服務(wù)器的時(shí)間

2、Redis過(guò)期鍵刪除策略

Redis key過(guò)期的方式有三種:

(1)、被動(dòng)刪除:當(dāng)讀/寫(xiě)一個(gè)已經(jīng)過(guò)期的key時(shí),會(huì)觸發(fā)惰性刪除策略,直接刪除掉這個(gè)過(guò)期key

(2)、主動(dòng)刪除:由于惰性刪除策略無(wú)法保證冷數(shù)據(jù)被及時(shí)刪掉,所以Redis會(huì)定期主動(dòng)淘汰一批已過(guò)期的key

(3)、當(dāng)前已用內(nèi)存超過(guò)maxmemory限定時(shí),觸發(fā)主動(dòng)清理策略

被動(dòng)刪除

只有key被操作時(shí)(如GET),REDIS才會(huì)被動(dòng)檢查該key是否過(guò)期,如果過(guò)期則刪除之并且返回nil

1、這種刪除策略對(duì)CPU是友好的,刪除操作只有在不得不的情況下才會(huì)進(jìn)行,不會(huì)其他的expire key上浪費(fèi)無(wú)謂的CPU時(shí)間。

2、但是這種策略對(duì)內(nèi)存不友好,一個(gè)key已經(jīng)過(guò)期,但是在它被操作之前不會(huì)被刪除,仍然占據(jù)內(nèi)存空間。如果有大量的過(guò)期鍵存在但是又很少被訪問(wèn)到,那會(huì)造成大量的內(nèi)存空間浪費(fèi)。expireIfNeeded(redisDb *db, robj *key)函數(shù)位于src/db.c。

/*----------------------------------------------------------------------------- ?*?Expires?API ?*----------------------------------------------------------------------------*/ ? int?removeExpire(redisDb?*db,?robj?*key)?{ ????/*?An?expire?may?only?be?removed?if?there?is?a?corresponding?entry?in?the ?????*?main?dict.?Otherwise,?the?key?will?never?be?freed.?*/ ????redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr)?!=?NULL); ????return?dictDelete(db->expires,key->ptr)?==?DICT_OK; } ? void?setExpire(redisDb?*db,?robj?*key,?long?long?when)?{ ????dictEntry?*kde,?*de; ? ????/*?Reuse?the?sds?from?the?main?dict?in?the?expire?dict?*/ ????kde?=?dictFind(db->dict,key->ptr); ????redisAssertWithInfo(NULL,key,kde?!=?NULL); ????de?=?dictReplaceRaw(db->expires,dictGetKey(kde)); ????dictSetSignedIntegerVal(de,when); } ? /*?Return?the?expire?time?of?the?specified?key,?or?-1?if?no?expire ?*?is?associated?with?this?key?(i.e.?the?key?is?non?volatile)?*/ long?long?getExpire(redisDb?*db,?robj?*key)?{ ????dictEntry?*de; ? ????/*?No?expire??return?ASAP?*/ ????if?(dictSize(db->expires)?==?0?|| ???????(de?=?dictFind(db->expires,key->ptr))?==?NULL)?return?-1; ? ????/*?The?entry?was?found?in?the?expire?dict,?this?means?it?should?also ?????*?be?present?in?the?main?dict?(safety?check).?*/ ????redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr)?!=?NULL); ????return?dictGetSignedIntegerVal(de); } ? /*?Propagate?expires?into?slaves?and?the?AOF?file. ?*?When?a?key?expires?in?the?master,?a?DEL?operation?for?this?key?is?sent ?*?to?all?the?slaves?and?the?AOF?file?if?enabled. ?* ?*?This?way?the?key?expiry?is?centralized?in?one?place,?and?since?both ?*?AOF?and?the?master->slave?link?guarantee?operation?ordering,?everything ?*?will?be?consistent?even?if?we?allow?write?operations?against?expiring ?*?keys.?*/ void?propagateExpire(redisDb?*db,?robj?*key)?{ ????robj?*argv[2]; ? ????argv[0]?=?shared.del; ????argv[1]?=?key; ????incrRefCount(argv[0]); ????incrRefCount(argv[1]); ? ????if?(server.aof_state?!=?REDIS_AOF_OFF) ????????feedAppendOnlyFile(server.delCommand,db->id,argv,2); ????replicationFeedSlaves(server.slaves,db->id,argv,2); ? ????decrRefCount(argv[0]); ????decrRefCount(argv[1]); } ? int?expireIfNeeded(redisDb?*db,?robj?*key)?{ ????mstime_t?when?=?getExpire(db,key); ????mstime_t?now; ? ????if?(when??when; ? ????/*?Return?when?this?key?has?not?expired?*/ ????if?(now?id); ????return?dbDelete(db,key); } ? /*----------------------------------------------------------------------------- ?*?Expires?Commands ?*----------------------------------------------------------------------------*/ ? /*?This?is?the?generic?command?implementation?for?EXPIRE,?PEXPIRE,?EXPIREAT ?*?and?PEXPIREAT.?Because?the?commad?second?argument?may?be?relative?or?absolute ?*?the?"basetime"?argument?is?used?to?signal?what?the?base?time?is?(either?0 ?*?for?*AT?variants?of?the?command,?or?the?current?time?for?relative?expires). ?* ?*?unit?is?either?UNIT_SECONDS?or?UNIT_MILLISECONDS,?and?is?only?used?for ?*?the?argv[2]?parameter.?The?basetime?is?always?specified?in?milliseconds.?*/ void?expireGenericCommand(redisClient?*c,?long?long?basetime,?int?unit)?{ ????robj?*key?=?c->argv[1],?*param?=?c->argv[2]; ????long?long?when;?/*?unix?time?in?milliseconds?when?the?key?will?expire.?*/ ? ????if?(getLongLongFromObjectOrReply(c,?param,?&when,?NULL)?!=?REDIS_OK) ????????return; ? ????if?(unit?==?UNIT_SECONDS)?when?*=?1000; ????when?+=?basetime; ? ????/*?No?key,?return?zero.?*/ ????if?(lookupKeyRead(c->db,key)?==?NULL)?{ ????????addReply(c,shared.czero); ????????return; ????} ? ????/*?EXPIRE?with?negative?TTL,?or?EXPIREAT?with?a?timestamp?into?the?past ?????*?should?never?be?executed?as?a?DEL?when?load?the?AOF?or?in?the?context ?????*?of?a?slave?instance. ?????* ?????*?Instead?we?take?the?other?branch?of?the?IF?statement?setting?an?expire ?????*?(possibly?in?the?past)?and?wait?for?an?explicit?DEL?from?the?master.?*/ ????if?(when?db,key)); ????????server.dirty++; ? ????????/*?Replicate/AOF?this?as?an?explicit?DEL.?*/ ????????aux?=?createStringObject("DEL",3); ????????rewriteClientCommandVector(c,2,aux,key); ????????decrRefCount(aux); ????????signalModifiedKey(c->db,key); ????????notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",key,c->db->id); ????????addReply(c,?shared.cone); ????????return; ????}?else?{ ????????setExpire(c->db,key,when); ????????addReply(c,shared.cone); ????????signalModifiedKey(c->db,key); ????????notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"expire",key,c->db->id); ????????server.dirty++; ????????return; ????} } ? void?expireCommand(redisClient?*c)?{ ????expireGenericCommand(c,mstime(),UNIT_SECONDS); } ? void?expireatCommand(redisClient?*c)?{ ????expireGenericCommand(c,0,UNIT_SECONDS); } ? void?pexpireCommand(redisClient?*c)?{ ????expireGenericCommand(c,mstime(),UNIT_MILLISECONDS); } ? void?pexpireatCommand(redisClient?*c)?{ ????expireGenericCommand(c,0,UNIT_MILLISECONDS); } ? void?ttlGenericCommand(redisClient?*c,?int?output_ms)?{ ????long?long?expire,?ttl?=?-1; ? ????/*?If?the?key?does?not?exist?at?all,?return?-2?*/ ????if?(lookupKeyRead(c->db,c->argv[1])?==?NULL)?{ ????????addReplyLongLong(c,-2); ????????return; ????} ????/*?The?key?exists.?Return?-1?if?it?has?no?expire,?or?the?actual ?????*?TTL?value?otherwise.?*/ ????expire?=?getExpire(c->db,c->argv[1]); ????if?(expire?!=?-1)?{ ????????ttl?=?expire-mstime(); ????????if?(ttl?db->dict,c->argv[1]->ptr); ????if?(de?==?NULL)?{ ????????addReply(c,shared.czero); ????}?else?{ ????????if?(removeExpire(c->db,c->argv[1]))?{ ????????????addReply(c,shared.cone); ????????????server.dirty++; ????????}?else?{ ????????????addReply(c,shared.czero); ????????} ????} }

但僅是這樣是不夠的,因?yàn)榭赡艽嬖谝恍﹌ey永遠(yuǎn)不會(huì)被再次訪問(wèn)到,這些設(shè)置了過(guò)期時(shí)間的key也是需要在過(guò)期后被刪除的,我們甚至可以將這種情況看作是一種內(nèi)存泄露—-無(wú)用的垃圾數(shù)據(jù)占用了大量的內(nèi)存,而服務(wù)器卻不會(huì)自己去釋放它們,這對(duì)于運(yùn)行狀態(tài)非常依賴于內(nèi)存的Redis服務(wù)器來(lái)說(shuō),肯定不是一個(gè)好消息

主動(dòng)刪除

先說(shuō)一下時(shí)間事件,對(duì)于持續(xù)運(yùn)行的服務(wù)器來(lái)說(shuō), 服務(wù)器需要定期對(duì)自身的資源和狀態(tài)進(jìn)行必要的檢查和整理, 從而讓服務(wù)器維持在一個(gè)健康穩(wěn)定的狀態(tài), 這類操作被統(tǒng)稱為常規(guī)操作(cron job)

在 Redis 中, 常規(guī)操作由?redis.c/serverCron?實(shí)現(xiàn), 它主要執(zhí)行以下操作:

更新服務(wù)器的各類統(tǒng)計(jì)信息,比如時(shí)間、內(nèi)存占用、數(shù)據(jù)庫(kù)占用情況等。

清理數(shù)據(jù)庫(kù)中的過(guò)期鍵值對(duì)。

對(duì)不合理的數(shù)據(jù)庫(kù)進(jìn)行大小調(diào)整。

關(guān)閉和清理連接失效的客戶端。

嘗試進(jìn)行 AOF 或 RDB 持久化操作。

如果服務(wù)器是主節(jié)點(diǎn)的話,對(duì)附屬節(jié)點(diǎn)進(jìn)行定期同步。

如果處于集群模式的話,對(duì)集群進(jìn)行定期同步和連接測(cè)試。

Redis 將?serverCron?作為時(shí)間事件來(lái)運(yùn)行, 從而確保它每隔一段時(shí)間就會(huì)自動(dòng)運(yùn)行一次, 又因?yàn)?serverCron?需要在 Redis 服務(wù)器運(yùn)行期間一直定期運(yùn)行, 所以它是一個(gè)循環(huán)時(shí)間事件:?serverCron?會(huì)一直定期執(zhí)行,直到服務(wù)器關(guān)閉為止。

在 Redis 2.6 版本中, 程序規(guī)定?serverCron?每秒運(yùn)行?10?次, 平均每?100?毫秒運(yùn)行一次。 從 Redis 2.8 開(kāi)始, 用戶可以通過(guò)修改?hz選項(xiàng)來(lái)調(diào)整?serverCron?的每秒執(zhí)行次數(shù)。

也叫定時(shí)刪除,這里的“定期”指的是Redis定期觸發(fā)的清理策略,由位于src/redis.c的activeExpireCycle(void)函數(shù)來(lái)完成。

serverCron是由redis的事件框架驅(qū)動(dòng)的定位任務(wù),這個(gè)定時(shí)任務(wù)中會(huì)調(diào)用activeExpireCycle函數(shù),針對(duì)每個(gè)db在限制的時(shí)間REDIS_EXPIRELOOKUPS_TIME_LIMIT內(nèi)遲可能多的刪除過(guò)期key,之所以要限制時(shí)間是為了防止過(guò)長(zhǎng)時(shí)間 的阻塞影響redis的正常運(yùn)行。這種主動(dòng)刪除策略彌補(bǔ)了被動(dòng)刪除策略在內(nèi)存上的不友好。

因此,Redis會(huì)周期性的隨機(jī)測(cè)試一批設(shè)置了過(guò)期時(shí)間的key并進(jìn)行處理。測(cè)試到的已過(guò)期的key將被刪除。典型的方式為,Redis每秒做10次如下的步驟:

(1)隨機(jī)測(cè)試100個(gè)設(shè)置了過(guò)期時(shí)間的key

(2)刪除所有發(fā)現(xiàn)的已過(guò)期的key

(3)若刪除的key超過(guò)25個(gè)則重復(fù)步驟1

這是一個(gè)基于概率的簡(jiǎn)單算法,基本的假設(shè)是抽出的樣本能夠代表整個(gè)key空間,redis持續(xù)清理過(guò)期的數(shù)據(jù)直至將要過(guò)期的key的百分比降到了25%以下。這也意味著在任何給定的時(shí)刻已經(jīng)過(guò)期但仍占據(jù)著內(nèi)存空間的key的量最多為每秒的寫(xiě)操作量除以4.

Redis-3.0.0中的默認(rèn)值是10,代表每秒鐘調(diào)用10次后臺(tái)任務(wù)。?

除了主動(dòng)淘汰的頻率外,Redis對(duì)每次淘汰任務(wù)執(zhí)行的最大時(shí)長(zhǎng)也有一個(gè)限定,這樣保證了每次主動(dòng)淘汰不會(huì)過(guò)多阻塞應(yīng)用請(qǐng)求,以下是這個(gè)限定計(jì)算公式:

#define?ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC?25?/*?CPU?max?%?for?keys?collection?*/? ...? timelimit?=?1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;

hz調(diào)大將會(huì)提高Redis主動(dòng)淘汰的頻率,如果你的Redis存儲(chǔ)中包含很多冷數(shù)據(jù)占用內(nèi)存過(guò)大的話,可以考慮將這個(gè)值調(diào)大,但Redis作者建議這個(gè)值不要超過(guò)100。我們實(shí)際線上將這個(gè)值調(diào)大到100,觀察到CPU會(huì)增加2%左右,但對(duì)冷數(shù)據(jù)的內(nèi)存釋放速度確實(shí)有明顯的提高(通過(guò)觀察keyspace個(gè)數(shù)和used_memory大小)。?

可以看出timelimit和server.hz是一個(gè)倒數(shù)的關(guān)系,也就是說(shuō)hz配置越大,timelimit就越小。換句話說(shuō)是每秒鐘期望的主動(dòng)淘汰頻率越高,則每次淘汰最長(zhǎng)占用時(shí)間就越短。這里每秒鐘的最長(zhǎng)淘汰占用時(shí)間是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰頻率和每次淘汰的最長(zhǎng)時(shí)間是通過(guò)hz參數(shù)控制的。?

從以上的分析看,當(dāng)redis中的過(guò)期key比率沒(méi)有超過(guò)25%之前,提高h(yuǎn)z可以明顯提高掃描key的最小個(gè)數(shù)。假設(shè)hz為10,則一秒內(nèi)最少掃描200個(gè)key(一秒調(diào)用10次*每次最少隨機(jī)取出20個(gè)key),如果hz改為100,則一秒內(nèi)最少掃描2000個(gè)key;另一方面,如果過(guò)期key比率超過(guò)25%,則掃描key的個(gè)數(shù)無(wú)上限,但是cpu時(shí)間每秒鐘最多占用250ms。?

當(dāng)REDIS運(yùn)行在主從模式時(shí),只有主結(jié)點(diǎn)才會(huì)執(zhí)行上述這兩種過(guò)期刪除策略,然后把刪除操作”del key”同步到從結(jié)點(diǎn)。

maxmemory

當(dāng)前已用內(nèi)存超過(guò)maxmemory限定時(shí),觸發(fā)主動(dòng)清理策略:

volatile-lru:只對(duì)設(shè)置了過(guò)期時(shí)間的key進(jìn)行LRU(默認(rèn)值)

allkeys-lru : 刪除lru算法的key

volatile-random:隨機(jī)刪除即將過(guò)期key

allkeys-random:隨機(jī)刪除

volatile-ttl : 刪除即將過(guò)期的

noeviction : 永不過(guò)期,返回錯(cuò)誤當(dāng)mem_used內(nèi)存已經(jīng)超過(guò)maxmemory的設(shè)定,對(duì)于所有的讀寫(xiě)請(qǐng)求,都會(huì)觸發(fā)redis.c/freeMemoryIfNeeded(void)函數(shù)以清理超出的內(nèi)存。注意這個(gè)清理過(guò)程是阻塞的,直到清理出足夠的內(nèi)存空間。所以如果在達(dá)到maxmemory并且調(diào)用方還在不斷寫(xiě)入的情況下,可能會(huì)反復(fù)觸發(fā)主動(dòng)清理策略,導(dǎo)致請(qǐng)求會(huì)有一定的延遲。?

當(dāng)mem_used內(nèi)存已經(jīng)超過(guò)maxmemory的設(shè)定,對(duì)于所有的讀寫(xiě)請(qǐng)求,都會(huì)觸發(fā)redis.c/freeMemoryIfNeeded(void)函數(shù)以清理超出的內(nèi)存。注意這個(gè)清理過(guò)程是阻塞的,直到清理出足夠的內(nèi)存空間。所以如果在達(dá)到maxmemory并且調(diào)用方還在不斷寫(xiě)入的情況下,可能會(huì)反復(fù)觸發(fā)主動(dòng)清理策略,導(dǎo)致請(qǐng)求會(huì)有一定的延遲。

清理時(shí)會(huì)根據(jù)用戶配置的maxmemory-policy來(lái)做適當(dāng)?shù)那謇恚ㄒ话闶荓RU或TTL),這里的LRU或TTL策略并不是針對(duì)redis的所有key,而是以配置文件中的maxmemory-samples個(gè)key作為樣本池進(jìn)行抽樣清理。

maxmemory-samples在redis-3.0.0中的默認(rèn)配置為5,如果增加,會(huì)提高LRU或TTL的精準(zhǔn)度,redis作者測(cè)試的結(jié)果是當(dāng)這個(gè)配置為10時(shí)已經(jīng)非常接近全量LRU的精準(zhǔn)度了,并且增加maxmemory-samples會(huì)導(dǎo)致在主動(dòng)清理時(shí)消耗更多的CPU時(shí)間,建議:

(1)盡量不要觸發(fā)maxmemory,最好在mem_used內(nèi)存占用達(dá)到maxmemory的一定比例后,需要考慮調(diào)大hz以加快淘汰,或者進(jìn)行集群擴(kuò)容。

(2)如果能夠控制住內(nèi)存,則可以不用修改maxmemory-samples配置;如果Redis本身就作為L(zhǎng)RU cache服務(wù)(這種服務(wù)一般長(zhǎng)時(shí)間處于maxmemory狀態(tài),由Redis自動(dòng)做LRU淘汰),可以適當(dāng)調(diào)大maxmemory-samples。

以下是上文中提到的配置參數(shù)的說(shuō)明

#?Redis?calls?an?internal?function?to?perform?many?background?tasks,?like? #?closing?connections?of?clients?in?timeout,?purging?expired?keys?that?are? #?never?requested,?and?so?forth.? #? #?Not?all?tasks?are?performed?with?the?same?frequency,?but?Redis?checks?for? #?tasks?to?perform?according?to?the?specified?"hz"?value.? #? #?By?default?"hz"?is?set?to?10.?Raising?the?value?will?use?more?CPU?when? #?Redis?is?idle,?but?at?the?same?time?will?make?Redis?more?responsive?when? #?there?are?many?keys?expiring?at?the?same?time,?and?timeouts?may?be? #?handled?with?more?precision.? #? #?The?range?is?between?1?and?500,?however?a?value?over?100?is?usually?not? #?a?good?idea.?Most?users?should?use?the?default?of?10?and?raise?this?up?to? #?100?only?in?environments?where?very?low?latency?is?required.? hz?10? ? #?MAXMEMORY?POLICY:?how?Redis?will?select?what?to?remove?when?maxmemory? #?is?reached.?You?can?select?among?five?behaviors:? #? #?volatile-lru?->?remove?the?key?with?an?expire?set?using?an?LRU?algorithm? #?allkeys-lru?->?remove?any?key?according?to?the?LRU?algorithm? #?volatile-random?->?remove?a?random?key?with?an?expire?set? #?allkeys-random?->?remove?a?random?key,?any?key? #?volatile-ttl?->?remove?the?key?with?the?nearest?expire?time?(minor?TTL)? #?noeviction?->?don't?expire?at?all,?just?return?an?error?on?write?operations? #? #?Note:?with?any?of?the?above?policies,?Redis?will?return?an?error?on?write? #???????operations,?when?there?are?no?suitable?keys?for?eviction.? #? #???????At?the?date?of?writing?these?commands?are:?set?setnx?setex?append? #???????incr?decr?rpush?lpush?rpushx?lpushx?linsert?lset?rpoplpush?sadd? #???????sinter?sinterstore?sunion?sunionstore?sdiff?sdiffstore?zadd?zincrby? #???????zunionstore?zinterstore?hset?hsetnx?hmset?hincrby?incrby?decrby? #???????getset?mset?msetnx?exec?sort? #? #?The?default?is:? #? maxmemory-policy?noeviction? ? #?LRU?and?minimal?TTL?algorithms?are?not?precise?algorithms?but?approximated? #?algorithms?(in?order?to?save?memory),?so?you?can?tune?it?for?speed?or? #?accuracy.?For?default?Redis?will?check?five?keys?and?pick?the?one?that?was? #?used?less?recently,?you?can?change?the?sample?size?using?the?following? #?configuration?directive.? #? #?The?default?of?5?produces?good?enough?results.?10?Approximates?very?closely? #?true?LRU?but?costs?a?bit?more?CPU.?3?is?very?fast?but?not?very?accurate.? #? maxmemory-samples?5

Replication link和AOF文件中的過(guò)期處理

為了獲得正確的行為而不至于導(dǎo)致一致性問(wèn)題,當(dāng)一個(gè)key過(guò)期時(shí)DEL操作將被記錄在AOF文件并傳遞到所有相關(guān)的slave。也即過(guò)期刪除操作統(tǒng)一在master實(shí)例中進(jìn)行并向下傳遞,而不是各salve各自掌控。

這樣一來(lái)便不會(huì)出現(xiàn)數(shù)據(jù)不一致的情形。當(dāng)slave連接到master后并不能立即清理已過(guò)期的key(需要等待由master傳遞過(guò)來(lái)的DEL操作),slave仍需對(duì)數(shù)據(jù)集中的過(guò)期狀態(tài)進(jìn)行管理維護(hù)以便于在slave被提升為master會(huì)能像master一樣獨(dú)立的進(jìn)行過(guò)期處理。

以上就是

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊6 分享