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的连接池就挂逼了…

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 妙计想了一千五,明朝依旧卖豆腐[通俗易懂]

    妙计想了一千五,明朝依旧卖豆腐

  • 2.1.1 操作系统之进程的定义、特征、组成、组织

    文章目录1.进程的定义(1)程序的概念(2)进程的概念(2)进程的定义2.进程的特征3.进程的组成4.进程的组织(1)链接方式(2)索引方式1.进程的定义(1)程序的概念(2)进程的概念一个进程可以包含多个程序(2)进程的定义2.进程的特征3.进程的组成而其中最重要的就是进程控制块PCB(ProcessControlBlock)PCB简介:&nbsp…

  • hook技术截取服务器信息,Windows Hook技术

    hook技术截取服务器信息,Windows Hook技术0x01简介有人称它为“钩子”,有人称它为“挂钩”技术。谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼。编程技术的钩子也是在等待捕获系统中的某个消息或者动作。钩子的应用范围非常广泛,比如输入监控、API拦截、消息捕获、改变程序执行流程等方面。杀毒软件会用Hook技术钩住一些API函数,比如钩住注册表读写函数,从而防止病毒对注册表进行写入;病毒使用Hook技术有针对性的捕获键盘的输入,从而…

  • servlet-Filter过滤器

    servlet-Filter过滤器Filter过滤器Filter过滤器是javaweb的三大组件之一,三大组件分别是:Servlet程序,Listener监听器,Filter过滤器Filter过滤器它是javaEE的规范,也就是接口Filter过滤器它的作用是拦截请求,过滤响应拦截请求常见的应用场景:权限检查日记操作事务管理等等原理package at.guitu.com.FIlter;import javax.servlet.FilterChain;import javax.servlet.Filte

  • navicat for mysql注册码激活_navicat注册激活

    navicat for mysql注册码激活_navicat注册激活打开navicatformysql接着打开帮助,选中注册,把下面的复制上去就可以了NAVH-WK6A-DMVK-DKW3 

    2022年10月10日
  • oracle触发器报错语法,oracle触发器

    oracle触发器报错语法,oracle触发器oracle触发器系统默认用户浏览4438oracle触发器怎么写?通过编写数据库触发器,在HR数据库上实现下面的业务规则:1.如果某工种的最低工资进行上涨,则相应的员工的工资应自动增长…通过编写数据库触发器,在HR数据库上实现下面的业务规则:1.如果某工种的最低工资进行上涨,则相应的员工的工资应自动增长推荐于2019-06-0421:52:46创建触发器,给触发器命名,在哪个表上的增删改…

发表回复

您的电子邮箱地址不会被公开。

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