出现场景
同一时间多次调用jedis的set方法,出现:
redis.clients.jedis.exceptions.jedisconnectionexception: java.net.socketexception: socket is not connected: socket write error
at redis.clients.jedis.protocol.sendcommand(protocol.java:98)
at redis.clients.jedis.protocol.sendcommand(protocol.java:78)
at redis.clients.jedis.connection.sendcommand(connection.java:101)
at redis.clients.jedis.binaryclient.set(binaryclient.java:99)
at redis.clients.jedis.client.set(client.java:29)
at redis.clients.jedis.jedis.set(jedis.java:72)
at com.castle.cache.jedisutils.setsingle(jedisutils.java:21)
at com.castle.cache.jedisutils$1.run(jedisutils.java:36)
at java.util.concurrent.threadpoolexecutor.runworker(unknown source)
at java.util.concurrent.threadpoolexecutor$worker.run(unknown source)
at java.lang.thread.run(unknown source)
caused by: java.net.socketexception: socket is not connected: socket write error
at java.net.socketoutputstream.socketwrite0(native method)
at java.net.socketoutputstream.socketwrite(unknown source)
at java.net.socketoutputstream.write(unknown source)
at redis.clients.util.redisoutputstream.flushbuffer(redisoutputstream.java:31)
at redis.clients.util.redisoutputstream.write(redisoutputstream.java:38)
at redis.clients.jedis.protocol.sendcommand(protocol.java:84)
... 10 more
问题重现代码
环境:jre7 32bit
jedis:
<dependency> <groupid>redis.clients</groupid> <artifactid>jedis</artifactid> <version>2.7.3</version> <type>jar</type> <scope>compile</scope> </dependency>
private static jedis jedis = new jedis("localhost",6379);;
// 过期时间/生存时间
// protected static int expiretime = 60 * 60 *24;
public static jedis getinstance(){
return jedis;
}
public static void setsingle(string key,string value){
jedis.set(key, value);
// jedis.expire(key, expiretime);
}
public static string getsingle(string key){
// jedis.expire(key, expiretime);
return jedis.get(key);
}
public static void main(string[] args) {
executorservice cachedthreadpool = executors.newcachedthreadpool();
for (int i = 1; i <= 1000; i++) {
final string ii = "test:test_num-"+i;
cachedthreadpool.execute(new thread(){
public void run(){
setsingle(ii, ii);
}
});
}
}运行代码然后就出现:

原因分析
猜测多线程获取连接,同一时间获取同一个连接导致卡死
解决方案
拟用连接池:
private static jedispool pool;
/**
* 初始化redis连接池
*/
private static void initializepool() {
//redisurl 与 redisport 的配置文件
jedispoolconfig config = new jedispoolconfig();
//设置最大连接数(100个足够用了,没必要设置太大)
config.setmaxtotal(20);
//最大空闲连接数
config.setmaxidle(5);
//获取jedis连接的最大等待时间(50秒)
config.setmaxwaitmillis(50 * 1000);
//在获取jedis连接时,自动检验连接是否可用
config.settestonborrow(true);
//在将连接放回池中前,自动检验连接是否有效
config.settestonreturn(true);
//自动测试池中的空闲连接是否都是可用连接
config.settestwhileidle(true);
//创建连接池
pool = new jedispool(config, "localhost",6379);
}
/**
* 多线程环境同步初始化(保证项目中有且仅有一个连接池)
*/
private static synchronized void poolinit() {
if (null == pool) {
initializepool();
}
}
public static jedis getjedis() {
if (pool == null) {
poolinit();
}
//如果没有以下代码会造成初始化的jedis拿不到 jedis对象
jedis jedis = null;
try {
if (pool != null) {
jedis = pool.getresource();
}
}
catch (exception e) {
e.printstacktrace();
}
return jedis;
}
/**
* 释放jedis资源
*
* @param jedis
*/
public static void returnresource(jedis jedis) {
if (null != jedis) {
pool.returnresourceobject(jedis);
}
}
//private static jedis jedis = new jedis("localhost",6379);;
// public static jedis getinstance(){
// return jedis;
// }
// 过期时间/生存时间
protected static int expiretime = 60 * 60 *24;
public static void put(string key,string value){
// jedis.set(key, value);
jedis jedis = getjedis();
while (true) {
if (null != jedis) {
break;
} else {
jedis = getjedis();
}
}
jedis.set(key, value);
returnresource(jedis);
// jedis.expire(key, expiretime);
}
public static string get(string key){
// jedis.expire(key, expiretime);
// return jedis.get(key);
jedis jedis = getjedis();
while (true) {
if (null != jedis) {
break;
} else {
jedis = getjedis();
}
}
string value = jedis.get(key);
returnresource(jedis);
return value;
}
public static set<string> keys(string keymatch){
// jedis.expire(key, expiretime);
//
jedis jedis = getjedis();
while (true) {
if (null != jedis) {
break;
} else {
jedis = getjedis();
}
}
set<string> res = jedis.keys(keymatch);
returnresource(jedis);
return res;
}
public static void remove(string key){
// jedis.del(key);
jedis jedis = getjedis();
while (true) {
if (null != jedis) {
break;
} else {
jedis = getjedis();
}
}
jedis.del(key);
returnresource(jedis);
}测试代码:
public static void main(string[] args) {
executorservice cachedthreadpool = executors.newcachedthreadpool();
for (int i = 1; i <= 1000; i++) {
final string ii = "test:test_num-"+i;
cachedthreadpool.execute(new thread(){
public void run(){
put(ii, ii);
}
});
}
}插入成功:

这是在jdk7 32位的情况下,我在jdk8 64位运行会报异常的代码仍然能插入。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论