10

我正在经历所谓的超时执行 HGET company:product:settings, inst: 1, queue: 8, qu=0, qs=8, qc=0, wr=0/0, in=79/1超时异常.

这很奇怪,因为同一台机器上的同一个 Redis 实例正在存储数据,但它是一个特定的应用程序引发了这个异常。更新:其实同一个应用,上面一行从 Redis 接收数据。问题在于HGET.

此外,我将多路复用器配置的超时时间增加到 6 秒,但没有运气。

此外,我检查了该IDatabase实例是否IsConnected具有true价值。

如何解释这些错误消息以及整个超时背后的问题是什么?

一些背景...

某些代码部分获取数据库(即multiplexer.GetDatabase())时,我已经成功解决了这个问题。

虽然多路复用器有一个实例,AppDomain如 StackExchange.Redis 文档中所述,但许多控制反转组件正在IDatabase它们自己的代码中创建许多实例。也就是说,IDatabase实例不共享。

实际代码正在执行 a ListRightPopLeftPush,然后,它正在实例化控制组件的反转,该组件在组件实例化期间读取哈希键。如果在做所谓的之前实例化整个组件ListRightPopLeftPush,那么整体HashGet不会抛出超时异常。

似乎即使ListRightPopLeftPush从其他实例执行,在执行读取操作时也会IDatabase在下一个实例中产生某种问题。IDatabase

无论如何,我的修复没有回答这个问题。我刚刚添加了更详细的信息,以便我们找到问题所在和自己的解决方案。

更新

Anyway, the above "fix" won't fix further read accesses to Redis. I'm getting the same timeout exception in further calls. And now in paramater found in exception's message says 60/1.

4

1 回答 1

7

Based on a long discussion in chat, and a lot of digging, it looks like in some obscure scenarios the TPL is hijacking the dedicated reader thread when we are doing things like .TrySetResult (which: we do often). This causes an instant deadlock if you make a synchronous call, since it can't possibly process any socket data if it is busy waiting for a task to complete (which would only ever be completed by itself). We do actually have code in place specifically to prevent this, but it looks like the workaround actually forces it to happen in some other scenarios. Which... is horrible. I will see what I can find. But basically, the problem is that currently, in some limited scenarios, TaskCompletionSource.TrySetResult is giving power to the TPL to run synchronous continuations. This includes Task.WhenAny.

于 2014-09-01T11:20:37.843 回答