2017-09-24 504 views
1

我在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客戶端庫?

回答

1

有幾個解決方案。首先,他們在github回購上寫了一些關於他們提出的解決方案的文章,找到了here

我發現雖然只是儘可能地使用異步函數,但它只是超時的同步函數。在我看來,超時是基於他們不想在出現問題時阻止您的代碼的想法的設計決定。我不買,所以我使用的工作是使用異步功能,然後等待任務。所以,而不是db.StringGet("thestring")我只是做db.StringGetAsync("thestring").Result。也就是說,如果我不能用任何理由等待。

無論如何,您可能想盡可能使用async/await。如果您認爲合適,您可能還想使用FireAndForget。您也可以使用ContinueWith。他們談論那些解決方案here

+0

我已經閱讀了這些解決方案,我會嘗試使用異步版本,然後等待任務...我們不使用異步代碼,因爲我的團隊不熟悉異步/等待模式,並且由於異步性,我們害​​怕會有很多錯誤......另一方面,調用異步函數並等待它,對我來說似乎很奇怪:這樣做,我會花時間切換另一個線程,等待,然後切換回主線程否? – Dypso

+0

我不確定你的意思,但它與同步函數發生的情況沒有什麼不同。所發生的只是當前線程一直等待,直到調用完成並繼續,但這正是同步調用的情況。 –

0

從「工作者:(忙= 5,空閒= 795,最小= 8,最大= 800)」,我看到有5個繁忙的工作者線程和最少8個工作線程。我懷疑,如果你看看你收到的整套錯誤,在某些情況下,你可能會發現Busy大於Min計數。這將表示threadpool throttling。該鏈接還提供了一些解決方案,以增加Worker和IOCP線程的Min Thread數量。

0

固定RedisTimeout例外始終是一個挑戰,有沒有很多因素導致超時異常,

在日誌

你可以看到IOCP線程有1忙線程和您的系統被配置爲允許8最小線程。所以它不是如此,因爲1不>8

一旦我有同樣的情況,我通過在連接字符串中增加syncTimeout,你可以嘗試固定超時異常增加它

我也意識到,一些打開的連接影響Redis的性能, 你可以看看打開的連接,運行以下命令

info clients 

我在那個超時異常的時間約90打開的連接被拋出,我重新啓動服務器重新開放連接和超時例外消失