如何用StackExchange.Redis解决客户端的Redis超时问题?

问题描述:

我在c#wcf应用程序中使用StackExchange.Redis客户端:我只使用同步命令来获取和设置值。问题是我有这种奇怪的日志超时:如何用StackExchange.Redis解决客户端的Redis超时问题?

Timeout performing EXISTS DataKey:50, 
inst: 1, queue: 1, qu: 0, qs: 1, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, clientName: Machine1, 
serverEndpoint: redis-server:6381, keyHashSlot: 7984, 
IOCP: (Busy=1,Free=799,Min=8,Max=800), 
WORKER: (Busy=5,Free=795,Min=8,Max=800) 
(Please take a look at this article for some common client-side issues that can 
cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts) 

如果我的理解是正确的就意味着我的GET值进行排队,因为有5个工作线程? 使用netstat,我看到我的应用程序正在向服务器打开两个物理连接。 我已经确保在我的线程池中有足够多的线程可用。 在我的连接设置中,我有一个syncTimeout = 3000 ... 如果使用redis-cli,我可以在0.64秒内获得密钥的值。

任何人都可以帮忙吗?我能做什么?我是否必须在代码中使用异步或查找其他redis客户端库?

有几个解决方案。首先,他们在github回购上写了一些关于他们提出的解决方案的文章,找到了here

我发现虽然只是尽可能地使用异步函数,但它只是超时的同步函数。在我看来,超时是基于他们不想在出现问题时阻止您的代码的想法的设计决定。我不买,所以我使用的工作是使用异步功能,然后等待任务。所以,而不是db.StringGet("thestring")我只是做db.StringGetAsync("thestring").Result。也就是说,如果我不能用任何理由等待。

无论如何,您可能想尽可能使用async/await。如果您认为合适,您可能还想使用FireAndForget。您也可以使用ContinueWith。他们谈论那些解决方案here

+0

我已经阅读了这些解决方案,我会尝试使用异步版本,然后等待任务...我们不使用异步代码,因为我的团队不熟悉异步/等待模式,并且由于异步性,我们害​​怕会有很多错误......另一方面,调用异步函数并等待它,对我来说似乎很奇怪:这样做,我会花时间切换另一个线程,等待,然后切换回主线程否? – Dypso

+0

我不确定你的意思,但它与同步函数发生的情况没有什么不同。所发生的只是当前线程一直等待,直到调用完成并继续,但这正是同步调用的情况。 –

从“工作者:(忙= 5,空闲= 795,最小= 8,最大= 800)”,我看到有5个繁忙的工作者线程和最少8个工作线程。我怀疑,如果你看看你收到的整套错误,在某些情况下,你可能会发现Busy大于Min计数。这将表示threadpool throttling。该链接还提供了一些解决方案,以增加Worker和IOCP线程的Min Thread数量。

固定RedisTimeout例外始终是一个挑战,有没有很多因素导致超时异常,

在日志

你可以看到IOCP线程有1忙线程和您的系统被配置为允许8最小线程。所以它不是如此,因为1不>8

一旦我有同样的情况,我通过在连接字符串中增加syncTimeout,你可以尝试固定超时异常增加它

我也意识到,一些打开的连接影响Redis的性能, 你可以看看打开的连接,运行以下命令

info clients 

我在那个超时异常的时间约90打开的连接被抛出,我重新启动服务器重新开放连接和超时例外消失