這篇“redis的過期策略和內(nèi)存淘汰策略怎么用”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Redis的過期策略和內(nèi)存淘汰策略怎么用”文章吧。
10年積累的成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有大東免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
expire key seconds 時(shí)間復(fù)雜度:O(1)
設(shè)置key
的過期時(shí)間。超時(shí)后,將會(huì)自動(dòng)刪除該key
。在Redis的術(shù)語中一個(gè)key
的相關(guān)超時(shí)是volatile的。
超時(shí)后只有對(duì)key
執(zhí)行DEL、SET、GETSET時(shí)才會(huì)清除。 這意味著,從概念上講所有改變key
而不用新值替換的所有操作都將保持超時(shí)不變。 例如,使用 INCR
遞增key的值,執(zhí)行 LPUSH
將新值推到 list 中或用 HSET
改變hash的field
,這些操作都使超時(shí)保持不變。
使用 PERSIST
命令可以清除超時(shí),使其變成一個(gè)永久key
若 key
被 RENAME
命令修改,相關(guān)的超時(shí)時(shí)間會(huì)轉(zhuǎn)移到新key
若 key
被 RENAME
命令修改,比如原來就存在 Key_A
,然后調(diào)用 RENAME Key_B Key_A
命令,這時(shí)不管原來 Key_A
是永久的還是設(shè)為超時(shí)的,都會(huì)由Key_B
的有效期狀態(tài)覆蓋
注意,使用非正超時(shí)調(diào)用 EXPIRE/PEXPIRE 或具有過去時(shí)間的 EXPIREAT/PEXPIREAT 將導(dǎo)致key被刪除而不是過期(因此,發(fā)出的key事件將是 del,而不是過期)。
對(duì)已經(jīng)有過期時(shí)間的key
執(zhí)行EXPIRE
操作,將會(huì)更新它的過期時(shí)間。有很多應(yīng)用有這種業(yè)務(wù)場景,例如記錄會(huì)話的session。
在 Redis 版本之前 2.1.3 中,使用更改其值的命令更改具有過期集的密鑰具有完全刪除key的效果。由于現(xiàn)在修復(fù)的復(fù)制層中存在限制,因此需要此語義。
EXPIRE 將返回 0,并且不會(huì)更改具有超時(shí)集的鍵的超時(shí)。
1
如果成功設(shè)置過期時(shí)間。
0
如果key
不存在或者不能設(shè)置過期時(shí)間。
假設(shè)有一 Web 服務(wù),對(duì)用戶最近訪問的最新 N 頁感興趣,這樣每個(gè)相鄰頁面視圖在上一個(gè)頁面之后不超過 60 秒。從概念上講,可以將這組頁面視圖視為用戶的導(dǎo)航會(huì)話,該會(huì)話可能包含有關(guān)ta當(dāng)前正在尋找的產(chǎn)品的有趣信息,以便你可以推薦相關(guān)產(chǎn)品。
可使用以下策略輕松在 Redis 中對(duì)此模式建模:每次用戶執(zhí)行頁面視圖時(shí),您都會(huì)調(diào)用以下命令:
MULTI RPUSH pagewviews.user:http://..... EXPIRE pagewviews.user: 60 EXEC
如果用戶空閑超過 60 秒,則將刪除該key,并且僅記錄差異小于 60 秒的后續(xù)頁面視圖。 此模式很容易修改,使用 INCR 而不是使用 RPUSH 的列表。
通常,創(chuàng)建 Redis 鍵時(shí)沒有關(guān)聯(lián)的存活時(shí)間。key將永存,除非用戶以顯式方式(例如 DEL 命令)將其刪除。 EXPIRE 族的命令能夠?qū)⑦^期項(xiàng)與給定key關(guān)聯(lián),但代價(jià)是該key使用的額外內(nèi)存。當(dāng)key具有過期集時(shí),Redis 將確保在經(jīng)過指定時(shí)間時(shí)刪除該key。 可使用 EXPIRE 和 PERSIST 命令(或其他嚴(yán)格命令)更新或完全刪除生存的關(guān)鍵時(shí)間。
在 Redis 2.4 中,過期可能不準(zhǔn)確,并且可能介于 0 到 1 秒之間。 由于 Redis 2.6,過期誤差從 0 到 1 毫秒。
過期信息的鍵存儲(chǔ)為絕對(duì) Unix 時(shí)間戳(Redis 版本 2.6 或更高版本為毫秒)。這意味著即使 Redis 實(shí)例不處于活動(dòng)狀態(tài),時(shí)間也在流動(dòng)。 要使過期工作良好,必須穩(wěn)定計(jì)算機(jī)時(shí)間。若將 RDB 文件從兩臺(tái)計(jì)算機(jī)上移動(dòng),其時(shí)鐘中具有大 desync,則可能會(huì)發(fā)生有趣的事情(如加載時(shí)加載到過期的所有key)。 即使運(yùn)行時(shí)的實(shí)例,也始終會(huì)檢查計(jì)算機(jī)時(shí)鐘,例如,如果將一個(gè)key設(shè)置為 1000 秒,然后在將來設(shè)置計(jì)算機(jī)時(shí)間 2000 秒,則該key將立即過期,而不是持續(xù) 1000 秒。
鍵的過期方式有兩種:被動(dòng)方式 - 惰性刪除,主動(dòng)方式 - 定期刪除。
當(dāng)客戶端嘗試訪問key時(shí),key會(huì)被動(dòng)過期,即Redis會(huì)檢查該key是否設(shè)置了過期時(shí)間,如果過期了就會(huì)刪除,也不會(huì)返回任何東西。 注意并非是key到期了就會(huì)被自動(dòng)刪除,而是當(dāng)查詢?cè)搆ey時(shí),Redis再很懶惰地檢查是否刪除。這和 spring 的延遲初始化有著異曲同工之妙。
當(dāng)然,這是不夠的,因?yàn)橛羞^期的key,永遠(yuǎn)不會(huì)再訪問。無論如何,這些key都應(yīng)過期,因此請(qǐng)定期 Redis 在具有過期集的key之間隨機(jī)測試幾個(gè)key。已過期的所有key將從key空間中刪除。
具體來說,如下 Redis 每秒 10 次:
測試 20 個(gè)帶有過期的隨機(jī)鍵
刪除找到的所有已過期key
如果超過 25% 的key已過期,從步驟 1 重新開始
這是一個(gè)微不足道的概率算法,基本上假設(shè)我們的樣本代表整個(gè)key空間,繼續(xù)過期,直到可能過期的key百分比低于 25%。 這意味著在任何給定時(shí)刻,使用內(nèi)存的已過期的最大鍵量等于最大寫入操作量/秒除以 4。
為了在不犧牲一致性的情況下獲得正確行為,當(dāng)key過期時(shí),DEL 操作將同時(shí)在 AOF 文件中合成并獲取所有附加的從節(jié)點(diǎn)。這樣,過期的這個(gè)處理過程集中到主節(jié)點(diǎn)中,還沒有一致性錯(cuò)誤的可能性。
但是,雖然連接到主節(jié)點(diǎn)的從節(jié)點(diǎn)不會(huì)獨(dú)立過期key(但會(huì)等待來自master的 DEL),但它們?nèi)詫⑹褂脭?shù)據(jù)集中現(xiàn)有過期的完整狀態(tài),因此,當(dāng)選擇slave作為master時(shí),它將能夠獨(dú)立過期key,完全充當(dāng)master。
可是,很多過期key,你沒及時(shí)去查,定期刪除也漏掉了,大量過期key堆積內(nèi)存,Redis內(nèi)存殆耗盡!
因此還需有內(nèi)存淘汰機(jī)制!
不會(huì)繼續(xù)服務(wù)寫請(qǐng)求 (DEL 請(qǐng)求可以繼續(xù)服務(wù)),讀請(qǐng)求可以繼續(xù)進(jìn)行。這樣 可以保證不會(huì)丟失數(shù)據(jù),但是會(huì)讓線上的業(yè)務(wù)不能持續(xù)進(jìn)行。
config.c
createEnumConfig("maxmemory-policy", NULL, MODIFIABLE_CONFIG, maxmemory_policy_enum, server.maxmemory_policy, MAXMEMORY_NO_EVICTION, NULL, NULL),
當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在鍵空間中,隨機(jī)移除某key。憑啥隨機(jī)呢,至少也是把最近最少使用的key刪除。
當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在鍵空間中,移除最近最少使用的key,沒有設(shè)置過期時(shí)間的 key 也會(huì)被淘汰。
LRU的關(guān)鍵是看頁面最后一次被使用到發(fā)生調(diào)度的時(shí)間長短,而LFU關(guān)鍵是看一定時(shí)間段內(nèi)頁面被使用的頻率。
嘗試淘汰設(shè)置了過期時(shí)間的 key,最少使用的 key 優(yōu)先被淘汰。 沒有設(shè)置過期時(shí)間的 key 不會(huì)被淘汰,這樣可以保證需要持久化的數(shù)據(jù)不會(huì)突然丟失。 區(qū)別于 allkey-lru,這個(gè)策略要淘汰只是過期的 key 集合。
淘汰的 key 是過期 key 集合中隨機(jī)的 key。
淘汰的策略不是 LRU,而是 key 的剩余壽命 ttl 的值,ttl 越小越優(yōu)先被淘汰。
volatile-xxx 策略只會(huì)針對(duì)帶過期時(shí)間的 key 進(jìn)行淘汰,allkeys-xxx 策略會(huì)對(duì)所有的 key 進(jìn)行淘汰。
如果你只是拿 Redis 做緩存,那應(yīng)該使用 allkeys-xxx,客戶端寫緩存時(shí)不必?cái)y帶過期時(shí)間。
如果你還想同時(shí)使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,這樣可以保留沒有設(shè)置過期時(shí)間的 key,它們是永久的 key 不會(huì)被 LRU 算法淘汰。
確實(shí)有時(shí)會(huì)問這個(gè),因?yàn)橛行┖蜻x人如果確實(shí)過五關(guān)斬六將,前面的問題都答的很好,那么其實(shí)讓他寫一下LRU算法,可以考察一下編碼功底
你可以現(xiàn)場手寫最原始的LRU算法,那個(gè)代碼量太大了,不太現(xiàn)實(shí)
public class LRUCacheextends LinkedHashMap { private final int CACHE_SIZE; // 這里就是傳遞進(jìn)來最多能緩存多少數(shù)據(jù) public LRUCache(int cacheSize) { // true指linkedhashmap將元素按訪問順序排序 super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true); CACHE_SIZE = cacheSize; } @Override protected boolean removeEldestEntry(Map.Entry eldest) { // 當(dāng)KV數(shù)據(jù)量大于指定緩存?zhèn)€數(shù)時(shí),就自動(dòng)刪除最老數(shù)據(jù) return size() > CACHE_SIZE; } }
以上就是關(guān)于“Redis的過期策略和內(nèi)存淘汰策略怎么用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。