最近在做的一個項目,用的.net core 2.1,然后緩存用的Redis,緩存相關封裝是同事寫的,用的驅動是StackExchange.Redis
version 2.0.571
,一直聽說這個驅動並發情況下有TimeOut bug,項目開發差不多后,我壓測了一下,簡單的模擬30個用戶持續訪問某一個有用到緩存的查詢接口,結果這么小的壓力下超時異常出現:
Timeout performing GET my_141 (5000ms), inst: 30, qu: 0, qs: 20, in: 20320, serverEndpoint: 172.16.3.119:6379, mgr: 10 of 10 available, clientName: s-119, IOCP: (Busy=0,Free=1000,Min=1,Max=1000), WORKER: (Busy=120,Free=32747,Min=1,Max=32767), v: 2.0.571.20511(Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts))
后面是堆棧信息.....
蛋疼了很久,搜了很多文章,得到以下
解決方案
1、換掉,不用這個驅動( 可以看看.net core redis 驅動推薦,為什么不使用 StackExchange.Redis)
2、redis操作修改為全部異步&& ThreadPool.SetMinThreads(200, 200);
我用的第二種解決了問題,主要換驅動也可能遇到坑;還有時間成本問題;
原因簡析
我們看到以上的異常信息當中有這么一段:
IOCP: (Busy=0,Free=1000,Min=1,Max=1000),
WORKER: (Busy=120,Free=32747,Min=1,Max=32767),
意思是當前繁忙的WORKER 線程有120個,而系統“要由線程池根據需要創建的新的最小工作程序線程數。”,也就是系統創建的工作線程數不足以滿足redis的Get操作的繁忙線程的需求,導致部分Get操作的線程堵塞超時了;
所以我們把“最小線程workerThreads” 修改為200解決問題;
200是我估摸着生產環境服務器設置的,該值設置不合理有可能導致性能問題;