当前位置: 代码网 > it编程>数据库>Redis > Redis在多线程情况下写入失败的问题及解决

Redis在多线程情况下写入失败的问题及解决

2025年11月06日 Redis 我要评论
出现场景同一时间多次调用jedis的set方法,出现:redis.clients.jedis.exceptions.jedisconnectionexception: java.net.sockete

出现场景

同一时间多次调用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位运行会报异常的代码仍然能插入。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com