sql >> データベース >  >> NoSQL >> Redis

Redisトランザクション

    このページでは、ServiceStackRedis Service StackのC#Redisクライアントを使用してアトミックRedisトランザクションを作成する方法の例を示します

    Redisでカスタムアトミック操作を作成する方法#

    Redisの主な機能の1つは、カスタムアトミック操作を構築する機能です。これは、RedisのMULTI / EXEC/DISCARD操作を利用することで実現されます。

    ServiceStackのC#Redisクライアントでは、強い型のIRedisTransaction(文字列の場合)およびIRedisTypedTransaction (POCOタイプの場合)APIに便利なメソッドを提供して、単一のトランザクション内でIRedisClient操作を組み合わせることができるため、Redisトランザクションを簡単に利用できます。

    トランザクションの作成は、IRedisClient.CreateTransaction()を呼び出すことによって行われます。 。そこから、IRedisTransaction.QueueCommand()のいずれかを使用して、トランザクションの一部にしたいすべての操作を「キューに入れ」ます。 過負荷。その後、IRedisTransaction.Commit()を呼び出すことで、すべての操作を実行できます。 これにより、「EXEC」コマンドがRedisサーバーに送信され、すべてのキューコマンドが実行され、それらのコールバックが処理されます。

    Commit()を呼び出さない場合 usingブロックが終了する前に、Dispose() メソッドは自動的にRollback()を呼び出します これにより、「DISCARD」コマンドが送信され、現在のトランザクションが破棄され、Redisクライアント接続が以前の状態にリセットされます。

    Redisトランザクションの例#

    以下は、コールバックがある場合とない場合のRedis操作をキューに入れる方法を示す簡単な例です。

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

    その他の一般的な例#

    完全なソースコードとその他の一般的な例は、一般的なトランザクションテストページにあります。

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

    オールインワンの例#

    この例やその他の例は、RedisTransactionTests.csテストスイートを確認することで見つけることができます。

    単一のトランザクション内でさまざまなRedis操作を組み合わせたオールインワンの例を次に示します。

    [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. Mongodb C#ドライバーは、配列内の一致するサブドキュメントのみを返します

    2. PythonRedisの相互作用

    3. MongoDBのサブドキュメントのすべてのフィールドを合計するにはどうすればよいですか?

    4. 127.0.0.1:6379へのRedis接続に失敗しました-ECONNREFUSEDに接続します