4

Booksleeve は CAS 操作 (つまり、Redis WATCHコマンド) をサポートしていますか? たとえば、次のようなものをどのように実装しますか?

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

複数のスレッドが同じオブジェクトを同じデータで変更しようとするときの競合状態を避けるために、これが必要です。

4

1 に答える 1

2

現在の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つの間変更された場合):WATCHEXECGET

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が確実に高速になるように最適化され、他の発信者に影響を与えないようにします。

于 2012-08-01T21:35:56.003 に答える