美文网首页
Jedis断线重连问题

Jedis断线重连问题

作者: 新签名 | 来源:发表于2019-04-16 16:19 被阅读0次

    问题以及现象

    前一阵子发现redis断线重连后,会出现类似如下的错误:

    错误日志

    解决思路

    socket write error之前以为redisTemplate不支持断线重连,也就没当回事。后来请教一个比我更有经验的开发人员,他说jedis支持断线重连,并给我写了一个demo,发现确实会断线重连。

    但项目上跑的服务为什么不会断线重连呢,接连排除了redis版本、redisTemplate版本、redisTemplate使用不当可能引起的问题,最后在redisTemplate中发现以下代码:

    redisTemplate#execute(RedisCallback<T> , boolean , boolean )

    public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
            Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
            Assert.notNull(action, "Callback object must not be null");
    
            RedisConnectionFactory factory = getConnectionFactory();
            RedisConnection conn = null;
            try {
    
                if (enableTransactionSupport) {
                    // only bind resources in case of potential transaction synchronization
                    conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
                } else {
                    conn = RedisConnectionUtils.getConnection(factory);
                }
    
                boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
    
                RedisConnection connToUse = preProcessConnection(conn, existingConnection);
    
                boolean pipelineStatus = connToUse.isPipelined();
                if (pipeline && !pipelineStatus) {
                    connToUse.openPipeline();
                }
    
                RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
                T result = action.doInRedis(connToExpose);
    
                // close pipeline
                if (pipeline && !pipelineStatus) {
                    connToUse.closePipeline();
                }
    
                // TODO: any other connection processing?
                return postProcessResult(result, connToUse, existingConnection);
            } finally {
    
                if (!enableTransactionSupport) {
                    RedisConnectionUtils.releaseConnection(conn, factory);
                }
            }
        }
    

    在最后的finally中发现如果启用事务并不会释放连接,猜想可能是这个原因。果然项目上redisTemplate配置了启用事务这个选项,最后将其去掉,一切回归正常,断线10min后连接仍可以连上。

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="enableTransactionSupport" value="false" />
    </bean>
    

    其他

    • redisTemplate默认不启用事务,如需事务,redisTemplate也提供了手动操作,代码如下:
    RedisTemplate redisTemplate = (RedisTemplate) applicationContext.getBean("redisTemplate");
    
    try{
        redisTemplate.multi();
        ......
        redisTemplate.exec();
    } catch(Exception e){
        redisTemplate.discard();
    }
    
    • jdk8可以考虑用lettuce,支持同步、异步、哨兵、集群、重连机制,底层用的netty。

    相关文章

      网友评论

          本文标题:Jedis断线重连问题

          本文链接:https://www.haomeiwen.com/subject/hdnbwqtx.html