jedis參數不當引發的問題總結


jedis參數不當引發dubbo服務線程池耗盡異常

現象:一個dubbo服務偶發性的出現個別機器甚至整個集群大量報線程池耗盡的問題。一開始對問題的處理比較粗暴,直接增加了10倍的線程數。但是問題依然偶爾出現,重啟服務就可以暫時解決。后來,發現問題出現頻率有點高,不得不花點時間認真分析了。

實際原因:jedis參數設置不當。實際仔細分析問題后發現每次出現異常最開始都是出現了大量的jedis連接池獲取連接異常:

redis.clients.jedis.exceptions.JedisConnection: Could not get a resource from the pool
...省略其他堆棧信息
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect time out
...省略其他堆棧信息

而這些time out實際是redis節點故障或者網絡抖動引起的。然后看看jedis配置,timeout設置為1000,maxRedirect為2,所以一旦出現redis連接問題,將會導致請求阻塞3s左右。而此服務的qps分攤到單機約為200,阻塞導致了dubbo請求的堆積,進而導致雪崩。處理方法:縮短timeout;去除redirect;根據業務請求考慮增加熔斷組件。

另外通過jstack分析,發現一旦出dubbo線程池耗盡的問題,大量的dubbo處理線程都是處於WAITING(parking)狀態,卡頓在獲取redis連接。分析jedis連接管理相關代碼,jedis連接池使用ReentrantReadWriteLock管理,獲取連接涉及鎖資源的爭奪,而redis server節點無法連接將導致連接池需要嘗試創建新的連接,這個過程會拿走寫鎖,導致其他需要通過讀鎖獲取連接的線程進入等待。所以
也需要根據qps設置maxTotal(這個出現問題的jedis居然設置的連接數為10!)。

spark服務使用jedis訪問redis導致redis服務毛刺

我們所使用的redis cluster集群是個比較大集群,具有數十個節點,集群的讀寫壓力都相當大。其中一部分讀寫操作來自其他同事維護的spark服務,使用jedis訪問。

現象:發現redis的響應時間出現有規律的毛刺
DBA排查發現redis集群的一個節點的負載相對於其他節點比較高,而且出現大量的cluster slots命令。

分析:分析jedis源碼,jedis每次初始化創建連接都是從第一個節點開始嘗試並執行cluster slots命令來獲取整個redis cluster集群的拓撲信息;如果jedis連接池獲取的連接失效,也會執行renewSlotCache,renewClotCache也是會執行cluster slots命令的。
經過推斷及分析,問題出在spark使用jedis的模式上,spark每個批次任務都會創建新的jedis連接,批次處理完成即銷毀掉,所以spark任務執行過程中會反復執行jedis連接池的初始化進而執行cluster slots命令,而從DBA了解到cluster slots命令是比較耗資源的,所以導致了第一個節點負載比較高(jedis連接串固定的,所以第一個節點總是被執行cluster slots命令)。

處理:通過打散jedis連接串上節點的順序來避免總是固定的第一個節點被用來執行cluster slots。此方法實施后,毛刺確實消失了。

疑問:上述方法可以說只是緩解了redis節點負載不均衡的問題,但是由於對spark使用不太了解,所以暫時不知道是否有辦法在多個批次任務間共享jedis連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM