Redisのトランザクションについてまとめます。MULTIコマンドを使用するとアトミックな(原子性のある)制御をし、WATCHコマンドを使用すると楽観的排他制御を実現できます。
前提
公式ドキュメント
参考になる公式ドキュメントを以下に示します。
動作確認済環境
- Rocky Linux 8.6
- Redis 5.0.3
MULTIコマンド
COMMIT処理(EXECコマンド)
MULTIコマンドを使用すると、一連のコマンドをアトミックに処理できます。まずはテスト用のデータを投入します。
127.0.0.1:6379> SET foo 1 OK 127.0.0.1:6379> SET baa 1 OK 127.0.0.1:6379>
MULTIコマンド入力後の処理が1つのトランザクションとして扱われます。以下の操作例の場合は、fooとbaaの加算が1つのトランザクションとして実行されます。
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> INCR foo QUEUED 127.0.0.1:6379> INCR baa QUEUED 127.0.0.1:6379>
トランザクションを処理(実行)する場合は、EXECコマンドを実行します。RDBMSにおけるCOMMIT相当の操作です。
127.0.0.1:6379> EXEC 1) (integer) 2 2) (integer) 2 127.0.0.1:6379>
ROLLBACK処理(DISCARDコマンド)
MULTIコマンドをの過程で、DISCARDコマンドを使用するとトランザクションを破棄します。まずはテスト用のトランザクションを作成します。
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> INCR foo QUEUED 127.0.0.1:6379> INCR baa QUEUED 127.0.0.1:6379>
DISCARDコマンドを使用すると、トランザクションを破棄できます。
127.0.0.1:6379> DISCARD OK 127.0.0.1:6379>
WATCHコマンド(楽観的排他制御)
処理成功の場合
WATCHコマンドを使うと、楽観的排他制御ができます。以下のようにWATCHコマンドを使用すると、他者がfooの値を変更していない場合のみ処理が成功します。
127.0.0.1:6379> SET foo 1 OK 127.0.0.1:6379> WATCH foo OK 127.0.0.1:6379>
以下のようにMULTIコマンドとEXECコマンドを使用すると、WATCHコマンド実行からEXECコマンドまでの間で他者がfooの値を変更していない場合のみ処理が成功します。
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> INCR foo QUEUED 127.0.0.1:6379> EXEC 1) (integer) 2 127.0.0.1:6379>
処理失敗の場合
処理失敗の場合も観察してみましょう。まず、ある端末でWATCHコマンドを実行します。
127.0.0.1:6379> SET foo 1 OK 127.0.0.1:6379> WATCH foo OK 127.0.0.1:6379>
その後、別の端末でfooの値を変更します。
127.0.0.1:6379> SET foo 5 OK 127.0.0.1:6379>
この状態でfooの値の変更を試みると、EXECコマンド実行時にnilが返されます。
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> INCR foo QUEUED 127.0.0.1:6379> EXEC (nil) 127.0.0.1:6379>