• 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来执行命令;
  • 相关阅读:
    「manacher」
    「回文自动机」
    「可持久化数据结构(平衡树、trie树、线段树) 」
    「后缀数组」
    「LCT」
    「网络流」
    「一些知识点」
    「至今不会」
    「推荐博客」
    「最小生成树」
  • 原文地址:https://www.cnblogs.com/xiaodf/p/12167268.html
Copyright © 2020-2023  润新知