本文對redis的過期處理機制做個簡單的概述,讓大家有個基本的認識。
Redis中有個設置時間過期的功能,即對存儲在redis數據庫中的值可以設置一個過期時間。作為一個緩存數據庫,這是非常實用的。如我們一般項目中的token或者一些登錄信息,尤其是短信驗證碼都是有時間限制的,按照傳統的數據庫處理方式,一般都是自己判斷過期,這樣無疑會嚴重影響項目性能。
一、有效時間設置:
redis對存儲值的過期處理實際上是針對該值的鍵(key)處理的,即時間的設置也是設置key的有效時間。Expires字典保存了所有鍵的過期時間,Expires也被稱為過期字段。
四種處理策略
EXPIRE 將key的生存時間設置為ttl秒
PEXPIRE 將key的生成時間設置為ttl毫秒
EXPIREAT 將key的過期時間設置為timestamp所代表的的秒數的時間戳
PEXPIREAT 將key的過期時間設置為timestamp所代表的的毫秒數的時間戳
其實以上幾種處理方式都是根據PEXPIREAT來實現的,設置生存時間的時候是redis內部計算好時間之后在內存處理的,最終的處理都會轉向PEXPIREAT。
1、2兩種方式是設置一個過期的時間段,就是咱們處理驗證碼最常用的策略,設置三分鍾或五分鍾后失效,把分鍾數轉換成秒或毫秒存儲到redis中。
3、4兩種方式是指定一個過期的時間 ,比如優惠券的過期時間是某年某月某日,只是單位不一樣。
二、過期處理
過期鍵的處理就是把過期鍵刪除,這里的操作主要是針對過期字段處理的。
Redis中有三種處理策略:定時刪除、惰性刪除和定期刪除。
定時刪除:在設置鍵的過期時間的時候創建一個定時器,當過期時間到的時候立馬執行刪除操作。不過這種處理方式是即時的,不管這個時間內有多少過期鍵,不管服務器現在的運行狀況,都會立馬執行,所以對CPU不是很友好。
惰性刪除:惰性刪除策略不會在鍵過期的時候立馬刪除,而是當外部指令獲取這個鍵的時候才會主動刪除。處理過程為:接收get執行、判斷是否過期(這里按過期判斷)、執行刪除操作、返回nil(空)。
定期刪除:定期刪除是設置一個時間間隔,每個時間段都會檢測是否有過期鍵,如果有執行刪除操作。這個概念應該很好理解。
看完上面三種策略后可以得出以下結論:
4. 1、3為主動刪除,2為被動刪除。
5. 1是實時執行的,對CPU不是很友好,但是這在最大程度上釋放了內存,所以這種方式算是一種內存優先優化策略。
6. 2、3為被動刪除,所以過期鍵應該會存在一定的時間,這樣就使得過期鍵不會被立馬刪除,仍然占用着內存。但是惰性刪除的時候一般是單個刪除,相對來說對CPU是友好的。
7. 定期鍵這種刪除策略是一種讓人很蛋疼的策略,它既有避免1、2兩種策略劣勢的可能,也有同時發生1、2兩種策略劣勢的可能。如果定期刪除執行的過於頻繁就可能會演變成定時刪除,如果執行的過少就有可能造成過多過期鍵未被刪除而占用過多內存,如果時間的設置不是太好,既可能占用過多內存又同時對CPU產生不好的影響。所以。使用定期刪除的時候一定要把握好這個刪除的時間點。存在即為合理,既然開發的時候有這種策略,就說明定期刪除還是有他的優勢的,具體大家可以自己琢磨。
三、主從服務器刪除過期鍵處理
參考書上說的有三種:RDB持久化、AOF持久化和復制功能。
RDB:
1. 主服務器模式運行在載入RDB文件時,程序會檢查文件中的鍵,只會加載未過期的,過期的會被忽略,所以RDB模式下過期鍵不會對主服務器產生影響。
2. 從服務器運行載入RDB文件時,會載入所有鍵,包括過期和未過期。當主服務器進行數據同步的時候,從服務器的數據會被清空,所以RDB文件的過期鍵一般不會對從服務器產生影響。
AOF:
AOF文件不會受過期鍵的影響。如果有過期鍵未被刪除,會執行以下動作:
客戶端請求時(過期鍵):
從數據庫充刪除被訪問的過期鍵;
追加一條DEL 命令到AOF文件;
向執行請求的客戶端回復nil(空)。
復制:
主服務器刪除過期鍵之后,向從服務器發送一條DEL指令,告知刪除該過期鍵。
從服務器接收到get指令的時候不會對過期鍵進行處理,只會當做未過期鍵一樣返回。(為了保持主從服務器數據的一致性)
從服務器只有接到主服務器發送的DEL指令后才會刪除過期鍵。
參考書籍:《Redis設計與實現》黃健宏著