前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jedis客户端--分片连接池

Jedis客户端--分片连接池

作者头像
姜同学
发布2022-10-27 16:14:46
5040
发布2022-10-27 16:14:46
举报
文章被收录于专栏:姜同学姜同学

分片连接池

因为每次创建和销毁Jedis的连接非常耗费资源,所以 引入了分片连接池JedisPool,但是JedisPool里只能 存放一个Jedis节点的连接,所以JedisSharded封装 了分片对象,以及ShardedJedisPool.

自己实现的分片对象的封装
代码语言:javascript
复制
/*
 * 自定义封装底层计算分片对象
 */
public class HashJedisPool {

	private List<JedisPool> nodes = new ArrayList();
	int n;
	
	public HashJedisPool(List<String> nodes) {
		this.n = nodes.size();
		for (String node : nodes) {
			String host = node.split(":")[];
			int port = Integer.parseUnsignedInt(node.split(":")[]);
			JedisPool jedisPool = new JedisPool(host,port);
			this.nodes.add(jedisPool);
		}
	}
	
	public void set(String key, String value) {
		int i = (key.hashCode()&Integer.MAX_VALUE)%n;
		JedisPool jedisPool = nodes.get(i);
		Jedis jedis = jedisPool.getResource();
		jedis.set(key,value);
		jedisPool.returnResource(jedis);
	}
	
	public String get(String key) {
		int i = (key.hashCode()&Integer.MAX_VALUE)%n;
		JedisPool jedisPool = nodes.get(i);
		System.out.println(i);
		Jedis jedis = jedisPool.getResource();
		String value = jedis.get(key);
		jedisPool.returnResource(jedis);
		return value;
	}
}

Jedis客户端封装的分片对象

代码语言:javascript
复制
/*
	 * 使用Jedis底层封装好的分片对象
	 */
	@Test
	public void test04() {
		List<JedisShardInfo> infos = new ArrayList<JedisShardInfo>();
		infos.add(new JedisShardInfo("10.42.167.114",));
		infos.add(new JedisShardInfo("10.42.167.114",));
		infos.add(new JedisShardInfo("10.42.167.114",));
		ShardedJedis jedis = new ShardedJedis(infos);
		jedis.set("name","piaolaoshi");
		System.out.println(jedis.get("name"));
	}

Jedis客户端的分片连接池

代码语言:javascript
复制
/*
	 * 分片对象连接池
	 */
	@Test
	public void test05() {
		List<JedisShardInfo> infos = new ArrayList<JedisShardInfo>();
		infos.add(new JedisShardInfo("10.42.167.114",));
		infos.add(new JedisShardInfo("10.42.167.114",));
		infos.add(new JedisShardInfo("10.42.167.114",));
		ShardedJedis jedis = new ShardedJedis(infos);
		
		JedisPoolConfig config = new JedisPoolConfig();
		// 最大连接数200
		config.setMaxTotal();
		// 最大空闲数8
		config.setMaxIdle();
		// 最下空闲数3
		config.setMinIdle();
		
		// 创建分片对象连接池
		ShardedJedisPool shardedJedisPool = new ShardedJedisPool(config, infos);
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		shardedJedis.set("name","jiangmingyang");
		System.out.println(shardedJedis.get("name"));
	}

hash取模与hash一致性算法的对比

代码语言:javascript
复制
根据代码可以看出来我再手动封装分片对象时为了满足
相同key值读取的一致性时使用了hash取模算法
(key.hashcode()&Integer.MAX_VALUE)% 分片个数
但是当我们对分片进行扩容或缩容时,扩容的节点越多
缓存的命中率就会越低,很容易引起缓存的雪崩。所以
Jedis底层在对分片对象进行封装时,使用的是hash
一致性算法。

hash一致性算法

代码语言:javascript
复制
一致性哈希算法将整个哈希值空间映射成一个虚拟的圆环,
整个哈希空间的取值范围为~-。
整个空间按顺时针方向组织。~-在零点中方向重合。
接下来使用如下算法对服务请求进行映射,将服务请求使用哈
希算法算出对应的hash值,然后根据hash值的位置沿圆环顺时针
查找,第一台遇到的服务器就是所对应的处理请求服务器.
当增加一台新的服务器,受影响的数据仅仅是新添加
的服务器到其环空间中前一台的服务器(也就是顺着逆
时针方向遇到的第一台服务器)之间的数据,其他都不
会受到影响。综上所述,一致性哈希算法对于节点的增
减都只需重定位环空间中的一小部分数据,具有较好的
容错性和可扩展性 []  。

简单的来说任何一个对象经过hash一致性算法 计算之后都能被映射在一个0~43亿之间的hash环上,分布在不同区间的key值按照顺时针的方向去匹配最近的redis分片对象。这样在reidis节点进行扩容或缩容时受影响的只是 新节点后面一小段区间的部分,随着节点数量 的增多,受影响的区间会越来越小,这也就意味着缓存的命中率会随这节点的增多而增大,这与hash取模算法刚好相反,所以进行分片对象的封装时,Jedis客户端采用了Hash一致性算法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-06T,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分片连接池
    • 自己实现的分片对象的封装
    • Jedis客户端封装的分片对象
    • Jedis客户端的分片连接池
    • hash取模与hash一致性算法的对比
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档