你應該知道的Redis過時鍵和過時策略

今天,我和你們分享一篇關於 Redis 有關過時鍵的內容,主要有四個內容:redis

  1. 如何設置過時鍵算法

  2. 如何取消設置的過時時間數據庫

  3. 過時鍵的過時策略是怎樣的編程

  4. RDB、AOF 和複製對過時鍵的處理又是怎樣的設計模式

設置鍵的生存時間或過時時間

redis 一共有 4 個命令來設置鍵的生存時間(能夠存活多久)或過時時間(何時被刪除)bash

  • expire :將 key 的生存時間設置爲 ttl 秒
  • pexpire :將 key 的生存時間設置爲 ttl 毫秒
  • expireat :將 key 的過時時間設置爲 timestamp 所指定的秒數時間戳
  • pexpireat :將 key 的過時時間設置爲 timestamp 所指定的毫秒數時間戳

上述四種命令本質上都是經過 pexpireat 命令來實現的。服務器

例子:
127.0.0.1:6379> set a test
OK
127.0.0.1:6379> EXPIRE a 5
(integer) 1
127.0.0.1:6379> get a // 距離設置生存時間命令的 5 秒內執行
"test"
127.0.0.1:6379> get a // 距離設置生存時間命令的 5 秒後執行
(nil)

127.0.0.1:6379> set b 12
OK
127.0.0.1:6379> EXPIREAT b 1545569500
(integer) 1
127.0.0.1:6379> time
1) "1545569486"
2) "108616"
127.0.0.1:6379> get b // 距離設置 1545569500 所指定的秒數時間戳內執行
"12"
127.0.0.1:6379> time
1) "1545569506"
2) "208567"
127.0.0.1:6379> get b // 距離設置 1545569500 所指定的秒數時間戳後執行
(nil)
複製代碼

若是本身不當心設置錯了過時時間,那麼咱們能夠刪除先前的過時時間微信

移除過時時間

persist 命令能夠移除一個鍵的過時時間,舉個栗子:數據結構

127.0.0.1:6379> EXPIRE c 1000
(integer) 1
127.0.0.1:6379> ttl c   // 有過時時間
(integer) 9996
127.0.0.1:6379> PERSIST c
(integer) 1
127.0.0.1:6379> ttl c  // 無過時時間
(integer) -1

PS:ttl 是以秒爲單位,返回鍵的剩餘生存時間;同理還有 pttl 命令是以毫秒爲單位,返回鍵的剩餘生存時間
複製代碼

此時,若是咱們沒有移除過時時間,那麼若是一個鍵過時了,那它何時會被刪除呢?架構

這個問題就會有如下三種答案了,它們分別表明三種不一樣的刪除策略

過時鍵的刪除策略

定時刪除

在設置鍵的過時時間的同時,建立一個定時器,讓定時器在鍵的過時時間來臨時,當即執行對鍵的刪除操做。

優勢:對內存最友好的。能夠及時釋放鍵所佔用的內存。

缺點:對 CPU 不友好。特別在過時鍵比較多的狀況下,刪除過時鍵會佔用至關一部分 CPU 時間。同時在內存不緊張,CPU 緊張的狀況下,將 CPU 用在刪除和當前任務不想關的過時鍵上,無疑會對服務器響應時間和吞吐量形成影響。

惰性刪除

聽任鍵過時無論,可是每次從鍵空間中讀寫鍵時,都會檢查取得的鍵是否過時。若是過時就刪除該刪,不然就返回該鍵。(PS:鍵空間是一個保存了數據庫全部鍵值對的數據結構)

優勢:對 CPU 最友好。只有在操做的時候進行過時檢查,刪除的目標僅限於當前須要處理的鍵,不會在刪除其餘無關本次操做的過時鍵上花費任何 CPU 時間。

缺點:對內存不友好。這個十分容易理解了,鍵過時了,但由於一直沒有被訪問到,因此一直保留着(除非手動執行 flushdb 操來於清空當前數據庫中的全部 key。),至關於內存泄漏。

按期刪除

每隔一段時間,程序就對數據庫進行檢查,刪除裏面的過時鍵。至於要刪除多少過時鍵,以及檢查多少數據庫,則有算法決定。

該策略是上述兩種策略的折中方案,須要經過實際狀況,來設置刪除操做的執行時長和頻率。

明白了過時鍵的刪除策略後,那 redis 服務器又是採用什麼策略來刪除過時鍵的呢?

實際上,Redis 服務器使用的是惰性刪除和按期刪除兩種策略,經過配合使用,服務器能夠很好的平衡 CPU 和內存。

其中惰性刪除爲 redis 服務器內置策略。而按期刪除能夠經過如下兩種方式設置:

  1. 配置 redis.conf 的 hz 選項,默認爲10 (即 1 秒執行 10 次,值越大說明刷新頻率越快,對 Redis 性能損耗也越大)
  2. 配置 redis.conf 的 maxmemory 最大值,當已用內存超過 maxmemory 限定時,就會觸發主動清理策略

RDB 對過時鍵的處理

生成 RDB 文件

程序會被數據庫中的鍵進行檢查,過時的鍵不會被保存到新建立的 RDB 文件中。所以數據庫中的過時鍵不會對生成新的 RDB 文件形成影響

載入 RDB 文件

這裏須要分狀況說明:

  1. 若是服務器以主服務器模式運行,則在載入 RDB 文件時,程序會對文件中保存的鍵進行檢查,過時鍵不會被載入到數據庫中。因此過時鍵不會對載入 RDB 文件的主服務器形成影響
  2. 若是服務器以從服務器模式運行,則在載入 RDB 文件時,不論鍵是否過時都會被載入到數據庫中。但因爲主從服務器在進行數據同步時,從服務器的數據會被清空。因此通常來講,過時鍵對載入 RDB 文件的從服務器也不會形成影響

AOF 對過時鍵的處理

AOF 文件寫入

當服務器以 AOF 持久化模式運行時,若是數據庫某個過時鍵還沒被刪除,那麼 AOF 文件不會由於這個過時鍵而產生任何影響,依舊保留。

而當過時鍵被刪除後,那麼程序會向 AOF 文件追加一條 DEL 命令來顯式地記錄該鍵被刪除。

AOF 重寫

執行 AOF 重寫過程當中,也會被數據庫的鍵進行檢查,已過時的鍵不會被保存到重寫後的 AOF 文件中。所以不會對 AOF 重寫形成影響

複製對過時鍵的處理

當服務器運行在複製模式下,由主服務器來控制從服務器的刪除過時鍵動做,目的是保證主從服務器數據的一致性。

那究竟是怎麼控制的呢?

  1. 主服務器刪除一個過時鍵後,會向全部從服務器發送一個 DEL 命令,告訴從服務器刪除這個過時鍵
  2. 從服務器接受到命令後,刪除過時鍵

PS:從服務器在接收到客戶端對過時鍵的讀命令時,依舊會返回該鍵對應的值給客戶端,而不會將其刪除。

參考《Redis設計與實現》,公衆號後臺回覆「redis」可自取該書電子版

PS:本文原創發佈於微信公衆號「不僅Java」,後臺回覆如下關鍵字獲取經典必讀書籍: Java、MySQL、Redis、Linux、mq、數據結構、設計模式、編程思想、架構

公衆號專一分享 Java 乾貨、讀書筆記、成長思考

相關文章
相關標籤/搜索