redis集群JedisCluster连接关闭问题

JedisCluster连接关闭问题

set方法为例

//伪代码
JedisCluster jedisCluster = new JedisCluster();
jedisCluster.set("testKey", "testValue");

进入到set方法

  • 类JedisCluster中;

  • 初始化一个JedisClusterCommand对象,调用run方法;

  • 需要实现一个execute方法,通过Jedis调用set方法(这里又回到单节点调用set的方式了);

public String set(final String key, final String value) {
   return new JedisClusterCommand<String>(connectionHandler, maxAttempts) {
     @Override
     public String execute(Jedis connection) {
       return connection.set(key, value);
     }
   }.run(key);
 }

进入到run方法

  • 类JedisClusterCommand中;
public T run(String key) {
   return runWithRetries(JedisClusterCRC16.getSlot(key), this.maxAttempts, false, null);
 }

进入到runWithRetries方法

  • 类JedisClusterCommand中;
  • 只需要关注2个地方即可;
    • return execute(connection),这里调用了之前实现的execute方法;
    • releaseConnection(connection),在finally中释放了连接;
private T runWithRetries(final int slot, int attempts, boolean tryRandomNode, JedisRedirectionException redirect) {
    if (attempts <= 0) {
      throw new JedisClusterMaxAttemptsException("No more cluster attempts left.");
    }

    Jedis connection = null;
    try {
		//此处为空,走else
      if (redirect != null) {
        connection = this.connectionHandler.getConnectionFromNode(redirect.getTargetNode());
        if (redirect instanceof JedisAskDataException) {
          // TODO: Pipeline asking with the original command to make it faster....
          connection.asking();
        }
      } else {
        //此处是false,走else
        if (tryRandomNode) {
          connection = connectionHandler.getConnection();
        } else {
          //这里会从池中获取一个Jedis对象
          connection = connectionHandler.getConnectionFromSlot(slot);
        }
      }
		//这里调用最开始实现的execute方法
      return execute(connection);

    } catch (JedisNoReachableClusterNodeException jnrcne) {
      throw jnrcne;
    } catch (JedisConnectionException jce) {
      // release current connection before recursion
      releaseConnection(connection);
      connection = null;

      if (attempts <= 1) {
        //We need this because if node is not reachable anymore - we need to finally initiate slots
        //renewing, or we can stuck with cluster state without one node in opposite case.
        //But now if maxAttempts = [1 or 2] we will do it too often.
        //TODO make tracking of successful/unsuccessful operations for node - do renewing only
        //if there were no successful responses from this node last few seconds
        this.connectionHandler.renewSlotCache();
      }

      return runWithRetries(slot, attempts - 1, tryRandomNode, redirect);
    } catch (JedisRedirectionException jre) {
      // if MOVED redirection occurred,
      if (jre instanceof JedisMovedDataException) {
        // it rebuilds cluster's slot cache recommended by Redis cluster specification
        this.connectionHandler.renewSlotCache(connection);
      }

      // release current connection before recursion
      releaseConnection(connection);
      connection = null;

      return runWithRetries(slot, attempts - 1, false, jre);
    } finally {
      //此处释放了连接
      releaseConnection(connection);
    }
  }

进入到releaseConnection方法

  • 类JedisClusterCommand中;
  • 实际上是通过Jedis.close()关闭的,和我们用单节点时,是一样的关闭方式;
private void releaseConnection(Jedis connection) {
    if (connection != null) {
      connection.close();
    }
  }

总结

  • 使用JedisCluster时,不需要手动释放连接;
  • 在调用的过程中,会自动释放连接;
  • 实际上是JedisCluster中通过JedisPool获取Jedis来执行命令;

posted on   XIAO的博客  阅读(7639)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

统计

点击右上角即可分享
微信分享提示