Redis的過期鍵刪除策略和數據逐出策略

2021-01-15 全菜工程師小輝

Redis作為一個高性能的內存NoSQL資料庫,其容量受到最大內存限制的限制。

在實際生產環境中使用Redis時,偶然會覺得Redis的內存佔用要比自己預想的大。事實上,Redis佔用的內存除了保存鍵值對所需的開銷外,還有一些運行時產生的額外內存,包括:

過期Key所佔空間漸進式Rehash導致未及時刪除的空間Redis管理數據,包括底層數據結構開銷,客戶端信息,讀寫緩衝區等主從複製,bgsave時的額外開銷Redis的漸進式Rehash,在筆者介紹Concurrenthashmap擴容的時候,做了簡單的介紹,點擊查看詳解ConcurrentHashMap及JDK8的優化

Redis的主從複製,則在筆者的另一篇博客裡做了詳細的介紹,點擊查看Redis主從複製的原理

所以本文將主要圍繞過期Key的回收問題進行講解。

過期鍵的刪除策略

如果Redis的一個鍵是過期的,那它到了過期時間之後並不是馬上就從內存中被刪除,而是採用了三種不同的刪除策略:

立即刪除惰性刪除定時刪除其中第二種為被動刪除,第一種和第三種為主動刪除,而且第一種實時性更高。

1.立即刪除

立即刪除是指,在設置鍵的過期時間時,創建一個回調事件,當過期時間達到時,由時間處理器自動執行鍵的刪除操作。

立即刪除能保證內存中數據的最大新鮮度,因為它保證過期鍵值會在過期後馬上被刪除,其所佔用的內存也會隨之釋放。但是立即刪除對cpu是最不友好的。因為刪除操作會佔用cpu的時間,如果剛好碰上了cpu正在做排序等計算的時候,就會給cpu造成額外的壓力。

而且目前redis事件處理器對時間事件的處理方式--無序鍊表,查找一個key的時間複雜度為O(n),所以並不適合用來處理大量的時間事件。

2.惰性刪除

惰性刪除是指,某個鍵值過期後,此鍵值不會馬上被刪除,而是等到下次被使用的時候,才會被檢查到過期,此時才能得到刪除。所以惰性刪除的缺點很明顯:浪費內存。

舉個例子,對於一些按時間點來更新的數據,比如log日誌,過期後在很長的一段時間內可能都得不到訪問,這樣在這段時間內就要浪費這麼多內存來存log。

3.定時刪除

從上面分析來看,立即刪除會短時間內佔用大量cpu,惰性刪除會在一段時間內浪費內存,所以定時刪除是一個折中的辦法。

定時刪除是指:每隔一段時間執行一次刪除操作,並通過限制刪除操作執行的時長和頻率,來減少刪除操作對cpu的影響。另一方面定時刪除也有效的減少了因惰性刪除帶來的內存浪費。

過期Key清理算法

Redis過期Key清理的機制對清理的頻率和最大時間都有限制,在儘量不影響正常服務的情況下,進行過期Key的清理,以達到長時間服務的性能最優。

Redis會周期性的隨機測試一批設置了過期時間的key並進行處理。測試到的已過期的key將被刪除。具體的算法如下:

Redis配置項hz定義了serverCron任務的執行周期,默認為10,即CPU空閒時每秒執行10次;每次過期key清理的時間不超過CPU時間的25%,即若hz=1,則一次清理時間最大為250ms,若hz=10,則一次清理時間最大為25ms;清理時依次遍歷所有的db;從db中隨機取20個key,判斷是否過期,若過期,則逐出;若有5個以上key過期,則重複步驟4,否則遍歷下一個db;在清理過程中,若達到了25%CPU時間,退出清理過程;這是一個基於概率的簡單算法,基本的假設是抽出的樣本能夠代表整個key空間,redis持續清理過期的數據直至將要過期的key的百分比降到了25%以下。

由於算法採用的隨機取key判斷是否過期的方式,故幾乎不可能清理完所有的過期Key。

調高hz參數可以提升清理的頻率,過期key可以更及時的被刪除,但hz太高會增加CPU時間的消耗。

數據逐出策略

在redis中,允許用戶設置最大使用內存大小maxmemory(需要配合maxmemory-policy使用),設置為0表示不限制(默認配置)。

生產環境中需要設置此值,最好不超過內存60%-70%。

當redis內存數據集快到達maxmemory時,redis會實行數據淘汰策略。

Redis提供6種數據淘汰策略。在逐出算法中,根據用戶設置的逐出策略,選出待逐出的key,直到當前內存小於最大內存值為止。

可選逐出策略如下:

volatile-lru:從已設置過期時間的數據集中挑選最近最少使用的數據淘汰volatile-ttl:從已設置過期時間的數據集中挑選將要過期的數據淘汰volatile-random:從已設置過期時間的數據集中任意選擇數據 淘汰allkeys-lru:從數據集中挑選最近最少使用的數據淘汰allkeys-random:從數據集中任意選擇數據淘汰no-enviction(驅逐):禁止驅逐數據在redis2.8中默認策略是volatile-lru在redis3.2和redis4.0中默認策略是no-eviction如果使用no-eviction時,當內存不足,Redis會返回OOM的錯誤信息(error) OOM command not allowed when used memory > 'maxmemory'.

當cache中沒有符合清除條件的key時,回收策略 volatile-lru, volatile-random 和volatile-ttl 將會和策略 noeviction 一樣直接返回錯誤。

選擇正確的回收策略是很重要的,取決於你的應用程式的訪問模式。使用INFO命令輸出來監控緩存命中和錯過的次數,以調優Redis的配置。

通用規則如下:

如果期望用戶請求呈現冪律分布(power-law distribution),也就是,期望一部分子集元素被訪問得遠比其他元素多時,可以使用allkeys-lru策略。如果期望是循環周期的訪問,所有的鍵被連續掃描,或者期望請求符合平均分布(每個元素以相同的概率被訪問),可以使用allkeys-random策略。如果期望是讓redis使用緩存對象設置的TTL值,確定哪些對象應該是較好的清除候選項,可以使用volatile-ttl策略。

相關焦點

  • Redis過期鍵刪除策略
    在這三種策略中,第一種和第三種為主動刪除策略,而第二種則為被動刪除策略。定時刪除定時刪除策略對內存是最友好的:通過使用定時器,定時刪除策略可以保證過期鍵會儘可能快地被刪除,並釋放過期鍵所佔用的內存。另一方面,定時刪除策略的缺點是,它對CPU時間是最不友好的:在過期鍵比較多的情況看下,刪除過期鍵這一行為可能會佔用相當一部分CPU時間,在內存不緊張但是CPU時間非常緊張的情況下,將CPU時間用在刪除和當前無關的過期鍵上,無疑會對伺服器的響應時間和吞吐量造成影響。
  • redis的過期策略和內存淘汰策略
    最近有用到redis的zset結合定時器做延遲數據的狀態變更,同事說你怎麼不用key過期監聽呢,想想也是,自己隨後實驗了下這個key過期,其實確實能跑通。但是內心有點堪憂,會不會吃內存嚴重和耗CPU。苦於任務沒有過多的時間來做這塊內存和cpu損耗的驗證,遂放棄了這個搞法,留待以後實驗。
  • 談談 Redis 的過期策略
    要搞清楚這些,就要了解 Redis 的過期策略和內存淘汰機制。Redis採用的是定期刪除 + 懶惰刪除策略。因為指令同步是異步進行的,所以主庫過期的 key 的 del 指令沒有及時同步到從庫的話,會出現主從數據的不一致,主庫沒有的數據在從庫裡還存在。
  • Redis單機資料庫持久化與過期建刪除
    是以鍵值對的方式來進行數據存儲,首先redis會維持一個鍵表,在這個表上存儲著redis所有的 「key」 (也就是direct表)再來就是以指針的方式指向對於的&34;,而它的value就數據結構比較豐富,有動態字符串,鍊表,跳躍表等等、redis採用對象式存儲,每一個鍵都是一個String對象,而value則是一個對應數據結構的對象。
  • Redis5.0數據淘汰策略詳解(最新版本,面試常問)
    作為一個內存資料庫,redis在內存空間不足的時候,為了保證命中率,就會選擇一定的數據淘汰策略,這篇文章主要講解常見的幾種內存淘汰策略。和我們作業系統中的頁面置換算法類似。一、參數設置我們的redis資料庫的最大緩存、主鍵失效、淘汰機制等參數都是通過配置文件來配置的。
  • 「系統架構」如何保證Redis中的數據都是熱數據?
    ,而redis中只有50w數據,如何保證redis中10w數據都是熱點數據?其實,這道題考察的是Redis的數據逐出原理。當 Redis 使用的內存超過設置的最大內存時,會觸發 Redis 的 key 淘汰機制,以保留最活躍的數據。
  • 每日一題之 Redis
    Redis 的數據過期策略Redis 中數據過期策略採用定期刪除+惰性刪除策略定期刪除策略:Redis 啟用一個定時器定時監視所有的 key,判斷key是否過期,過期的話就刪除。這種策略可以保證過期的 key 最終都會被刪除,但是也存在嚴重的缺點:每次都遍歷內存中所有的數據,非常消耗 CPU 資源,並且當 key 已過期,但是定時器還處於未喚起狀態,這段時間內 key 仍然可以用。惰性刪除策略:在獲取 key 時,先判斷 key 是否過期,如果過期則刪除。
  • 初識Redis
    中的值不僅可以是字符串,而且還可以是具體的數據結構:字符串、哈希、列表、集合、有序集合 3.豐富的功能 提供了鍵過期功能,可以用來實現緩存。 6種內存淘汰策略,當內存滿的時候才會選取策略刪除keyvolatile-lru:從已設置過期時間的數據集中挑選最近最少使用的數據淘汰volatile-ttl:從已設置過期時間的數據集中挑選
  • 從零手寫緩存框架(12)redis過期隨機特性詳解及實現
    java從零手寫實現redis(二)redis expire 過期原理java從零手寫實現redis(三)內存數據如何重啟不丟失?java從零手寫實現redis(四)添加監聽器java從零手寫實現redis(五)過期策略的另一種實現思路java從零手寫實現redis(六)AOF 持久化原理詳解及實現java從零開始手寫redis(七)LRU 緩存淘汰策略詳解java從零開始手寫redis(八)樸素 LRU 淘汰算法性能優化第二節中我們已經初步實現了類似
  • Redis持久化策略
    如果僅將數據存在內存,一旦宕機重啟,數據全部丟失。1 持久化概論1.1 什麼是持久化redis所有數據保持在內存中,對數據的更新將異步地保存到磁碟上。在Redis重啟時,通過回放日誌中的寫入指令來重構整個數據。如果希望Redis僅作為純內存的緩存來用,亦可禁用RDB和AOF。 可以在同一實例中同時使用AOF和RDB。這種情況下,當Redis重新啟動時,AOF文件將用於重建原始數據集,因為它可以保證是最完整的。
  • Redis的超時命令和垃圾回收策略
    當程序編寫不當或考慮欠缺的時候(比如讀入大文件),內存就可能存儲不下運行所需要的數據,那麼 Java 虛擬機就會拋出內存溢出的異常而導致服務失敗。同樣,Redis 也是基於內存而運行的數據集合,也存在著對內存垃圾的回收和管理的問題。
  • Redis緩存失效策略思考
    Redis採用了兩種策略:定期刪除和惰性刪除。(1) 定期刪除Redis每隔一段時間就檢查哪些KEY已經過期,如果過期就刪除。但是我們來設想一個問題:如果Redis存儲KEY非常多,僅僅超時檢查這項工作就會非常耗費資源並嚴重影響服務能力。
  • 從零開始手寫 redis(五)過期策略的另一種實現思路
    java從零手寫實現redis(三)redis expire 過期原理java從零手寫實現redis(三)內存數據如何重啟不丟失?java從零手寫實現redis(四)添加監聽器前面實現了 redis 的幾個基本特性,其中在 expire 過期原理時,提到了另外一種實現方式。這裡將其記錄下來,可以拓展一下自己的思路。
  • 從一次線上故障來看redis刪除機制
    通過日誌分析和數據核對發現某個key過期了,但在slave上還可以讀取的到。二、故障分析 為什麼會出現這種情況呢,我們來分析下redis中key過期刪除策略,redis中key過期刪除策略有二種:主動刪除、惰性刪除。
  • Redis面試題
    本文圍繞以下幾點進行闡述1、為什麼使用redis2、使用redis有什麼缺點3、單線程的redis為什麼這麼快4、redis的數據類型,以及每種數據類型的使用場景5、redis的過期策略以及內存淘汰機制6、redis和資料庫雙寫一致性問題7、如何應對緩存穿透和緩存雪崩問題8、如何解決redis的並發競爭問題
  • Redis原理和機制詳解
    4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。這種情況一般是把redis既當緩存,又做持久化存儲的時候才用。不推薦5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。
  • 過期處理:Redis內部的清潔工,有效的管理和清理內存
    三種過期策略:定時刪除:在設置key過期時間的同時,為該key創建一個定時器,key過期時進行刪除。優點:內存釋放及時。缺點:若key很多,定時器創建耗時;維護大量定時器;刪除開銷很大;嚴重影響cpu性能。定期刪除:每隔一段時間執行一次過期key的刪除。優點:限制了刪除時長和頻率,減少刪除操作對cpu的佔用。
  • 從零開始手寫 redis(十)緩存淘汰LFU算法詳解
    java從零手寫實現redis(三)redis expire 過期原理java從零手寫實現redis(三)內存數據如何重啟不丟失?java從零手寫實現redis(四)添加監聽器java從零手寫實現redis(五)過期策略的另一種實現思路java從零手寫實現redis(六)AOF 持久化原理詳解及實現java從零手寫實現redis(七)LRU 緩存淘汰策略詳解java從零開始手寫 redis(八)樸素 LRU 淘汰算法性能優化本節一起來學習下另一個常用的緩存淘汰算法
  • Redis內存淘汰機制
    設置過期時間我們可以在設置鍵時設置expire time,也可以在運行時給存在的鍵設置剩餘的生存時間,不設置則默認為-1,設置為-1時表示永久存儲。隨機抽取設置了過期時間的key,並對其進行檢查,如果已經過期則刪除。
  • 阿里雲Redis開發規範 – 附架構師的解析
    阿里雲的redis開發規範同樣如此。建議根據公司實際情況進行參考。本文」解析「部分額外附上基礎架構部門數據架構師的解析,歡迎批評和討論。【推薦】:控制key的生命周期,redis不是垃圾桶。建議使用expire設置過期時間(條件允許可以打散過期時間,防止集中過期),不過期的數據重點關注idletime。