業務
Redisのトランザクション機能は、ユーザーが複数のコマンドをラップすることができ、その後、1時間、連続的に包まれたすべてのコマンド。
トランザクションの実行の過程では、サーバはすべての区画が終了した後にのみ他のコマンド、コマンドトランザクションを実行するためのトランザクションと変更要求を中断しません、サーバーは、他のコマンドを処理するために要求します。
使用のトランザクションの例
今、私たちはそのSETEXコマンドを想定してみましょう私たちはSETEX自身のコマンドを達成する必要がある場合は、その後、我々は次のコードを使用することができ、Redisの中に存在しない、とSETコマンドのパラメーターEX秒をサポートしていません。
def SETEX(key, seconds, value):
SET key value
EXPIRE key seconds
一般的には、このキーを設定するには、自家製SETEXコマンドを達成し、生産時間の効果を設定することができますが、自家製SETEX欠陥がある:サーバーは、SETコマンドの実装を成功した後、データ保存クラッシュした場合、コマンドは期限切れになります実行する方法はありません。
この時点で、我々はキーを設定しているが、キーの有効期限を設定しなかったが、我々は、これは定期的に削除されている必要があることを見つけていない場合は、メモリ内の鍵データベースに残されていたであろうとしても、エラーの原因の後にプログラムによって占められ。
Transactionコマンド
上記の出会いの上を避けるために、我々は、我々ができる取引を通じてRedisのトランザクション機能を使用する必要があるトランザクションまたはすべてを実行するために、または持っていることを保証するために、一度にRedisの複数のコマンドを作り、順番にそれは実行されません。
トランザクションを開始
MULTIは
トランザクションを開始します。このコマンドが実行された後、データベースまたはデータベースキーのクライアントから送信されたすべてのコマンドは即時に実行されませんが、トランザクションキューの内部に入れられ、そしてチームへのコマンドことQUEUED手段を返します。
redis> MULTI # 开始一个事务
OK
redis> SET msg "hello world" # 将这个 SET 命令放入事务队列
QUEUED
redis> EXPIRE msg 10086 # 将这个 SET 命令放入事务队列
QUEUED
複雑さはO(1)です。
トランザクションを放棄
DISCARDは、
トランザクション・キュー内のすべてのコマンドをあきらめ、トランザクションを取り消します。複雑さはO(1)です。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> DISCARD # 事务已被取消
OK
redis> SET msg "hello world"
OK
執行部
EXEC
コマンドの順序に従って、トランザクションキューに、トランザクションキューにすべてのコマンドをキューに入れられています。
すべてのコマンドのコマンドキューと複雑さの複雑さ。
戻り値はコマンドリストで、リストには、コマンドの戻り値を実行するすべてのトランザクション・キューが含まれています。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> EXEC
1) OK # SET 命令的返回值
2) (integer) 1 # EXPIRE 命令的返回值
トランザクションの安全保障の操作を使用します
SETEXの自家製はセキュリティ上の欠陥で、前に定義されました:
def SETEX(key, seconds, value):
SET key value
EXPIRE key seconds # 如果服务器在 SET 命令执行之后崩溃,那么 EXPIRE 将无法执行
使用事务实现的自制 SETEX 的定义,没有安全缺陷,服务器保证要么两个命令都执行,要么就两个命令都不执行:
def SETEX(key, seconds, value):
MULTI
SET key value
EXPIRE key seconds
EXEC
パイプラインとトランザクションの違い
(PIPELINE_START)
SET msg “hello world” # 这两条命令会被一起发送至服务器
EXPIRE msg 10086
(PIPELINE_END)
MULTI
SET msg “hello world” # 这两条命令会一起被服务器执行
EXPIRE msg 10086
EXEC
オプティミスティック・ロック
使用して、データの正確さを保証するために、ロック
データの正確さを保証するために、楽観ロックを使用します
MULTIとEXECを使用することにより、我々は、すべてのコマンドを実行したり、データの破損を防ぐために上で実行されていないのいずれか、そのトランザクションを確実にするために、単一のトランザクションの実行に複数のコマンドすることができます。しかし、時には唯一のトランザクションは、まだデータの正確性、我々はRedisの(オプティミスティック・ロック)が提供する楽観的ロック機能を使用する必要があり、この時間を保証することはできません。
我々が言っている順序付きコレクションの前に導入されたときに、例えば、RedisのはZINCRBYコマンド要素はインクリメント演算子のスコアだったが、自己スコアの対応する要素のために用意されていません提供します以下ZDECRBYコマンド操作は、私たち自身のZDECRBYコマンドを達成するために、我々はこのようなコードを書くかもしれません。
def ZDECRBY(key, decrment, member):
# 取得元素当前的分值
old_score = ZSCORE key member
# 使用当前分值减去指定的减量,得出新的分 值
new_score = old_score - decrment
# 为元素设置新分值,覆盖现有的分值
ZADD key new_score member
ZDECRBY競争条件(1/2)
要素の値を低減する効果を達成ZDECRBY上に実現することができるが、複数のクライアントが同時に同じ要素のZDECRBYを呼び出すと、この実装は競合状態を含むが、この競合状態が発生する可能性があります。
例えば、今、両方のクライアントとは、状況に表に示す300ピーター・ピーターの要素は、起こり得るZDECRBY給与500ピーターZDECRBY給与を実行する場合、ピーター素子4000スコア給与の順序集合と仮定する。
ZDECRBY競争条件(2/2)
適切な状況の下で、4000のオリジナルスコアのピーター要素500及び300を控除された後、スコアは3200匹の魚に変更しなければなりません。
但是在上面的这个表中, 客户端 A 和客户端 B 先后对 peter 元素的分值进行减法操作, 并且客户端 A 的 ZADD 操作比客户端 B 的 ZADD 操作更早执行, 当客户端 B 执行 ZADD 时, 它不知道 peter 元素当前的分值已经出现了变化,导致它计算出的新分值 3700 已经过期了, 而是继续一味地进行设置, 使 得计算出现了错误。
WATCH 命令
为了消除 ZDECRBY 实现中的竞争条件, 我们需要用到 Redis 提供的 WATCH 命令, 这个命令需要在开始一个事务之前执行, 它接受任意多个键作为参数, 并对输入的键进行监视:
WATCH key [key …]
如果被监视的键在事务提交之前(也即是 EXEC 命令执行之前), 已经被其他客户端抢先修改了, 那么服务器将拒绝执行客户端提交的事务, 并返回 nil 作为事务的回复:
redis> WATCH msg # 监视键 msg
OK
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXEC # 在这个事务之前,已经有其他客户端对键 msg 进行了修改
(nil)
使用 WATCH 来防止竞争条件(1/3)
回到 ZDECRBY 的例子, 为了确保 ZDECRBY 执行时, ZADD 设置的新分值是正确的, 我们需要在 ZDECRBY 执行一开始时, 就使用 WATCH 监视输入的有序集合,并将修改操作 ZADD 添加到事务里面执行, 以下是修改后的 ZDECRBY 命令的实现:
def ZDECRBY(key, decrment, member):
# 监视输入的有序集合
WATCH key
# 取得元素当前的分值
old_score = ZSCORE key member
# 使用当前分值减去指定的减量,得出新的分值
new_score = old_score - decrment
# 使用事务包裹 ZADD 命令
# 确保 ZADD 命令只会在有序集合没有被修改的情况下执行
MULTI
ZADD key new_score member # 为元素设置新分值,覆盖现有的分值
EXEC
使用 WATCH 来防止竞争条件(2/3)
在这个新的 ZDECRBY 执行时, 有两种情况可能会出现:
• 如果在程序执行期间, 输入的有序集合没有发生任何变化, 那么说明 ZADD 要修改的元素及其分值并没有变化, ZADD 可以正常地更新元素的分 值。
• 如果在程序执行期间, 输入的有序集合发生了变化, 那么程序要修改的元素可能已 经发生了变化, 这时服务器就会阻止事务执行, 使得 ZADD 无法执行, 从而防止竞争条件出现, 也避免了元素的分值被设置为错误的值。
使用 WATCH 来防止竞争条件(3/3)
コマンドの効果WATCH ZADDは、コマンドの故障につながるので、たとえば、次の表には、2つのクライアントを同時にZDECRBYは、クライアントBのコマンドを実行しました:
その他の関連するコマンドと楽観的ロック
redis> WATCH msg name fruits # 监视三个键
OK
redis> UNWATCH # 取消对上面三个键的监视
OK
楽観と悲観的ロックの違い
オプティミスティック・ロックを監視するためのデータをロックされ、複数のクライアントが同時に最初のクライアントが成功するが、クライアントを試した後失敗する試みたデータを、変更しようとすることができます。
悲観的ロックは唯一の他のクライアントが変更する権利を取得しようとするために、終了終了後に改正の下で顧客を待つ必要があります。一方で、クライアントは、データを変更することができます。
Redisのは、頻繁に読み取りと書き込みの操作については、回避クライアントへの楽観的ロックの使用がブロックされます。クライアントの修正データに障害が発生した場合、それは限りすることができますように再試行し、このプロセスは、任意の待ち時間を必要としません。
レビュー
レビュー(1/2)
サービスには、トランザクション内のすべてのコマンドがあるまで、サーバーが待機するユーザーは、すべて一度のコマンドのトランザクション・キューの内部、および他のコマンドによって中断されることはありませんトランザクション要求の実行中に、その後と、トランザクションキューの内側に複数のコマンドを置くことができます完成した後に、クライアントの要求によって送信された他のコマンドに対処するために行く前に。
コマンドはトランザクションで、彼らはすべてのいずれかで実行されたかには実行されません。
レビュー(2/2)
WATCHコマンドキーを監視するためにデータベースを使用することで、操作を実行しながら、競争条件の導入を防止することができます。