Using ServiceStack.Redis, how can I run strongly-typed read-only queries in a transaction

使用redis,servicestack。我怎么能跑的强类型的事务中的只读查询

问题 (Question)

I'm aware that I can increase performance of Redis queries by executing them in a transaction (and even more so in a dedicated pipeline).

The problem is that using the ServiceStack Redis client, I can execute the reads in a transaction but I cannot access the results. This is the code I have below:

User user = null;
Group group = null;

using (IRedisClient cacheClient = new RedisClient())
using (var trans = cacheClient.CreateTransaction())
{
    trans.QueueCommand(x =>
    {
        var userClient = x.As<User>();
        var userHash = userClient.GetHash<string>("Users");
        user = userClient.GetValueFromHash(userHash, userKey);
    });

    trans.QueueCommand(y =>
    {
        // Retrieve modules from cache
        var groupClient = y.As<Group>();
        var groupHash = groupClient.GetHash<string>("Groups");
        group = groupClient.GetValueFromHash(groupHash, groupKey);
    });

    trans.Commit()
}

The problem here is that the user and group variables are not set with the output from the transaction.

So, how can I run a series of different strongly-typed read queries in a transaction (or pipeline) and retrieve the results?

Thanks.

我知道我可以通过执行事务中增加使用查询性能(甚至更多的是在一个专用的管道)。

问题是,使用servicestack redis的客户,我可以执行读取一个事务但我无法访问的结果。这是我下面的代码:

User user = null;
Group group = null;

using (IRedisClient cacheClient = new RedisClient())
using (var trans = cacheClient.CreateTransaction())
{
    trans.QueueCommand(x =>
    {
        var userClient = x.As<User>();
        var userHash = userClient.GetHash<string>("Users");
        user = userClient.GetValueFromHash(userHash, userKey);
    });

    trans.QueueCommand(y =>
    {
        // Retrieve modules from cache
        var groupClient = y.As<Group>();
        var groupHash = groupClient.GetHash<string>("Groups");
        group = groupClient.GetValueFromHash(groupHash, groupKey);
    });

    trans.Commit()
}

这里的问题是:usergroup变量是未设置从交易的输出。

所以,我怎么能运行一系列不同的强类型阅读事务中的查询(或管道)和检索结果?

感谢

最佳答案 (Best Answer)

You cannot do any dependent reads (operations relying on other read values) within a Redis transaction since the way that transactions work in Redis is that they all commands get batched and sent down to redis and executed as a single unit, so there's no opportunity to use a read value from within the same transaction.

The way you can ensure integrity is to use the Redis WATCH command to watch any keys before a transaction and if any of keys changed before the transaction it will throw when the transaction is committed. e.g:

var cacheClient = new RedisClient();

cacheClient.Watch("Users", "Groups");

var userHash = cacheClient.As<User>().GetHash<string>("Users");
var groupHash = cacheClient.As<Group>.GetHash<string>("Groups");

using (var trans = cacheClient.CreateTransaction())
{
    trans.QueueCommand(x =>
    {
        user = x.As<User>().GetValueFromHash(userHash, userKey);
    });

    trans.QueueCommand(y =>
    {
        group = y.As<Group>().GetValueFromHash(groupHash, groupKey);
    });

    trans.Commit();
}

Another alternative to transactions is to use Redis server-side LUA.

你不能做任何相关阅读(依靠其他读值操作)在使用事务的方式在这样的交易是他们所有的命令得到批量发送到Redis作为一个单元执行,所以没有机会使用阅读价值在同一交易。

这样可以确保完整性是使用再看命令看任何键之前的交易,如果任何键改变交易之前,它将在事务提交。例句:

var cacheClient = new RedisClient();

cacheClient.Watch("Users", "Groups");

var userHash = cacheClient.As<User>().GetHash<string>("Users");
var groupHash = cacheClient.As<Group>.GetHash<string>("Groups");

using (var trans = cacheClient.CreateTransaction())
{
    trans.QueueCommand(x =>
    {
        user = x.As<User>().GetValueFromHash(userHash, userKey);
    });

    trans.QueueCommand(y =>
    {
        group = y.As<Group>().GetValueFromHash(groupHash, groupKey);
    });

    trans.Commit();
}

另一项交易是使用使用服务器端的Lua

本文翻译自StackoverFlow,英语好的童鞋可直接参考原文:http://stackoverflow.com/questions/21776021