記錄一次并發(fā)情況下的redis導致服務假死的問題解決
問題描述
最近項目在做性能壓測,框架使用的是 spring boot 2.1.2 + jedis 2.9.1,80個并發(fā)持續(xù)壓測4-5分鐘服務就假死,所有的請求就pending,查看服務日志沒有任何異常,查看其它沒有使用redis的接口都能正常請求。
查找問題思路
查看了一下redis的連接配置,都是正常夠用的
再使用jstack看一下堆棧信息

發(fā)現(xiàn)很多WAITING的線程,再往下看都是redis的getResource方法導致的等待。
查看redis的源碼
Jedis.java@Override public void close() { if (dataSource != null) {//1 if (client.isBroken()) { this.dataSource.returnBrokenResource(this); } else { this.dataSource. returnResource(this); // 2 } this.dataSource = null; // 3 } else { super.close(); } }分析一下這個代碼,
client.isBroken()這里默認值是false,連接釋放的時候先釋放resource 然后再將dataSource置為null,那如果是并發(fā)的情況下話,那有可能再下一個線程進來的時候dataSource已經就是null了,在執(zhí)行第2步的時候dataSource剛好被置為null,那這個時候就無法釋放連接了。這個時候我們再看下獲取連接的方法。JedisSentinelPool.java@Override public Jedis getResource() { while (true) { Jedis jedis = super.getResource(); jedis.setDataSource(this); // <-- This line // get a reference because it can change concurrently final HostAndPort master = currentHostMaster; final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient() .getPort()); if (master.equals(connection)) { // connected to the correct master return jedis; } else { returnBrokenResource(jedis); } } }這里
jedis.setDataSource(this);設置的則為null。
問題解決方案
我查看了一下jedis的github,在issue上有找到有人曾經提出過這樣的問題,https://github.com/redis/jedis/issues/1920 ,給出的解決方案是升級jedis的jar包到2.10.2版本以上,換成高版本的以后問題果然就解決了。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.10.2</version>
</dependency>這里要注意一下的是jedis的版本跟spring-data-redis的版本是有一個對應關系的。
spring-data-redis 2.1.x 對應的jedis版本是2.x.x 版本
spring-data-redis 2.2.x 對應的jedis 版本就是3.x版本了
分析升級版本以后的改動
還是看那兩個類,看看新版本做了什么改動
public void close() {
if (this.dataSource != null) {
Pool<Jedis> pool = this.dataSource;
this.dataSource = null;
if (this.client.isBroken()) {
pool.returnBrokenResource(this);
} else {
pool.returnResource(this);
}
} else {
super.close();
}
}這里很明顯的處理方式就是講dataSource復制給pool,然后用pool去釋放資源,這個時候設置dataSource與這個就沒有關系了,就不存在釋放資源釋放不了的情況了。
到此這篇關于記錄一次并發(fā)情況下的redis導致服務假死的問題解決的文章就介紹到這了,更多相關redis導致服務假死內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Redis如何使用樂觀鎖(CAS)保證數(shù)據(jù)一致性
本文主要介紹了Redis如何使用樂觀鎖(CAS)保證數(shù)據(jù)一致性,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Redis shake實現(xiàn)可視化監(jiān)控的示例代碼
Redis可視化監(jiān)控是通過監(jiān)控Redis服務器的各項指標和狀態(tài),并將其以可視化的方式展示給用戶,本文給大家介紹了Redis shake實現(xiàn)可視化監(jiān)控,并通過代碼示例講解的非常詳細,需要的朋友可以參考下2024-03-03
基于Redis實現(xiàn)每日登錄失敗次數(shù)限制
這篇文章主要介紹了通過redis實現(xiàn)每日登錄失敗次數(shù)限制的問題,通過redis記錄登錄失敗的次數(shù),以用戶的username為key,本文給出了實例代碼,需要的朋友可以參考下2019-08-08

