daisuzz.log

Redis Keyspace Notificationsで発火されるイベントを見てみる

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"

参考

https://redis.io/docs/manual/keyspace-notifications/