redisson连接池配置_redis连接池原理

redisson连接池配置_redis连接池原理文章目录PreCode初始化槽计算无需手工调用close方法PreRedis进阶-Redis集群原理剖析及gossip协议初探集群原理部分简单的提了下Jest是如何实现RedisCluster的,这里我们再来梳理一下Codeimportredis.clients.jedis.HostAndPort;importredis.clients.jedis.JedisCl…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

在这里插入图片描述


Pre

Redis进阶-Redis集群原理剖析及gossip协议初探 集群原理部分 简单的提了下Jest是如何实现Redis Cluster 的 ,这里我们再来梳理一下


Code


import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


public class JedisClusterDemo { 
   
    public static void main(String[] args) throws IOException { 
   

        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);

        Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort("192.168.18.131", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.18.131", 8004));
        jedisClusterNode.add(new HostAndPort("192.168.18.132", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.18.132", 8005));
        jedisClusterNode.add(new HostAndPort("192.168.18.133", 8003));
        jedisClusterNode.add(new HostAndPort("192.168.18.133", 8006));

        JedisCluster jedisCluster = null;
        try { 
   
            //connectionTimeout:指的是连接一个url的连接等待时间
            //soTimeout:指的是连接上一个url,获取response的返回等待时间
            jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "artisan", config);
            System.out.println(jedisCluster.set("clusterArtisan", "artisanValue"));
            System.out.println(jedisCluster.get("clusterArtisan"));
        } catch (Exception e) { 
   
            e.printStackTrace();
        } finally { 
   
            if (jedisCluster != null)
                jedisCluster.close();
        }
    }
}

这里是个简单的demo, 生产中用的话,需要确保jedisCluster是单例的,并且无需手工调用close,不然的话 这个连接池就关闭了,你就无法获取到连接了。


初始化

当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。

我们来看下jedis的实现

 jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "artisan", config);

跟下源码

public JedisClusterConnectionHandler(Set<HostAndPort> nodes,
                                       final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout, String password) { 
   
    this.cache = new JedisClusterInfoCache(poolConfig, connectionTimeout, soTimeout, password);
    initializeSlotsCache(nodes, poolConfig, password);
  }

重点看下 initializeSlotsCache

  private void initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig, String password) { 
   
    for (HostAndPort hostAndPort : startNodes) { 
   
      Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort());
      if (password != null) { 
   
        jedis.auth(password);
      }
      try { 
   
        cache.discoverClusterNodesAndSlots(jedis);
        break;
      } catch (JedisConnectionException e) { 
   
        // try next nodes
      } finally { 
   
        if (jedis != null) { 
   
          jedis.close();
        }
      }
    }
  }

继续 cache.discoverClusterNodesAndSlots(jedis); cache为 JedisClusterInfoCache 对象。

  public void discoverClusterNodesAndSlots(Jedis jedis) { 
   
    w.lock();

    try { 
   
      reset();
      List<Object> slots = jedis.clusterSlots();

      for (Object slotInfoObj : slots) { 
   
        List<Object> slotInfo = (List<Object>) slotInfoObj;

        if (slotInfo.size() <= MASTER_NODE_INDEX) { 
   
          continue;
        }

        List<Integer> slotNums = getAssignedSlotArray(slotInfo);

        // hostInfos
        int size = slotInfo.size();
        for (int i = MASTER_NODE_INDEX; i < size; i++) { 
   
          List<Object> hostInfos = (List<Object>) slotInfo.get(i);
          if (hostInfos.size() <= 0) { 
   
            continue;
          }

          HostAndPort targetNode = generateHostAndPort(hostInfos);
          setupNodeIfNotExist(targetNode);
          if (i == MASTER_NODE_INDEX) { 
   
            assignSlotsToNode(slotNums, targetNode);
          }
        }
      }
    } finally { 
   
      w.unlock();
    }
  }

槽计算

set --------> run  ----> runWithRetries ----> connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key))

CRC16算法,计算key对应的slot connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key))

  public static int getSlot(byte[] key) { 
   
    int s = -1;
    int e = -1;
    boolean sFound = false;
    for (int i = 0; i < key.length; i++) { 
   
      if (key[i] == '{' && !sFound) { 
   
        s = i;
        sFound = true;
      }
      if (key[i] == '}' && sFound) { 
   
        e = i;
        break;
      }
    }
    if (s > -1 && e > -1 && e != s + 1) { 
   
      return getCRC16(key, s + 1, e) & (16384 - 1);
    }
    return getCRC16(key) & (16384 - 1);
  }

无需手工调用close方法

进入到set方法中看下源码

jedisCluster.set("clusterArtisan", "artisanValue")

如下:

  @Override
  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方法

  public T run(String key) { 
   
    if (key == null) { 
   
      throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
    }

    return runWithRetries(SafeEncoder.encode(key), this.maxAttempts, false, false);
  }

继续 runWithRetries , 截取核心逻辑

private T runWithRetries(byte[] key, int attempts, boolean tryRandomNode, boolean asking) { 
   

    Jedis connection = null;
    try { 
   

      if (asking) { 
   
       ......
      } else { 
   
        if (tryRandomNode) { 
   
          connection = connectionHandler.getConnection();
        } else { 
   
          connection = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));
        }
      }

      return execute(connection);
    } finally { 
   
      releaseConnection(connection);
    }
  }

关注点

  • CRC16算法,计算key对应的slot connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key))
  public static int getSlot(byte[] key) { 
   
    int s = -1;
    int e = -1;
    boolean sFound = false;
    for (int i = 0; i < key.length; i++) { 
   
      if (key[i] == '{' && !sFound) { 
   
        s = i;
        sFound = true;
      }
      if (key[i] == '}' && sFound) { 
   
        e = i;
        break;
      }
    }
    if (s > -1 && e > -1 && e != s + 1) { 
   
      return getCRC16(key, s + 1, e) & (16384 - 1);
    }
    return getCRC16(key) & (16384 - 1);
  }

  • getConnectionFromSlot 通过 JedisPool 获取连接

关注下 JedisCluster是如何获取连接的 getConnectionFromSlot 方法

  @Override
  public Jedis getConnectionFromSlot(int slot) { 
   
    JedisPool connectionPool = cache.getSlotPool(slot);
    if (connectionPool != null) { 
   
      // It can't guaranteed to get valid connection because of node
      // assignment
      return connectionPool.getResource();
    } else { 
   
      renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
      connectionPool = cache.getSlotPool(slot);
      if (connectionPool != null) { 
   
        return connectionPool.getResource();
      } else { 
   
        //no choice, fallback to new connection to random node
        return getConnection();
      }
    }
  }

本质上还是通过 JedisPool 来获取一个getResource ,跟我们使用Sentinel 啊 单节点获取方法是一样的


  • finally 语句中的 releaseConnection(connection); ,自动释放连接

看下该方法

  private void releaseConnection(Jedis connection) { 
   
    if (connection != null) { 
   
      connection.close();
    }
  }

说白了,JedisCluster set后会自动释放连接,调用的是jedis 的close方法,所以我们无需手工关闭,否则你这个jedis的连接池就挂逼了…

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/182232.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 舵机抖动的解决方法

    舵机抖动的解决方法现象与原因原文链接:https://blog.csdn.net/zenghuanyu_big/article/details/78515309最近用arduino单片机,机械臂一直在不停的抖动。首先,需要知道舵机的使用方法,简单来说,就是给一定时间的高电平,舵机能转动在一定的角度。其实,你只需给舵机一次能转动在一定角度的高低电平,之后只需保持上电状态,理论上舵机能保持不动。但这样极易出现波动…

    2022年4月30日
    132
  • python怎么读取excel文件_python如何读取文件夹下的所有文件

    python怎么读取excel文件_python如何读取文件夹下的所有文件python读取excel文件如何进行python编程语言拥有着比较强大的excel读写能力,我们只需要安装xlrd,xlwt这两个库就可以了。那么python读取excel文件如何进行,今天就为大家分享下python读取excel文件的具体操作方法,快来了解下吧!1、首先说明我是使用的python3.5,我的office版本是2010,首先打开dos命令窗,安装必须的两个库,命令是:pip3installxlrdPip3installxlwt2、准备好excel,例如我的一个工作文件,我

    2022年10月2日
    1
  • torch torchvision 下载安装与使用

    torch torchvision 下载安装与使用本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末torch和torchvision版本对应关系表torch下载官方下载地址:https://download.pytorch.org/whl/torch_stable.html选择对应版本下载即可torch安装安装命令:pipinstalltorch-1.5.1+cpu-cp36-cp36m-win_amd64.whlpipinstalltorchvision-0.6.0+cpu-cp36-cp

    2022年6月24日
    120
  • webstorm激活码【2021免费激活】[通俗易懂]

    (webstorm激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月26日
    516
  • 我收集了12款自动生成器,无聊人士自娱自乐专用「建议收藏」

    我收集了12款自动生成器,无聊人士自娱自乐专用「建议收藏」整理|Jane出品|AI科技大本营(ID:rgznai100)【导语】此前,AI科技大本营为大家介绍一个火爆文章生成器系统BullshitGenerator,专以生成各种奇葩…

    2022年5月21日
    608
  • java 104规约_电网104规约解包(java)「建议收藏」

    java 104规约_电网104规约解包(java)「建议收藏」【实例简介】电网104规约解包java代码项目是围绕电网规约101规约(DL/T634.5101-2002)和104规约(DL/T634.5104-2009),项目基于Java语言。可以完成规约的内容解析工作和组装工作。可用于实际场景的把发送报文的生成等工作。【文件目录】101_104规约解析├──LICENSE├──README.md├──docs│├──附件1:广东电网配网自动…

    2022年6月20日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号