Redis是如何淘汰key的?

2021-10-25 17:21:19 字數 4086 閱讀 3859

淘汰原理

系統線上執行中,記憶體總是昂貴且有限的,在資料總量遠大於 redis 可用的記憶體總量時,為了最大限度的提公升訪問效能,redis 中只能存放最新最熱的有效資料。

當 key 過期後,或者 redis 實際占用的記憶體超過閥值後,redis 就會對 key 進行淘汰,刪除過期的或者不活躍的 key,**其記憶體,供新的 key 使用。redis 的記憶體閥值是通過 maxmemory 設定的,而超過記憶體閥值後的淘汰策略,是通過 maxmemory-policy 設定的,具體的淘汰策略後面會進行詳細介紹。redis 會在 2 種場景下對 key 進行淘汰,第一種是在定期執行 servercron 時,檢查淘汰 key;第二種是在執行命令時,檢查淘汰 key。

第一種場景,redis 定期執行 servercron 時,會對 db 進行檢測,清理過期 key。清理流程如下。首先輪詢每個 db,檢查其 expire dict,即帶過期時間的過期 key 字典,從所有帶過期時間的 key 中,隨機選取 20 個樣本 key,檢查這些 key 是否過期,如果過期則清理刪除。如果 20 個樣本中,超過 5 個 key 都過期,即過期比例大於 25%,就繼續從該 db 的 expire dict 過期字典中,再隨機取樣 20 個 key 進行過期清理,持續迴圈,直到選擇的 20 個樣本 key 中,過期的 key 數小於等於 5,當前這個 db 則清理完畢,然後繼續輪詢下乙個 db。

在執行 servercron 時,如果在某個 db 中,過期 dict 的填充率低於 1%,則放棄對該 db 的取樣檢查,因為效率太低。如果 db 的過期 dict 中,過期 key 太多,一直持續迴圈**,會占用大量主線程時間,所以 redis 還設定了乙個過期時間。這個過期時間根據 servercron 的執行頻率來計算,5.0 版本及之前採用慢迴圈過期策略,預設是 25ms,如果**超過 25ms 則停止,6.0 非穩定版本採用快迴圈策略,過期時間為 1ms。

第二種場景,redis 在執行命令請求時。會檢查當前記憶體占用是否超過 maxmemory 的數值,如果超過,則按照設定的淘汰策略,進行刪除淘汰 key 操作。

淘汰方式

redis 中 key 的淘汰方式有兩種,分別是同步刪除淘汰和非同步刪除淘汰。在 servercron 定期清理過期 key 時,如果設定了延遲過期配置 lazyfree-lazy-expire,會檢查 key 對應的 value 是否為多元素的復合型別,即是否是 list 列表、set 集合、zset 有序集合和 hash 中的一種,並且 value 的元素數大於 64,則在將 key 從 db 中 expire dict 過期字典和主 dict 中刪除後,value 存放到 bio 任務佇列,由 bio 延遲刪除執行緒非同步**;否則,直接從 db 的 expire dict 和主 dict 中刪除,並** key、value 所占用的空間。在執行命令時,如果設定了 lazyfree-lazy-eviction,在淘汰 key 時,也採用前面類似的檢測方法,對於元素數大於 64 的 4 種復合型別,使用 bio 執行緒非同步刪除,否則採用同步直接刪除。

淘汰策略

redis 提供了 8 種淘汰策略對 key 進行管理,而且還引入基於樣本的 eviction pool,來提公升剔除的準確性,確保 在保持最大效能 的前提下,剔除最不活躍的 key。eviction pool 主要對 lru、lfu,以及過期 dict ttl  記憶體管理策略 生效。處理流程為,當 redis 記憶體占用超過閥值後,按策略從主 dict 或者帶過期時間的 expire dict 中隨機選擇 n 個 key,n 預設是 5,計算每個 key 的 idle 值,按 idle 值從小到大的順序插入 evictionpool 中,然後選擇 idle 最大的那個 key,進行淘汰。

選擇淘汰策略時,可以通過配置 redis 的 maxmemory 設定最大記憶體,並通 maxmemory_policy 設定超過最大記憶體後的處理策略。如果 maxmemory 設為 0,則表明對記憶體使用沒有任何限制,可以持續存放資料,適合作為儲存,來存放資料量較小的業務。如果資料量較大,就需要估算熱資料容量,設定乙個適當的值,將 redis 作為乙個快取而非儲存來使用。

redis 提供了 8 種 maxmemory_policy 淘汰策略來應對記憶體超過閥值的情況。

第一種淘汰策略是 noeviction,它是 redis 的預設策略。在記憶體超過閥值後,redis 不做任何清理工作,然後對所有寫操作返回錯誤,但對讀請求正常處理。noeviction 適合資料量不大的業務場景,將關鍵資料存入 redis 中,將 redis 當作 db 來使用。

第二種淘汰策略是 volatile-lru,它對帶過期時間的 key 採用最近最少訪問演算法來淘汰。使用這種策略,redis 會從 redisdb 的 expire dict 過期字典中,首先隨機選擇 n 個 key,計算 key 的空閒時間,然後插入 evictionpool 中,最後選擇空閒時間最久的 key 進行淘汰。這種策略適合的業務場景是,需要淘汰的key帶有過期時間,且有冷熱區分,從而可以淘汰最久沒有訪問的key。

第三種策略是 volatile-lfu,它對帶過期時間的 key 採用最近最不經常使用的演算法來淘汰。使用這種策略時,redis 會從 redisdb 中的 expire dict 過期字典中,首先隨機選擇 n 個 key,然後根據其 value 的 lru 值,計算 key 在一段時間內的使用頻率相對值。對於 lfu,要選擇使用頻率最小的 key,為了沿用 evictionpool 的 idle 概念,redis 在計算 lfu 的 idle 時,採用 255 減去使用頻率相對值,從而確保 idle 最大的 key 是使用次數最小的 key,計算 n 個 key 的 idle 值後,插入 evictionpool,最後選擇 idle 最大,即使用頻率最小的 key,進行淘汰。這種策略也適合大多數 key 帶過期時間且有冷熱區分的業務場景。

第四種策略是 volatile-ttl,它是對帶過期時間的 key 中選擇最早要過期的 key 進行淘汰。使用這種策略時,redis 也會從 redisdb 的 expire dict 過期字典中,首先隨機選擇 n 個 key,然後用最大無符號 long 值減去 key 的過期時間來作為 idle 值,計算 n 個 key 的 idle 值後,插入evictionpool,最後選擇 idle 最大,即最快就要過期的 key,進行淘汰。這種策略適合,需要淘汰的key帶過期時間,且有按時間冷熱區分的業務場景。

第五種策略是 volatile-random,它是對帶過期時間的 key 中隨機選擇 key 進行淘汰。使用這種策略時,redis 從 redisdb 的 expire dict 過期字典中,隨機選擇乙個 key,然後進行淘汰。如果需要淘汰的key有過期時間,沒有明顯熱點,主要被隨機訪問,那就適合選擇這種淘汰策略。

第六種策略是 allkey-lru,它是對所有 key,而非僅僅帶過期時間的 key,採用最近最久沒有使用的演算法來淘汰。這種策略與 volatile-lru 類似,都是從隨機選擇的 key 中,選擇最長時間沒有被訪問的 key 進行淘汰。區別在於,volatile-lru 是從 redisdb 中的 expire dict 過期字典中選擇 key,而 allkey-lru 是從所有的 key 中選擇 key。這種策略適合,需要對所有 key 進行淘汰,且資料有冷熱讀寫區分的業務場景。

第七種策略是 allkeys-lfu,它也是針對所有 key 採用最近最不經常使用的演算法來淘汰。這種策略與 volatile-lfu 類似,都是在隨機選擇的 key 中,選擇訪問頻率最小的 key 進行淘汰。區別在於,volatile-flu從expire dict 過期字典中選擇 key,而 allkeys-lfu 是從主 dict 中選擇 key。這種策略適合的場景是,需要從所有的 key 中進行淘汰,但資料有冷熱區分,且越熱的資料訪問頻率越高。

最後一種策略是 allkeys-random,它是針對所有 key 進行隨機演算法進行淘汰。它也是從主 dict 中隨機選擇 key,然後進行刪除**。如果需要從所有的 key 中進行淘汰,並且 key 的訪問沒有明顯熱點,被隨機訪問,即可採用這種策略。

Redis是如何淘汰資料?

摘要 大家在用redis做快取資料的時候有沒有估算過整個快取使用了多少空間呢?如果快取資料的大小超過了整個redis的記憶體大小,又會有什麼情況發生呢?在redis中,我們是可以去設定最大使用記憶體大小server.maxmemory的,當redis記憶體資料集大小上公升到一定程度的時候,就會施行資...

Redis 的記憶體KEY淘汰策略

策略說明優缺點 立即過期 set test testexpire 建立test expire test 3 設定3秒過期 優點 過期立馬釋放記憶體 缺點 每隔key都會設定定時器,消耗cpu的資源。不建議使用。惰性過期 當訪問的時候,才會判斷是否過期 當寫的時候,如果發現記憶體用完了,才會釋放空間 ...

Redis記憶體淘汰策略及Key的過期策略

volatile lru 淘汰最近最少使用的 volatile random 隨機淘汰 volatile ttl 淘汰將要到期的 allkeys random 所有key中隨機淘汰 allkeys lru 所有key中淘汰最近最少使用的 預設的淘汰策略 no enviction enviction譯...