redis淘汰策略的幾種實(shí)現(xiàn)
redis內(nèi)存數(shù)據(jù)數(shù)據(jù)集大小升到一定大的時(shí)候,就會(huì)實(shí)行數(shù)據(jù)淘汰策略(回收策略)。
1,volatile-lru:從已設(shè)置過(guò)期時(shí)間的哈希表(server.db[i].expires)中隨機(jī)挑選多個(gè)key,然后在選到的key中用lru算法淘汰最近最少使用的數(shù)據(jù)
2,allkey-lru:從所有key的哈希表(server.db[i].dict)中隨機(jī)挑選多個(gè)key,然后再選到的key中利用lru算法淘汰最近最少使用的數(shù)據(jù)
3,volatile-ttl:從已設(shè)置過(guò)期時(shí)間的哈希表(server.db[i].expires)中隨機(jī)挑選多個(gè)key,然后在選到的key中選擇過(guò)期時(shí)間最小的數(shù)據(jù)淘汰掉。
4,volatile-random:從已設(shè)置過(guò)期時(shí)間的哈希表(server.db[i].expires)中隨機(jī)挑選key淘汰掉。
5,allkey-random:從所有的key的哈希表(server.db[i].dict)中隨機(jī)挑數(shù)據(jù)淘汰
6,no-eviction(驅(qū)逐):內(nèi)存達(dá)到上限,不淘汰數(shù)據(jù)。
redis確認(rèn)驅(qū)逐某個(gè)鍵值對(duì)后,會(huì)刪除這個(gè)數(shù)據(jù),并將這個(gè)數(shù)據(jù)變更消息發(fā)布到本地(AOF持久化)和從機(jī)(主從連接)。
LRU數(shù)據(jù)淘汰機(jī)制是這樣的:在數(shù)據(jù)集中隨機(jī)挑選幾個(gè)鍵值對(duì),去除其中最近最少使用的鍵值對(duì)淘汰。所以Redis并不是保證取得所有數(shù)據(jù)集中最少最少使用的鍵值對(duì),而只是在隨機(jī)挑選的幾個(gè)鍵值對(duì)中。
TTL數(shù)據(jù)淘汰機(jī)制:從國(guó)企時(shí)間redisDB.expires表中隨機(jī)挑選幾個(gè)鍵值對(duì),取出其中最快過(guò)期的鍵值對(duì)淘汰。所以Redis并不保證取得所有過(guò)期時(shí)間表中最快過(guò)期的鍵值對(duì),而是隨機(jī)挑選的幾個(gè)鍵值對(duì)中。
無(wú)論是什么機(jī)制,都是從所有的鍵值對(duì)中挑選合適的淘汰。
在哪里開(kāi)始淘汰數(shù)據(jù):
Redis服務(wù)器每執(zhí)行一次命令的時(shí)候,會(huì)檢測(cè)使用的內(nèi)存是否超額。如果超額,即進(jìn)行數(shù)據(jù)淘汰。
int freeMemoryIfNeeded(void) { /** * noeviction 不淘汰數(shù)據(jù),什么都不做 */ if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION) return C_ERR; while (mem_freed < mem_tofree) { int j, k, keys_freed = 0; for (j = 0; j < server.dbnum; j++) { /** * 選擇操作的哈希表,Redis另外維護(hù)著一個(gè)保存過(guò)期時(shí)間的key=>expire關(guān)聯(lián)的哈希表 */ if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU || server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM) { dict = server.db[j].dict; } else { dict = server.db[j].expires; } /** * 分支一:全局哈希表隨機(jī)或者過(guò)期時(shí)間哈希表中,隨機(jī)淘汰一個(gè)key */ if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM || server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM) { de = dictGetRandomKey(dict); bestkey = dictGetKey(de); } /** * 分支二:全局哈希表隨機(jī)或者過(guò)期時(shí)間哈希表中,隨機(jī)采樣多個(gè)數(shù)據(jù),再運(yùn)用lru算法挑選一個(gè)淘汰 */ else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU || server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU) { /* 樣本集 */ struct evictionPoolEntry *pool = db->eviction_pool; while(bestkey == NULL) { /* * 采樣,更新和維護(hù)樣本集; * 樣本集開(kāi)始是空的,每次操作完并不會(huì)清空樣本集; * 而且每次采樣,都會(huì)采集多個(gè)數(shù)據(jù),同時(shí)和樣本集中已有的數(shù)據(jù)進(jìn)行比較,新增或者更新樣本集; */ evictionPoolPopulate(dict, db->dict, db->eviction_pool); /** * 開(kāi)始對(duì)樣本集使用lru算法,淘汰樣本集中訪問(wèn)時(shí)間最晚的key */ for (k = MAXMEMORY_EVICTION_POOL_SIZE-1; k >= 0; k--) { if (pool[k].key == NULL) continue; de = dictFind(dict,pool[k].key); /* 把選取到的key從樣本集中移除 */ sdsfree(pool[k].key); memmove(pool+k,pool+k+1, sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1)); pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key = NULL; pool[MAXMEMORY_EVICTION_POOL_SIZE-1].idle = 0; /* pool樣本集內(nèi)的key,只是樣本,不一定和db內(nèi)保持一致,也不必,可能在db中已經(jīng)被刪除的,所以要作判斷 */ if (de) { bestkey = dictGetKey(de); break; } else { /* Ghost... */ continue; } } } } /** * 分支三:在設(shè)置了過(guò)期時(shí)間的哈希表里面隨機(jī)選擇多個(gè)key,在挑選到的key中選擇過(guò)期時(shí)間最小的一個(gè)淘汰掉 */ else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) { for (k = 0; k < server.maxmemory_samples; k++) { sds thiskey; long thisval; de = dictGetRandomKey(dict); thiskey = dictGetKey(de); thisval = (long) dictGetVal(de); if (bestkey == NULL || thisval < bestval) { bestkey = thiskey; bestval = thisval; } } } if (bestkey) { long long delta; robj *keyobj = createStringObject(bestkey,sdslen(bestkey)); // 命令擴(kuò)散,把刪除key的命令同步到所有從庫(kù)slave propagateExpire(db,keyobj); // 刪除key dbDelete(db,keyobj); } } } return C_OK; }
到此這篇關(guān)于redis淘汰策略的幾種實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)redis淘汰策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis為什么快如何實(shí)現(xiàn)高可用及持久化
這篇文章主要介紹了Redis為什么快如何實(shí)現(xiàn)高可用及持久化,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12詳解Redis中Lua腳本的應(yīng)用和實(shí)踐
這篇文章主要介紹了詳解Redis中Lua腳本的應(yīng)用和實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01redis中事務(wù)機(jī)制及樂(lè)觀鎖的實(shí)現(xiàn)
這篇文章主要介紹了redis中事務(wù)機(jī)制及樂(lè)觀鎖的相關(guān)內(nèi)容,通過(guò)事務(wù)的執(zhí)行分析Redis樂(lè)觀鎖,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10redis哈希和集合_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了redis哈希和集合的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象的操作方法
這篇文章主要介紹了SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03