今天,我和你們分享一篇關於 Redis 有關過時鍵的內容,主要有四個內容:redis
如何設置過時鍵算法
如何取消設置的過時時間數據庫
過時鍵的過時策略是怎樣的編程
RDB、AOF 和複製對過時鍵的處理又是怎樣的設計模式
redis 一共有 4 個命令來設置鍵的生存時間(能夠存活多久)或過時時間(何時被刪除)bash
上述四種命令本質上都是經過 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 服務器內置策略。而按期刪除能夠經過如下兩種方式設置:
程序會被數據庫中的鍵進行檢查,過時的鍵不會被保存到新建立的 RDB 文件中。所以數據庫中的過時鍵不會對生成新的 RDB 文件形成影響
這裏須要分狀況說明:
當服務器以 AOF 持久化模式運行時,若是數據庫某個過時鍵還沒被刪除,那麼 AOF 文件不會由於這個過時鍵而產生任何影響,依舊保留。
而當過時鍵被刪除後,那麼程序會向 AOF 文件追加一條 DEL 命令來顯式地記錄該鍵被刪除。
執行 AOF 重寫過程當中,也會被數據庫的鍵進行檢查,已過時的鍵不會被保存到重寫後的 AOF 文件中。所以不會對 AOF 重寫形成影響
當服務器運行在複製模式下,由主服務器來控制從服務器的刪除過時鍵動做,目的是保證主從服務器數據的一致性。
那究竟是怎麼控制的呢?
PS:從服務器在接收到客戶端對過時鍵的讀命令時,依舊會返回該鍵對應的值給客戶端,而不會將其刪除。
參考《Redis設計與實現》,公衆號後臺回覆「redis」可自取該書電子版
PS:本文原創發佈於微信公衆號「不僅Java」,後臺回覆如下關鍵字獲取經典必讀書籍: Java、MySQL、Redis、Linux、mq、數據結構、設計模式、編程思想、架構
公衆號專一分享 Java 乾貨、讀書筆記、成長思考