Redis的過期設置,大家基本都用過了。但是裡面的坑不知道各位是否瞭解。
先從基礎講起。
Redis中的所有數據結構都可以設置超時時間,設置超時有四種做法:
EXPIRE 將key的生存時間設置為ttl秒
PEXPIRE 將key的生成時間設置為ttl毫秒
EXPIREAT 將key的過期時間設置為timestamp所代表的的秒數的時間戳
PEXPIREAT 將key的過期時間設置為timestamp所代表的的毫秒數的時間戳
如果讓我們自己來設計過期刪除策略,我們會怎麼做?
可能會想到做一個掃描器,對超時的key進行定時掃描收割。
但是內存中的key太多了,不可能做全部掃描。redis的做法是將設置了超時時間的key放到一個單獨的字典中,以後對這個字典進行單獨掃描。
但是,如果這個字典過大,仍然有全部掃描一次會耗時很長的問題。
這裡redis的做法值得我們借鑑:
Redis採用一種惰性刪除的策略,即過期的key並不會被立即刪除。
Redis默認每秒掃描10次超時字典。每次隨機取出20個key,對這20個key進行超時刪除。如果有超多四分之一(即5個)的key被刪除了.那麼再去取20個key進行超時刪除。一直這樣循環下去,直到字典中過期的ley變得稀疏。
同時,為了保證過期掃描不會出現循環過度,導致線程卡死現象,算法還增加了掃描時間的上限,默認不會超過 25ms。
那麼,這種策略還是有一個問題是,對於一個大型redis,如果客戶端請求到來時,正好在進行過期掃描,並且過期的key非常多,一直掃描了25ms。如果這個客戶端的請求設置了超時時間10ms,那麼就會出現大量的客戶端連接因為超時而關閉。
所以,這就引出了Redis設置超時策略一個坑:
不要將大量的key,設置在同一時間過期。
這種情況下最好加一個指定過期時間上加一個隨機變量時間。
閱讀更多 IT技術圈 的文章