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

时间:2017-09-24 14:59:11

标签: c# timeout stackexchange.redis

我在c#wcf应用程序中使用StackExchange.Redis客户端:我只使用synchronous命令来获取和设置值。问题是我对这个好奇的日志超时了:

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值排队,因为有五个工作线程? 使用netstat,我看到我的应用程序打开了两个到服务器的物理连接。  我确保在我的线程池中有线程可用。  在我的连接设置中,我有一个syncTimeout = 3000 ...  如果我使用redis-cli,我可以在0.64 secondes中得到密钥的值。

有人可以帮忙吗?我能做什么?我是否必须在我的代码中一直使用async或者找到另一个redis客户端库?

3 个答案:

答案 0 :(得分:3)

有一些解决方案。首先,他们在github回购中写了一篇关于他们提出的解决方案的文章,发现here

我发现虽然只是尽可能多地使用异步函数,但只有同步函数会超时。在我看来,超时是他们的一个设计决定,基于他们不想在出现问题时阻止你的代码的想法。我不买,所以我使用的工作是使用异步功能,然后等待任务。因此,我只需db.StringGet("thestring")代替db.StringGetAsync("thestring").Result。也就是说,如果我因任何原因无法使用等待。

您可能希望尽可能多地使用async / await。如果您认为合适,可能还需要使用FireAndForget。您也可以使用ContinueWith。他们谈论这些解决方案here

答案 1 :(得分:2)

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

答案 2 :(得分:1)

修复RedisTimeout异常总是一个挑战,有很多因素导致超时异常,

在您的日志中,您可以看到IOCP线程有1个忙线程,并且您的系统配置为允许8个最小线程。所以情况并非如此,因为1不是> 8

一旦我遇到相同的情况,我通过增加连接字符串中的syncTimeout来修复超时异常,你可以尝试增加它

我也意识到开放连接的数量会影响Redis的性能, 您可以通过运行此命令来查看打开的连接

info clients

在抛出超时异常时我有大约90个打开的连接,我重新启动服务器以重置打开连接并且超时异常消失