Redis有効期限の設定に関する注意事項


前言
Redisを使ったことがある人は知っているはずですが、Redisの各キーは期限切れを設定することができ、期限切れになると自動的に削除されます.しかし、期限切れを設定したkeyの中には、設定した時点で失効していないものもあることがあります.ここでは、期限切れについて詳しくお話しします.
有効期限の設定に注意すべき事項
1、DEL/SET/GETSETなどのコマンドは期限切れをクリアする
DEL、SET、GETSETなどのkey対応valueを上書きするコマンドを使用して、有効期限を設定したkeyを操作すると、対応するkeyの有効期限がクリアされます.
//  mykey      500s
127.0.0.1:6379> set tkey test ex 500
OK
//      
127.0.0.1:6379> ttl tkey 
(integer) 294
//  set    tkey   
127.0.0.1:6379> set tkey updatetest
OK
//       
127.0.0.1:6379> ttl tkey
(integer) -1

2、INCR/LPUSH/HSETなどのコマンドでは有効期限はクリアされません
一方、INCR/LPUSH/HSETというkeyを変更するだけのvalueを使用すると、value全体を上書きするコマンドではなく、keyの有効期限はクリアされません.
INCR:
//  incr_key      500s
127.0.0.1:6379> set incr_key 1 ex 500
OK
127.0.0.1:6379> ttl incr_key
(integer) 390
//      
127.0.0.1:6379> incr incr_key
(integer) 2
127.0.0.1:6379> get incr_key
"2"
//      ,           
127.0.0.1:6379> ttl incr_key
(integer) 312

LPUSH:
//    list   key,      1  
127.0.0.1:6379> LPUSH list 1
(integer) 1
// list  500s     
127.0.0.1:6379> expire list 500
(integer) 1
//      
127.0.0.1:6379> ttl list
(integer) 392
// list     2
127.0.0.1:6379> lpush list 2
(integer) 2
//  list    
127.0.0.1:6379> lrange list 0 1
1) "2"
2) "1"
//    list               
127.0.0.1:6379> ttl list
(integer) 352

3、PERSISTコマンドは期限切れをクリアする
PERSISTコマンドを使用して、有効期限が設定されているkeyを永続化されたkeyに変更すると、有効期限もクリアされます.
127.0.0.1:6379> set persist_key hello ex 400
OK
127.0.0.1:6379> ttl persist_key
(integer) 396
// key      
127.0.0.1:6379> persist persist_key
(integer) 1
//       
127.0.0.1:6379> ttl persist_key
(integer) -1

4、RENAMEコマンドを使用すると、古いキーの有効期限が新しいキーに移動します
使用例:RENAME KEY_1 KEY_2コマンドKEY_1名前をKEY_に変更2、KEY_にかかわらず1有効期限が設定されているか、新しいkey KEY_2 KEY_を引き継ぐ1のすべてのプロパティ.
//  key_1      400s
127.0.0.1:6379> set key_1 value_1 ex 400
OK
//  key_2      500s
127.0.0.1:6379> set key_2 value_2 ex 500
OK
127.0.0.1:6379> ttl key_1
(integer) 379
127.0.0.1:6379> ttl key_2
(integer) 391
// key_1    key_2
127.0.0.1:6379> rename key_1 key_2
OK
//  key_1   key_2     
127.0.0.1:6379> ttl key_2
(integer) 348

5、EXPIRE/PEXPIREを使用して設定した有効期限が負の場合、またはEXPIREAT/PEXPIREATを使用して有効期限を設定した場合、keyが削除される
EXPIRE:
127.0.0.1:6379> set key_1 value_1
OK
127.0.0.1:6379> get key_1
"value_1"
//       -1
127.0.0.1:6379> expire key_1 -1
(integer) 1
//  key   
127.0.0.1:6379> get key_1
(nil)

EXPIREAT:
127.0.0.1:6379> set key_2 value_2
OK
127.0.0.1:6379> get key_2
"value_2"
//            
127.0.0.1:6379> expireat key_2 10000
(integer) 1
//key   
127.0.0.1:6379> get key_2
(nil)

6、EXPIREコマンドで有効期限を更新できる
有効期限が設定されているkeyに対してexpireコマンドを使用して、有効期限を更新できます.
//  key_1      100s
127.0.0.1:6379> set key_1 value_1 ex 100
OK
127.0.0.1:6379> ttl key_1
(integer) 95
//  key_1      300s
127.0.0.1:6379> expire key_1 300
(integer) 1
127.0.0.1:6379> ttl key_1
(integer) 295

Redis 2.1.3次のバージョンでは、expireコマンドを使用して有効期限が設定されているkeyの有効期限を更新すると失敗します.また、有効期限が設定されているキーにLPUSH/HSETなどのコマンドを使用してvalueを変更すると、Redisがキーを削除します.
Redisの失効ポリシー
もしRedisの中に大量のkeyがあるならば、どのように効率的に期限切れのkeyを探し出してそれを削除することができて、もし遍歴の方式を採用するならば、もし同じ時期に期限切れのkeyが非常に多いならば、Redisはずっと期限切れの事件を処理するため、命令のカートンを読み書きすることができますか.
Redisは単一スレッドであるため、Redisデータ量が特に大きい場合、keys*コマンドを使用してすべてのkeyをリストするなど、時間のかかる操作によってRedisカートンが発生します.
実際にRedisは怠惰削除+定期削除を組み合わせた方法で期限切れのkeyを処理する.
1.怠惰削除
怠惰な削除とは、クライアントがそのkeyにアクセスしたときにredisがkeyの期限切れをチェックし、期限切れになったらすぐに削除することです.
この方法は完璧に見え、アクセス時にkeyの期限切れをチェックし、余分なCPUリソースをあまり消費しません.しかし、1つのキーが期限切れになっている場合、長い間アクセスされていない場合、このキーはメモリに保存され、メモリリソースを深刻に消費します.
2.定期的に削除
定期的に削除する原理は、Redisが有効期限を設定したkeyをすべて辞書に入れ、一定時間ごとに辞書から有効期限をランダムにチェックし、有効期限を削除することです.
Redisのデフォルトでは、1秒あたり10回の期限切れスキャンが行われます.
(1)期限切れ辞書からランダムに20個のkey(2)この20個のkeyの期限切れを削除(3)25%を超えるkeyが期限切れした場合、最初のステップを繰り返す
また、Redisは、ループオーバーが発生しないようにスキャンの時間上限を設定し、デフォルトでは25 msを超えません.