当键不存在时,带有When.NotExists的StringSetAsync返回false

问题描述

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

我收到多个尝试使用相同数据更新缓存的请求,因此为了避免多次写入,我在When.NotExists中使用了StringSetAsync。我的理解是,如果密钥已经存在,这将防止发生该集合。我希望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个副本节点和1个主节点。 StackExchange.Redis版本:2.1.58

解决方法

在这些情况下,我通常要做的是暂时将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);
    }
}

请告诉我情况如何!

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...