Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Redis-Transaktionen

Diese Seite enthält Beispiele zum Erstellen von atomaren Redis-Transaktionen mit dem C# Redis-Client von ServiceStackRedis Service Stack

So erstellen Sie benutzerdefinierte atomare Operationen in Redis #

Eines der Hauptmerkmale von Redis ist die Möglichkeit, benutzerdefinierte atomare Operationen zu erstellen. Dies wird durch die Nutzung der MULTI/EXEC/DISCARD-Operationen von Redis erreicht.

Der C# Redis-Client von ServiceStack erleichtert die Verwendung von Redis-Transaktionen, indem er eine stark typisierte IRedisTransaction- (für Zeichenfolgen) und IRedisTypedTransaction-APIs (für POCO-Typen) mit praktischen Methoden bereitstellt, mit denen Sie jede IRedisClient-Operation in einer einzigen Transaktion kombinieren können.

Das Erstellen einer Transaktion erfolgt durch Aufrufen von IRedisClient.CreateTransaction() . Von dort aus stellen Sie alle Operationen, die Sie Teil der Transaktion sein möchten, in die Warteschlange, indem Sie einen der IRedisTransaction.QueueCommand() verwenden Überlastungen. Danach können Sie alle Operationen ausführen, indem Sie IRedisTransaction.Commit() aufrufen Dadurch wird der 'EXEC'-Befehl an den Redis-Server gesendet, der alle Befehle in der Warteschlange ausführt und ihre Rückrufe verarbeitet.

Wenn Sie Commit() nicht aufrufen vor dem Ende des using-Blocks Dispose() -Methode ruft automatisch Rollback() auf Dadurch wird der 'DISCARD'-Befehl gesendet, der die aktuelle Transaktion verwirft und die Redis-Client-Verbindung auf ihren vorherigen Zustand zurücksetzt.

Beispiele für Redis-Transaktionen #

Unten sehen Sie ein einfaches Beispiel, das zeigt, wie Sie Redis-Vorgänge mit und ohne Rückruf in die Warteschlange stellen.

int callbackResult;
using (var trans = redis.CreateTransaction())
{
  trans.QueueCommand(r => r.Increment("key"));  
  trans.QueueCommand(r => r.Increment("key"), i => callbackResult = i);  

  trans.Commit();
}
//The value of "key" is incremented twice. The latest value of which is also stored in 'callbackResult'.

Andere gängige Beispiele #

Den vollständigen Quellcode und andere gängige Beispiele finden Sie auf der Seite für allgemeine Transaktionstests.

[Test]
public void Can_Set_and_Expire_key_in_atomic_transaction()
{
    var oneSec = TimeSpan.FromSeconds(1);

    Assert.That(Redis.GetString("key"), Is.Null);
    using (var trans = Redis.CreateTransaction())                  //Calls 'MULTI'
    {
        trans.QueueCommand(r => r.SetString("key", "a"));      //Queues 'SET key a'
        trans.QueueCommand(r => r.ExpireKeyIn("key", oneSec)); //Queues 'EXPIRE key 1'

        trans.Commit();                                        //Calls 'EXEC'

    }                                                              //Calls 'DISCARD' if 'EXEC' wasn't called

    Assert.That(Redis.GetString("key"), Is.EqualTo("a"));
    Thread.Sleep(TimeSpan.FromSeconds(2));
    Assert.That(Redis.GetString("key"), Is.Null);
}

[Test]
public void Can_Pop_priority_message_from_SortedSet_and_Add_to_workq_in_atomic_transaction()
{
    var messages = new List<string> { "message4", "message3", "message2" };

    Redis.AddToList("workq", "message1");

    var priority = 1;
    messages.ForEach(x => Redis.AddToSortedSet("prioritymsgs", x, priority++));

    var highestPriorityMessage = Redis.PopFromSortedSetItemWithHighestScore("prioritymsgs");

    using (var trans = Redis.CreateTransaction())
    {
        trans.QueueCommand(r => r.RemoveFromSortedSet("prioritymsgs", highestPriorityMessage));
        trans.QueueCommand(r => r.AddToList("workq", highestPriorityMessage));	

        trans.Commit();											
    }

    Assert.That(Redis.GetAllFromList("workq"), 
        Is.EquivalentTo(new List<string> { "message1", "message2" }));
    Assert.That(Redis.GetAllFromSortedSet("prioritymsgs"), 
        Is.EquivalentTo(new List<string> { "message3", "message4" }));
}

All-in-one-Beispiel #

Dieses und andere Beispiele finden Sie in der Testsuite RedisTransactionTests.cs.

Hier ist ein All-in-One-Beispiel, das verschiedene Redis-Operationen innerhalb einer einzigen Transaktion kombiniert:

[Test]
public void Supports_different_operation_types_in_same_transaction()
{
    var incrementResults = new List<int>();
    var collectionCounts = new List<int>();
    var containsItem = false;

    Assert.That(Redis.GetString(Key), Is.Null);
    using (var trans = Redis.CreateTransaction())
    {
        trans.QueueCommand(r => r.Increment(Key), intResult => incrementResults.Add(intResult));
        trans.QueueCommand(r => r.AddToList(ListKey, "listitem1"));
        trans.QueueCommand(r => r.AddToList(ListKey, "listitem2"));
        trans.QueueCommand(r => r.AddToSet(SetKey, "setitem"));
        trans.QueueCommand(r => r.SetContainsValue(SetKey, "setitem"), b => containsItem = b);
        trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem1"));
        trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem2"));
        trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem3"));
        trans.QueueCommand(r => r.GetListCount(ListKey), intResult => collectionCounts.Add(intResult));
        trans.QueueCommand(r => r.GetSetCount(SetKey), intResult => collectionCounts.Add(intResult));
        trans.QueueCommand(r => r.GetSortedSetCount(SortedSetKey), intResult => collectionCounts.Add(intResult));
        trans.QueueCommand(r => r.Increment(Key), intResult => incrementResults.Add(intResult));

        trans.Commit();
    }

    Assert.That(containsItem, Is.True);
    Assert.That(Redis.GetString(Key), Is.EqualTo("2"));
    Assert.That(incrementResults, Is.EquivalentTo(new List<int> { 1, 2 }));
    Assert.That(collectionCounts, Is.EquivalentTo(new List<int> { 2, 1, 3 }));
    Assert.That(Redis.GetAllFromList(ListKey), Is.EquivalentTo(new List<string> { "listitem1", "listitem2" }));
    Assert.That(Redis.GetAllFromSet(SetKey), Is.EquivalentTo(new List<string> { "setitem" }));
    Assert.That(Redis.GetAllFromSortedSet(SortedSetKey), Is.EquivalentTo(new List<string> { "sortedsetitem1", "sortedsetitem2", "sortedsetitem3" }));
}