Trang này cung cấp các ví dụ về cách tạo các giao dịch Redis nguyên tử với ServiceStackRedis Service Stack's C # Redis Client
Cách tạo các hoạt động nguyên tử tùy chỉnh trong Redis #
Một trong những tính năng chính của Redis là khả năng xây dựng các hoạt động nguyên tử tùy chỉnh. Điều này đạt được bằng cách sử dụng các hoạt động MULTI / EXEC / DISCARD của Redis.
C # Redis Client của ServiceStack giúp bạn dễ dàng sử dụng các giao dịch Redis bằng cách cung cấp một API IRedisTransaction được đánh máy mạnh (cho chuỗi) và IRedisTypedTransaction
Việc tạo giao dịch được thực hiện bằng cách gọi IRedisClient.CreateTransaction()
. Từ đó, bạn 'Xếp hàng' tất cả các thao tác bạn muốn trở thành một phần của giao dịch bằng cách sử dụng một trong các IRedisTransaction.QueueCommand()
quá tải. Sau đó, bạn có thể thực hiện tất cả các thao tác bằng cách gọi IRedisTransaction.Commit()
sẽ gửi lệnh 'EXEC' đến máy chủ Redis thực thi tất cả các lệnh Đã xếp hàng đợi và xử lý lệnh gọi lại của chúng.
Nếu bạn không gọi Commit()
trước khi kết thúc khối sử dụng, Dispose()
phương thức sẽ tự động gọi Rollback()
điều đó sẽ gửi lệnh 'DISCARD' hủy giao dịch hiện tại và đặt lại kết nối máy khách Redis trở lại trạng thái trước đó.
Redis Giao dịch Ví dụ #
Dưới đây là một ví dụ đơn giản cho thấy cách sắp xếp các hoạt động của Redis có và không có lệnh gọi lại.
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'.
Các ví dụ phổ biến khác #
Bạn có thể tìm thấy mã nguồn đầy đủ và các ví dụ phổ biến khác trên trang kiểm tra giao dịch phổ biến.
[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" }));
}
Ví dụ tất cả trong một #
Bạn có thể tìm thấy điều này và các ví dụ khác bằng cách xem bộ thử nghiệm RedisTransactionTests.cs.
Dưới đây là một ví dụ tất cả trong một kết hợp các hoạt động Redis khác nhau trong một giao dịch duy nhất:
[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" }));
}