我将 StackExchange.Redis 与配置为使用 Sentinel 的副本集群(3 个节点)一起使用。
我收到多个尝试使用相同数据更新缓存的请求,因此为了避免多次写入,我使用了 When.NotExists
在 StringSetAsync
.我的理解是,如果 key 已经存在,这将防止设置发生。我在期待 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
即使基于我手动检查 key 是否存在的健全性检查, key 还不存在,也会返回 false。笔记:
我的环境使用 2 个副本节点和一个主节点。
StackExchange.Redis 版本:2.1.58
最佳答案
在这些情况下,我通常做的是暂时增加 expiry (myTimeout)
参数设置为更大的值只是为了从等式中删除超时。接下来的步骤是检查应用程序和数据库服务器之间所有系统边界的访问权限。
另请记住,如果操作因超时或其他类型的失败而引发异常,则取决于您应用 async/await
的方式。堆栈,在某些情况下无法向调用线程抛出超时异常,需要查询Task.Exception
聚合以检查问题的根源。
结果是false
我觉得很可疑( boolean
的默认值)并且您可能在 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);
}
}
请告诉我进展如何!
关于c# - 当键不存在时,带有 When.NotExists 的 StringSetAsync 返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64210570/