【问题标题】:StringSetAsync with When.NotExists returns false when key doesn't exist当键不存在时,StringSetAsync with When.NotExists 返回 false
【发布时间】:2021-01-20 10:25:15
【问题描述】:

我正在将 StackExchange.Redis 与配置为使用 Sentinel 的副本集群(3 个节点)一起使用。

我收到多个尝试使用相同数据更新缓存的请求,因此为避免多次写入,我在StringSetAsync 中使用When.NotExists。我的理解是,如果密钥已经存在,这将阻止集合发生。我希望 StringSetAsync 仅在集合实际发生的情况下返回 true。

例子:

var inserted = await connectionMultiplexer.GetDatabase().StringSetAsync("my-key", "my-value", myTimeout, When.NotExists);

if(inserted == false)
{
  var keyExists = await connectionMultiplexer.GetDatabase().KeyExistsAsync("my-key");
  if(keyExists == false)
  {
    // I end up here, which I assumed should not happen. 
  }
}

令我惊讶的是,我看到 StringSetAsync 会返回 false,即使根据我手动检查密钥是否存在的健全性检查,密钥不存在。

注意事项: 我的环境使用 2 个副本节点和一个主节点。 StackExchange.Redis 版本:2.1.58

【问题讨论】:

  • 您在单节点集群中看到相同的行为吗?
  • 你检查redis集群是否启动了?

标签: c# redis stackexchange.redis sentinel redis-sentinel


【解决方案1】:

在这些情况下,我通常会临时将expiry (myTimeout) 参数增加到更大的值,以消除等式中的超时。接下来的步骤是检查应用程序和数据库服务器之间所有系统边界的访问权限。

另外请记住,如果操作由于超时或其他类型的失败而引发异常,取决于您应用async/await 堆栈的方式,在某些情况下无法引发超时异常调用线程,你需要查询Task.Exception聚合来检查问题的根源。

我怀疑结果是falseboolean 的默认值),您可能在Task.Exception 聚合中找到了问题的答案。

想知道可以同步试试:

try
{
    var inserted = connectionMultiplexer.GetDatabase().StringSetAsync("my-key", "my-value", myTimeout, When.NotExists).Result;
    if (inserted == false)
    {
        var keyExists = connectionMultiplexer.GetDatabase().KeyExistsAsync("my-key").Result;
        if (keyExists == false)
        {
            // I end up here, which I assumed should not happen. 
        }
    }
}
catch (AggregateException aex)
{
    foreach (var ex in aex.InnerExceptions)
    {
        Console.WriteLine(ex);
    }
}

请告诉我进展如何!

【讨论】:

    猜你喜欢
    • 2020-12-07
    • 2011-08-12
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    相关资源
    最近更新 更多