Denne side giver eksempler på, hvordan man opretter atomiske Redis-transaktioner med ServiceStackRedis Service Stacks C# Redis Client
Sådan opretter du tilpassede atomoperationer i Redis #
Et af hovedtræk ved Redis er evnen til at konstruere brugerdefinerede atomoperationer. Dette opnås ved at bruge Redis's MULTI/EXEC/DISCARD operationer.
ServiceStacks C# Redis-klient gør det nemt at bruge Redis-transaktioner ved at levere en stærkt indtastet IRedisTransaction (for strenge) og IRedisTypedTransaction
Oprettelse af en transaktion udføres ved at kalde IRedisClient.CreateTransaction()
. Derfra 'sætter du i kø' alle operationer, som du ønsker skal være en del af transaktionen ved at bruge en af IRedisTransaction.QueueCommand()
overbelastninger. Derefter kan du udføre alle operationerne ved at kalde IRedisTransaction.Commit()
som vil sende 'EXEC'-kommandoen til Redis-serveren, der udfører alle kommandoerne i kø og behandler deres tilbagekald.
Hvis du ikke kalder Commit()
før slutningen af brugsblokken, Dispose()
metoden vil automatisk kalde Rollback()
som vil sende 'DISCARD'-kommandoen, der fjerner den aktuelle transaktion og nulstiller Redis-klientforbindelsen tilbage til dens tidligere tilstand.
Eksempler på Redis-transaktioner #
Nedenfor er et simpelt eksempel, der viser, hvordan man sætter Redis-operationer i kø med og uden tilbagekald.
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'.
Andre almindelige eksempler #
Den fulde kildekode og andre almindelige eksempler kan findes på siden med almindelige 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" }));
}
Alt-i-et eksempel #
Dette og andre eksempler kan findes ved at se på RedisTransactionTests.cs testsuite.
Her er et alt-i-et-eksempel, der kombinerer forskellige Redis-operationer inden for en enkelt transaktion:
[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" }));
}