Booksleeve は CAS 操作 (つまり、Redis WATCHコマンド) をサポートしていますか? たとえば、次のようなものをどのように実装しますか?
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
複数のスレッドが同じオブジェクトを同じデータで変更しようとするときの競合状態を避けるために、これが必要です。
Booksleeve は CAS 操作 (つまり、Redis WATCHコマンド) をサポートしていますか? たとえば、次のようなものをどのように実装しますか?
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
複数のスレッドが同じオブジェクトを同じデータで変更しようとするときの競合状態を避けるために、これが必要です。
現在のnugetでは、そうは思いません。BookSleeveは通常、マルチプレクサとして使用することを目的としているため、「ウォッチ」は使用できなくなります。私はそれを追加することができます、ビットあなたはあなたの操作の期間中(BookSleeve接続ごとに)単一の発信者に使用を制限しなければならないでしょう。
これは変更されました; (例のように)手動で実装したい場合は、INCR
次を使用できます。
// note this could be null if the old key didn't exist
var oldVal = await connection.Strings.GetInt64(db, key);
var newVal = (oldVal ?? 0) + 1;
using (var tran = connection.CreateTransaction())
{
// check hasn't changed (this handles the WATCH, a checked GET,
// and an UNWATCH if necessary); note tat conditions are not sent
// until the Execute is called
tran.AddCondition(Condition.KeyEquals(db, key, oldVal));
// apply changes to perform assuming the conditions succeed
tran.Strings.Set(db, key, newVal); // the SET
// note that Execute includes the MULTI/EXEC, assuming the conditions pass
if (!await tran.Execute()) return null; // aborted; either a pre-condition
// failed, or a WATCH-key was changed
return newVal; // successfully incremented
}
明らかに、それを繰り返し(正常な制限内で)ループで実行して、が原因で中止された場合にWATCH
、最初からやり直すことができるようにすることができます。
これは実際の例とは少し異なります(最初の値GET
と2番目の値の間で値が変更されていないと仮定しますGET
)。
val = GET mykey
newval = (val ?? 0) + 1
WATCH mykey
chk = GET mykey // and verifies chk == val as part of the Execute
MULTI
SET mykey $newval
EXEC
とのEXEC
間で値が変更された場合でも、はキャンセルを報告できることに注意してください。または( 2つの間で変更された場合):WATCH
EXEC
GET
val = GET mykey
newval = (val ?? 0) + 1
WATCH mykey
chk = GET mykey // and verifies chk == val as part of the Execute
UNWATCH
違いはもう1つGET
ですが、マルチプレクサを使用できる唯一の方法です。つまり、Execute
が確実に高速になるように最適化され、他の発信者に影響を与えないようにします。