Redisチュートリアル(8):トランザクションの詳細
5561 ワード
一、概説:
他の多くのデータベースと同様に、RedisはNoSQLデータベースとしてトランザクション・メカニズムを提供します.Redisでは、MULTI/EXEC/DISCARD/WATCHの4つのコマンドがトランザクションを実現するための基盤となります.リレーショナル・データベースの開発経験のある開発者にとって、この概念はよく知られていないと信じています.それでも、Redisのトランザクションの実装特徴を簡単にリストします.
1). トランザクション内のすべてのコマンドはシリアル化された順序で実行され、トランザクションの実行中、Redisは他のクライアントのリクエストにサービスを提供せず、物事内のすべてのコマンドが原子によって実行されることを保証します.
2). リレーショナル・データベース内のトランザクションと比較して、Redisトランザクションでコマンドの実行に失敗した場合、その後のコマンドは続行されます. 3). MULTIコマンドでトランザクションを開始できます.リレーショナル・データベースの開発経験のある人は、「BEGIN TRANSACTION」文と理解できます.文の後に実行されるコマンドは、トランザクション内のアクションとみなされ、最後にEXEC/DISCARDコマンドを実行することで、トランザクション内のすべてのアクションをコミット/ロールバックできます.この2つのRedisコマンドは、リレーショナル・データベースのCOMMIT/ROLLBACK文と同等とみなすことができる.
4). トランザクションが開始される前に、クライアントとサーバの間で通信障害が発生し、ネットワークが切断された場合、実行する文はすべてサーバによって実行されません.しかし、ネットワーク割り込みイベントがクライアントがEXECコマンドを実行した後に発生した場合、トランザクション内のすべてのコマンドはサーバによって実行されます.
5). Append-ONlyモードを使用すると、Redisはシステム関数writeを呼び出してトランザクション内のすべての書き込みを今回の呼び出しでディスクに書き込みます.しかし、書き込み中に電源障害によるダウンタイムなどのシステムクラッシュが発生した場合、ディスクに書き込まれたデータの一部だけが失われ、他のデータの一部が失われた可能性があります.Redisサーバは、再起動時に必要な一貫性検出の一連を実行し、類似の問題が発見されるとすぐに終了し、対応するエラー・プロンプトを表示します.この場合、データが一致しないエラーを特定し、書き込まれたデータの一部をロールバックするのに役立つRedisツールパッケージに提供されているredis-check-aofツールを十分に活用します.修復後、Redisサーバを再起動できます.
二、関連コマンドのリスト:
コマンドプロトタイプ
時間の複雑さ
コマンドの説明
戻り値
MULTI
トランザクションの開始をマークするために使用され、その後に実行されるコマンドは、EXECが実行されるまで原子によって実行されないコマンドキューに格納されます.
常にOKに戻る
EXEC
1つのトランザクション内のコマンド・キュー内のすべてのコマンドを実行し、現在の接続のステータスを通常のステータス、すなわち非トランザクション・ステータスに戻します.トランザクションでWATCHコマンドが実行されている場合、EXECコマンドは、WATCHが監視するKeysが変更されていない場合にのみ、トランザクションキュー内のすべてのコマンドを実行できます.そうしないと、EXECは現在のトランザクションのすべてのコマンドを放棄します.
原子的な戻りトランザクション内の各コマンドの戻り結果.トランザクションでWATCHが使用されている場合、トランザクションが破棄されると、EXECはNULL-multi-bulk返信を返します.
DISCARD
トランザクション・キュー内のすべてのコマンドをロールバックし、現在の接続のステータスを通常のステータス、すなわち非トランザクション・ステータスに戻します.WATCHコマンドが使用されている場合、このコマンドはUNWATCHのすべてのKeysになります.
常にOKに戻ります.
WATCHkey [key ...]
O(1)
MULTIコマンドが実行される前に、監視対象のKeysを指定できますが、EXECが実行される前に、監視対象のKeysが変更されると、EXECはトランザクションキュー内のすべてのコマンドの実行を放棄します.
常にOKに戻ります.
UNWATCH
O(1)
現在のトランザクションで指定されているモニタリングのKeysをキャンセルします.EXECまたはDISCARDコマンドが実行されている場合、このコマンドを手動で実行する必要はありません.これは、その後、トランザクション内のすべてのモニタリングされているKeysが自動的にキャンセルされるためです.
常にOKに戻ります.
三、コマンドの例:
1. トランザクションは正常に実行されます.
2. トランザクションに失敗したコマンドがあります.
3. トランザクションのロールバック:
四、WATCHコマンドとCASベースの楽観ロック:
Redisのトランザクションでは、WATCHコマンドを使用してCAS(check-and-set)機能を提供できます.WATCHコマンドを使用して、トランザクションの実行前に複数のKeysを監視したとします.WATCHの後にキーの値が変化した場合、EXECコマンドで実行されたトランザクションは破棄され、Null multi-bulk応答に戻って呼び出し元のトランザクションの実行に失敗したことを通知します.たとえば、Redisではincrコマンドがキー値の原子的な増加を完了するために提供されていないと再仮定し、この機能を実現するには、対応するコードを自分で作成するしかありません.疑似コードは次のとおりです.
上記のコードは、同じ時点で複数のクライアントが同時にこのセグメントコードを実行すると、マルチスレッドプログラムでよく発生するエラーシーンである競合競合競合(race condition)が発生するため、単一接続の場合にのみ実行結果が正しいことを保証することができる.例えば、クライアントAとBは、同じ時刻にmykeyの元の値を読み出し、この値が10であると仮定し、その後、2つのクライアントが値を1つ加算してRedisサーバにセットバックすると、mykeyの結果は12ではなく11になります.同様の問題を解決するには、WATCHコマンドの助けが必要です.次のコードを参照してください.
これまでのコードとは異なり、新しいコードはmykeyの値を取得する前にWATCHコマンドでキーを監視し、その後setコマンドをトランザクションに囲みます.これにより、各接続がEXECを実行する前に、現在接続で取得したmykeyの値が他の接続のクライアントによって変更された場合、現在接続されているEXECコマンドが失敗することを効果的に保証できます.これにより、呼び出し者は、戻り値を判断した後、valが再設定されたかどうかを知ることができる.
他の多くのデータベースと同様に、RedisはNoSQLデータベースとしてトランザクション・メカニズムを提供します.Redisでは、MULTI/EXEC/DISCARD/WATCHの4つのコマンドがトランザクションを実現するための基盤となります.リレーショナル・データベースの開発経験のある開発者にとって、この概念はよく知られていないと信じています.それでも、Redisのトランザクションの実装特徴を簡単にリストします.
1). トランザクション内のすべてのコマンドはシリアル化された順序で実行され、トランザクションの実行中、Redisは他のクライアントのリクエストにサービスを提供せず、物事内のすべてのコマンドが原子によって実行されることを保証します.
2). リレーショナル・データベース内のトランザクションと比較して、Redisトランザクションでコマンドの実行に失敗した場合、その後のコマンドは続行されます. 3). MULTIコマンドでトランザクションを開始できます.リレーショナル・データベースの開発経験のある人は、「BEGIN TRANSACTION」文と理解できます.文の後に実行されるコマンドは、トランザクション内のアクションとみなされ、最後にEXEC/DISCARDコマンドを実行することで、トランザクション内のすべてのアクションをコミット/ロールバックできます.この2つのRedisコマンドは、リレーショナル・データベースのCOMMIT/ROLLBACK文と同等とみなすことができる.
4). トランザクションが開始される前に、クライアントとサーバの間で通信障害が発生し、ネットワークが切断された場合、実行する文はすべてサーバによって実行されません.しかし、ネットワーク割り込みイベントがクライアントがEXECコマンドを実行した後に発生した場合、トランザクション内のすべてのコマンドはサーバによって実行されます.
5). Append-ONlyモードを使用すると、Redisはシステム関数writeを呼び出してトランザクション内のすべての書き込みを今回の呼び出しでディスクに書き込みます.しかし、書き込み中に電源障害によるダウンタイムなどのシステムクラッシュが発生した場合、ディスクに書き込まれたデータの一部だけが失われ、他のデータの一部が失われた可能性があります.Redisサーバは、再起動時に必要な一貫性検出の一連を実行し、類似の問題が発見されるとすぐに終了し、対応するエラー・プロンプトを表示します.この場合、データが一致しないエラーを特定し、書き込まれたデータの一部をロールバックするのに役立つRedisツールパッケージに提供されているredis-check-aofツールを十分に活用します.修復後、Redisサーバを再起動できます.
二、関連コマンドのリスト:
コマンドプロトタイプ
時間の複雑さ
コマンドの説明
戻り値
MULTI
トランザクションの開始をマークするために使用され、その後に実行されるコマンドは、EXECが実行されるまで原子によって実行されないコマンドキューに格納されます.
常にOKに戻る
EXEC
1つのトランザクション内のコマンド・キュー内のすべてのコマンドを実行し、現在の接続のステータスを通常のステータス、すなわち非トランザクション・ステータスに戻します.トランザクションでWATCHコマンドが実行されている場合、EXECコマンドは、WATCHが監視するKeysが変更されていない場合にのみ、トランザクションキュー内のすべてのコマンドを実行できます.そうしないと、EXECは現在のトランザクションのすべてのコマンドを放棄します.
原子的な戻りトランザクション内の各コマンドの戻り結果.トランザクションでWATCHが使用されている場合、トランザクションが破棄されると、EXECはNULL-multi-bulk返信を返します.
DISCARD
トランザクション・キュー内のすべてのコマンドをロールバックし、現在の接続のステータスを通常のステータス、すなわち非トランザクション・ステータスに戻します.WATCHコマンドが使用されている場合、このコマンドはUNWATCHのすべてのKeysになります.
常にOKに戻ります.
WATCHkey [key ...]
O(1)
MULTIコマンドが実行される前に、監視対象のKeysを指定できますが、EXECが実行される前に、監視対象のKeysが変更されると、EXECはトランザクションキュー内のすべてのコマンドの実行を放棄します.
常にOKに戻ります.
UNWATCH
O(1)
現在のトランザクションで指定されているモニタリングのKeysをキャンセルします.EXECまたはDISCARDコマンドが実行されている場合、このコマンドを手動で実行する必要はありません.これは、その後、トランザクション内のすべてのモニタリングされているKeysが自動的にキャンセルされるためです.
常にOKに戻ります.
三、コマンドの例:
1. トランザクションは正常に実行されます.
# Shell Redis 。
/> redis-cli
# 。
redis 127.0.0.1:6379> multi
OK
# , , , 。
redis 127.0.0.1:6379> incr t1
QUEUED
# , , 。
redis 127.0.0.1:6379> incr t2
QUEUED
# , , 。
redis 127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
2. トランザクションに失敗したコマンドがあります.
# 。
redis 127.0.0.1:6379> multi
OK
# a string 3。
redis 127.0.0.1:6379> set a 3
QUEUED
# a , , lpop List , exec , 。
redis 127.0.0.1:6379> lpop a
QUEUED
# a 4。
redis 127.0.0.1:6379> set a 4
QUEUED
# a , set 。
redis 127.0.0.1:6379> get a
QUEUED
# , lpop , set get , Redis 。
redis 127.0.0.1:6379> exec
1) OK
2) (error) ERR Operation against a key holding the wrong kind of value
3) OK
4) "4"
3. トランザクションのロールバック:
# t2 。
redis 127.0.0.1:6379> set t2 tt
OK
# 。
redis 127.0.0.1:6379> multi
OK
# 。
redis 127.0.0.1:6379> set t2 ttnew
QUEUED
# 。
redis 127.0.0.1:6379> discard
OK
# t2 , 。
redis 127.0.0.1:6379> get t2
"tt"
四、WATCHコマンドとCASベースの楽観ロック:
Redisのトランザクションでは、WATCHコマンドを使用してCAS(check-and-set)機能を提供できます.WATCHコマンドを使用して、トランザクションの実行前に複数のKeysを監視したとします.WATCHの後にキーの値が変化した場合、EXECコマンドで実行されたトランザクションは破棄され、Null multi-bulk応答に戻って呼び出し元のトランザクションの実行に失敗したことを通知します.たとえば、Redisではincrコマンドがキー値の原子的な増加を完了するために提供されていないと再仮定し、この機能を実現するには、対応するコードを自分で作成するしかありません.疑似コードは次のとおりです.
val = GET mykey
val = val + 1
SET mykey $val
上記のコードは、同じ時点で複数のクライアントが同時にこのセグメントコードを実行すると、マルチスレッドプログラムでよく発生するエラーシーンである競合競合競合(race condition)が発生するため、単一接続の場合にのみ実行結果が正しいことを保証することができる.例えば、クライアントAとBは、同じ時刻にmykeyの元の値を読み出し、この値が10であると仮定し、その後、2つのクライアントが値を1つ加算してRedisサーバにセットバックすると、mykeyの結果は12ではなく11になります.同様の問題を解決するには、WATCHコマンドの助けが必要です.次のコードを参照してください.
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
これまでのコードとは異なり、新しいコードはmykeyの値を取得する前にWATCHコマンドでキーを監視し、その後setコマンドをトランザクションに囲みます.これにより、各接続がEXECを実行する前に、現在接続で取得したmykeyの値が他の接続のクライアントによって変更された場合、現在接続されているEXECコマンドが失敗することを効果的に保証できます.これにより、呼び出し者は、戻り値を判断した後、valが再設定されたかどうかを知ることができる.