sql >> Databáze >  >> NoSQL >> Redis

Transakce Redis

Tato stránka poskytuje příklady, jak vytvořit atomické transakce Redis pomocí klienta C# Redis Client ServiceStackRedis Service Stack

Jak vytvořit vlastní atomické operace v Redis #

Jedním z hlavních rysů Redis je schopnost konstruovat vlastní atomové operace. Toho je dosaženo využitím operací Redis MULTI/EXEC/DISCARD.

C# Redis Client služby ServiceStack usnadňuje používání transakcí Redis tím, že poskytuje rozhraní API se silným typem IRedisTransaction (pro řetězce) a IRedisTypedTransaction (pro typy POCO) s pohodlnými metodami, které vám umožní kombinovat jakoukoli operaci IRedisClient v rámci jedné transakce.

Vytvoření transakce se provádí voláním IRedisClient.CreateTransaction() . Odtud zařadíte všechny operace, které chcete být součástí transakce, do fronty pomocí jednoho z IRedisTransaction.QueueCommand() přetížení. Poté můžete provést všechny operace voláním IRedisTransaction.Commit() který odešle příkaz 'EXEC' na server Redis, který provede všechny příkazy ve frontě a zpracuje jejich zpětná volání.

Pokud nevoláte Commit() před koncem bloku using, Dispose() metoda automaticky vyvolá Rollback() to odešle příkaz 'DISCARD', který odstraní aktuální transakci a resetuje připojení klienta Redis zpět do předchozího stavu.

Příklady transakcí Redis #

Níže je jednoduchý příklad ukazující, jak zařadit operace Redis do fronty s a bez zpětného volání.

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'.

Další běžné příklady #

Úplný zdrojový kód a další běžné příklady lze nalézt na stránce běžných testů transakcí.

[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" }));
}

Příklad vše v jednom #

Tento a další příklady lze nalézt v testovací sadě RedisTransactionTests.cs.

Zde jsou příklady all-in-one kombinující různé operace Redis v rámci jedné transakce:

[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" }));
}

  1. Použití COD a CML k vytváření aplikací, které předpovídají skladová data

  2. Hledejte ve více kolekcích v MongoDB

  3. mongoengine - Dotaz na ListField EmbeddedDocumentField

  4. Zahrňte všechna existující pole a přidejte do dokumentu nová pole