Redis Key Expiration Reclaim

Redis 如何處理過期鍵值? 是否可以主動降低過期鍵值的數量?

Jerry’s Notes
What’s next?
4 min readMar 20, 2022

--

Redis 刪除過期的鍵值,有兩種方式:

1. Passive(被動被動刪除) : 當該鍵值被存取到時,若該鍵值已過期,則會先刪除該鍵值,而後回覆空值給前端應用。

2. Active(主動刪除) : 每隔 100 milliseconds 隨機挑選 20 個鍵值,然後刪除過期鍵值,若這20個鍵值中,有超過25%是過期的鍵值,則會重複這個動作,直到過期比率低於25%。 (每秒做10次,每次挑20個鍵值)

Redis Keys Expiration (Reclaim) — Redis delete expired keys in two ways:

One lazy way deletes a key when it is requested by a command, but it is found to be already expired.

One active way expires a few keys every 100 milliseconds.

Starting from Redis 6, there is a new parameter: active-expire-effort.

Redis 6 之後的版本,可以透過調整參數值 active-expire-effort,來降低過期鍵值的比例,但缺點是當過於主動去刪除過期鍵值時,反而會造成 cpu 負載的增加,進而增加命令產生延遲的機率。

This parameter defines the amount of effort that Redis uses to expire items in the periodic job. The default value of 1 tries to avoid having more than 10 percent of expired keys still in memory. It also tries to avoid consuming more than 25 percent of total memory and to add latency to the system. You can increase this value up to 10 to increase the amount of effort spent on expiring keys. The tradeoff is higher CPU and potentially higher latency. We recommend a value of 1 unless you are seeing high memory usage and can tolerate an increase in CPU utilization.

Parameter: active-expire-effort.

Default: 1 up to 10

Q. How to remove all expired key on Redis cluster?

1. Customer can use SCAN command to scan all keys on Redis to expire which key TTL have expired.

2. Backup and recreate new Redis cluster with backup RDB file. Due to snapshot backup will NOT backup expire key.

若客戶想清掉所有過期的key.. 除了,用 SCAN 的方式掃所有的鍵值外,可以用備份重建的方式來做,因為 rdb file 沒有記錄過期的key,這個方式只會存在過期時間在“備份時間點“之後過程的key,跟正常的key。

Q: Reclaim and Eviction 是否會在 Replica node 執行?

■ Reclaim and Eviction 只會發生在 Primary Node 上,Replica Node 不會有這樣的行為。

■ 為了保證一致性,從節點不會主動的刪除過期key,除非它升級為主節點或收到主節點發來的DEL命令。

Replicas don’t expire keys directly, instead they wait for primary to expire the keys. When the primary expires a key (or evict), it synthesizes a DEL command which is transmitted to all the replicas.

Please note: in theory, if all the keys are set up reasonable TTL, then there would be ~25% keys expired but not reclaimed. Basically, this means that if the database has many keys expiring in the same second, and these make up at least 25% of the current population of keys with an expire set, Redis can block in order to get the percentage of keys already expired below 25%. To remove the expired keys from the data set you can run a SCAN command to the keys. Also, scan command requires much less CPU resources than the KEYS command:

!!! 這個方式,可以手動去刪除特定鍵值。

!!! 請注意 COUNT 筆數過大的結果=使用KEYS命令,容易造成阻塞,請小心使用。

Q: 如何查詢已經到期的 key ,留存在內存中數量及比例?

在 redis 4.0 以上版本,redis info 命令的輸出中有一個指標 “expired_stale_perc”,這可以協助您判斷有多少的已經到期的 key 仍留存在內存中。

[+] Track number of logically expired keys still in memory :
https://github.com/redis/redis/commit/ffde73c57d0aa5cd58869c13cb1b76d6c27ef5b7

Q: 如何優化過期key的處理?

a. 您可以透過定期的執行 redis scan 命令,來加速過期key的回收(如 cron job)。 您可以使用scan來掃描整做個redis上的key,讓過期的 key 被刪除,在執行 scan 命令時會造成系統負載的上升,因此建議您在負戴較低的時段進行,或是減小scan每次執行的週期。

python 的範例

b. 使用集群模式來將 key 分散至不同的分片(shard)上,不同的 shard 可以同時處理過期 key 的回收,會比單一個 shard 來得更有效率。
c. 延長 key 的過期時間,這可以增加一定時間內 key 的回收數量。
d. 升級您的 redis 至 6.0 版本,6.0 版本針對 key 的過期回收機制進行了改良,可以讓過期的 key 回收更有效率。在 Elasticache 上您可以使用參數”active-expire-effort”增進回收的積極度。

Q: Expiration during Lua scripts?

During Lua scripts executions, no keys expiration is performed. !!!在LUA 執行期間,是不會執行Reclaim的。

As a Lua script runs, conceptually the time in the primary is frozen, so that a given key will either exist or not for all the time the script runs.

This prevents keys to expire in the middle of a script, and is needed in order to send the same script to the primary in a way that is guaranteed to have the same effects in the data set.

Q: What’s different between TTL AND PTTL?

■ TTL 命令以秒為單位返回 key 的剩餘過期時間。

> TTL

■ PTTL 命令以毫秒為單位返回 key 的剩餘過期時間。

> PTTL

Q: What’s different between Expire AND PExpire?

> Expire

Redis Expire 命令用於設置 key 的過期時間,key 過期後將不再可用。單位以秒計。

Redis Expireat 命令用於以 UNIX 時間戳(unix timestamp)格式設置 key 的過期時間。key 過期後將不再可用。

Redis PEXPIRE 命令和 EXPIRE 命令的作用類似,但是它以毫秒為單位設置 key 的生存時間,而不像 EXPIRE 命令那樣,以秒為單位。

Redis PEXPIREAT 命令用於設置 key 的過期時間,以毫秒計。key 過期後將不再可用。

hz settting in redis.conf

!!! 將redis.conf 配置檔案中的hz調大,將會提高Redis主動淘汰的頻率,但不建議調整,會建議升級到 Redis 6 之後的版本,可以透過調整參數值 active-expire-effort,來降低過期鍵值的比例。

將redis.conf 配置檔案中的hz調大將會提高Redis主動淘汰的頻率,如果你的Redis儲存中包含很多冷資料佔用記憶體過大的話,可以考慮將這個值調大,但Redis作者建議這個值不要超過100。我們實際線上將這個值調大到100,觀察到CPU會增加2%左右,但對冷資料的記憶體釋放速度確實有明顯的提高(通過觀察keyspace個數和used_memory大小)。

可以看出timelimit和server.hz是一個倒數的關係,也就是說hz配置越大,timelimit就越小。換句話說是每秒鐘期望的主動淘汰頻率越高,則每次淘汰最長佔用時間就越短。這裡每秒鐘的最長淘汰佔用時間是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰頻率和每次淘汰的最長時間是通過hz引數控制的。

ServerCron (redis.c/serverCron):

Redis 將 serverCron 作為時間事件來運行, 從而確保它每隔一段時間就會自動運行一次, 又因為 serverCron 需要在 Redis 服務器運行期間一直定期運行, 所以它是一個循環時間事件: serverCron 會一直定期執行,直到服務器關閉為止。

• every 100 milliseconds (10 times per second)

•更新服務器的各類統計信息,比如時間、內存佔用、數據庫佔用情況等

• 清理數據庫中的過期鍵值對

• 對不合理的數據庫進行大小調整

• 關閉和清理連接失效的客戶端

• 嘗試進行 AOF 或 RDB 持久化操作

• 如果服務器是主節點的話,對附屬節點進行定期同步

• 如果處於集群模式的話,對集群進行定期同步和連接測試

--

--

Jerry’s Notes
What’s next?

An cloud support engineer focus on troubleshooting with customer reported issue ,and cloud solution architecture.