Redis、まだDELコマンドで消耗しているの?
煽りタイトルですいません。
Redis のデータ削除によるブロッキング
Redis におけるクライアントからのデータ削除は、 v3 系までは DEL ・ FLUSHALL ・ FLUSHDB がありました。
また Redis 自身による削除として、有効期限 (TTL) 切れ時の EXPIRE とメモリ溢れ時の EVICTION 、 Replica が Full Sync し直す際の flush がありました。
特に DEL コマンドや FLUSH 系コマンドは削除対象となるデータ数に比例して処理をブロッキングします。
SET 型や HASH 型で要素数が非常に多い場合は、 1 つの Key を DEL しただけでも数秒処理が止まることもあります。
Lazy Free 機能
Redis v4 以降から、 DEL に対応する UNLINK と FLUSH 系コマンドには async
オプションが追加されました。
これらのコマンド・オプションはメモリを遅延解放するというものです。
これによりキー削除時にブロッキングを最小でデータ削除が行えるようになりました。
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> UNLINK key1 key2 key3
(integer) 2
redis> GET KEY1
(nil)
トレードオフとして予測可能性の悪化があります。
Lazy Free では当然ながらメモリ解放の遅延により、一時的に Redis の消費メモリが跳ねうります。
十分なメモリの空き(=削除されるデータ量分程度)を確保できていれば、そのメモリでパフォーマンスが買える機能といえます。
また、 Redis 自身による EXPIRE や EVICTION 、 Replica の Full Sync 前の flush なども Lazy Free する設定も追加されています。
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
※ yes にすると有効化される。
Appendix
アプリケーションの DEL を置き換えるのが大変な場合
Redis v6 からは、 lazyfree-lazy-user-del という設定値が増えました。
クライアントから DEL
コマンドが発行されると、内部的には UNLINK と同様の処理をするというものです。
※ソースコードを見てもわかるように、このフラグひとつで UNLINK 化します。
lazyfree-lazy-user-del no
※ yes にすると有効化される。
このフラグは CONFIG SET コマンドでオンラインに on/off 可能なため、アプリケーションを書き換える前に実験的に試してみるのも良いでしょう。
Lazy Free に関する議論
過去の議論が気になる方はこの Issue を追いかけると良いでしょう。
Lazy free of keys and databases · Issue #1748 · redis/redis · GitHub
Discussion