redis - 如何在事务中选择性地执行多个更新(不是添加或更新)?

标签 redis stackexchange.redis

我有这个方法:

    public async Task<bool> UpdateIfExist<T>(string cacheKey, IDictionary<string, T> dictionary)
    {
        ITransaction tran = m_connection.GetDatabase().CreateTransaction();

        List<HashEntry> hashEntries = new List<HashEntry>();
        foreach (KeyValuePair<string, T> keyValuePair in dictionary)
        {
            tran.AddCondition(Condition.HashExists(cacheKey, keyValuePair.Key)); // <-- this guy is the problem

            HashEntry hashEntry = GetHashEntry(keyValuePair);
            hashEntries.Add(hashEntry);
        }

        bool committed = await tran.ExecuteAsync();
        if (committed)
        {
            await tran.HashSetAsync(cacheKey, hashEntries.ToArray()));
        }

        return committed;
    }

我的意图是执行纯更新,即更新 dictionary 中的那些键它们也存在于缓存的哈希中。我不想要来自 dictionary 的新键值对插入到缓存的哈希中。但是上面执行的是“全有或全无”更新,也就是说,如果缓存的哈希中缺少字典中的任何一个键,则不会更新任何内容。

例如。假设我的 Redis 缓存中有这个哈希:
myKey foo bar
      goo baz

说,这是我的输入字典:
foo newBar
qoo qux

在我调用我的方法之后..

预期在缓存中:
myKey foo newBar // updated since the field exists in hash
      goo baz

实际:
myKey foo bar   // no change to cache
      goo baz

注:如果 Lua 脚本是我会尝试的唯一方法,但主要是寻找原生 SE.Redis API 方法。

最佳答案

没有本地 redis 方法可以直接执行此操作,因此没有本地 SE-Redis 方法可以直接执行此操作。我们真正想要的是 XX修饰符(我的意思见 SET),但在任何哈希命令中都不存在 - 只有 NX ,这与您想要的相反(NX 是“当不存在时”)。
你可以通过以下方式在没有 Lua 的情况下做到这一点:

  • 检查每个第一个
  • 是否存在
  • 修剪你的更新集
  • 创建仅包含修剪更新的事务,并带有断言检查的条件

  • 但这是很多往返和操作,并且由于数据更改冲突而失败的可能性很高。因此,我会说最好的方法是使用 Lua(对于您希望成为原子的多个相关操作通常是这种情况)。我会在 KEYS 中发送一个值,以及 ARGV 中每个条目的一对值, 并在 Lua 中循环,本质上(完全未经测试 - 甚至可能不是有效的语法)
    for i=1, #ARGV, 2 do
        if redis.call('hexists', KEYS[1], ARGV[i]) == 1then
            redis.call('hset', KEYS[1], ARGV[i], ARGV[i+1])
        end
    end
    

    关于redis - 如何在事务中选择性地执行多个更新(不是添加或更新)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62475567/

    相关文章:

    node.js - 如何在 Node js 聊天应用程序中存储用户的 session 信息?

    caching - Redis StackExchange 存储 500k 类

    c# - 如何通过 StackExchange.Redis 将通用列表添加到 Redis?

    node.js - 如何使 express.js 应用程序在不使用全局的情况下启动时仅连接 redis 1 次?

    node.js - 具有多个 Node.js 主机的 Socket.io,发送给所有客户端

    redis - 删除Redis中的完整文件夹

    c# - 在 StackExchange.Redis 中执行搜索

    azure - Azure 上的 StackExchange.Redis 抛出执行获取超时且无连接可用异常

    Redis key 命名约定?

    Node.js 和 Redis;等待循环完成