Redis Keyspace Notificationsとは
Redisには、キーに影響を与えるコマンドが実行されたタイミングや、キーが期限切れになったタイミングなどにRedisのPub/Subチャネルを介してクライアントにイベントを通知するRedis Keyspace Notifications
という機能があります。
CPUにある程度負荷がかかることを考慮してRedisのデフォルトでは無効になっていますが、Spring Sessionで利用する際には設定を有効にしておかないと、期限切れのセッションがRedisに残り続けパフォーマンスに影響を与えることになります。
※ Spring SessionではRedisサーバ側でRedis Keyspace Notificationsが無効になっていても、自動的にCONFIGコマンドを実行して有効にしてくれますが、クラウドサービスが提供しているマネージドなRedisなどでCONFIGコマンドが禁止されている環境では、開発者が明示的にRedisサーバの設定を変更する必要があります。
今回は、Redisのコマンドを実際に叩いて、発火されるイベントを見てみたいと思います。
redis serverの起動
redis serverやredis-cliをインストールする手順は割愛します。brew install redis
など好きな方法でインストールしてください。
まずは、redis serverをローカル上で起動します
$ redis-server 12207:C 29 Dec 2020 11:48:24.240 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 12207:C 29 Dec 2020 11:48:24.240 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=12207, just started 12207:C 29 Dec 2020 11:48:24.240 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 12207:M 29 Dec 2020 11:48:24.241 * Increased maximum number of open files to 10032 (it was originally set to 256). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.0.9 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 12207 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 12207:M 29 Dec 2020 11:48:24.244 # Server initialized 12207:M 29 Dec 2020 11:48:24.244 * Ready to accept connections
Redis Keyspace Notificationsを有効にする
redis serverの起動が完了したら、別のターミナルを開いてredis serverに接続します。
$ redis-cli 127.0.0.1:6379>
redis serverに接続したら、デフォルトで無効になっているRedis Keyspace Notificationsを有効にします。
CONFIG
コマンドを使ってnotify-keyspace-events
というパラメータに値を設定します。
127.0.0.1:6379> config set 'notify-keyspace-events' AKE
notify-keyspace-eventsに設定する文字列は1文字ずつそれぞれ意味があります。
例では、AKE
という文字列を設定していますが、これは、存在しないキーにアクセスするコマンド以外でキーに影響を与えるコマンド操作全て(A)のKeyspace event(K)とKeyevent event(E)を受け取る、という意味になります。
設定する値の詳細については以下を参照してください。
https://redis.io/docs/manual/keyspace-notifications/
イベントの監視
Redisで発火されるイベントを監視するためにPSUBSCRIBE
コマンドを実行します。
127.0.0.1:6379> psubscribe * Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "*" 3) (integer) 1
以降、イベントが発火されるとこの画面にイベントの情報が表示されます。
イベントを発火させてみる
試しに、別ターミナルを開いてredis serverに接続して、キーを追加してみます。
$ redis-cli 127.0.0.1:6379> set foo Foo OK
PSUBSCRIBEコマンドを実行していた画面をみると、イベントが発火されていることが確認できます。
Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "*" 3) (integer) 1 1) "pmessage" 2) "*" 3) "__keyspace@0__:foo" 4) "set" 1) "pmessage" 2) "*" 3) "__keyevent@0__:set" 4) "foo"
同様に、別ターミナルでキーを削除してみます。
$ redis-cli 127.0.0.1:6379> del foo (integer) 1
PSUBSCRIBEコマンドを実行していた画面をみると、イベントが発火されていることが確認できます。
1) "pmessage" 2) "*" 3) "__keyspace@0__:foo" 4) "del" 1) "pmessage" 2) "*" 3) "__keyevent@0__:del" 4) "foo"
最後に期限切れを迎えた場合のイベントを確認してみます。 キーを追加して、有効期限を10秒に設定します。
$ redis-cli 127.0.0.1:6379> set bar Bar OK 127.0.0.1:6379> expire bar 10 (integer) 1
PSUBSCRIBEコマンドを実行していた画面をみると、EXPIRE
実行時にイベントが発火され、さらに10秒後にイベントが発火されていることが確認できます。
1) "pmessage" 2) "*" 3) "__keyspace@0__:bar" 4) "expire" 1) "pmessage" 2) "*" 3) "__keyevent@0__:expire" 4) "bar" // 10秒後 1) "pmessage" 2) "*" 3) "__keyspace@0__:bar" 4) "expired" 1) "pmessage" 2) "*" 3) "__keyevent@0__:expired" 4) "bar"