回顾上一篇文章jedis连接池的构建。

我们来分析ShardedJedisPool的基于客户端分片所可能带来的问题:扩容

ShardedJedisPool的节点扩容 。ShardedJedisPool采用的 是客户端分片模式 ,我们来看一下Sharded的初始化代码,获取节点信息后,其节点按照权重*160个的虚拟节点,将创建的节点放在TreeMap中,value为虚拟节点对应的 正式分片信息。

  1. private void initialize(List<S> shards) {
  2. nodes = new TreeMap<Long, S>();
  3.  
  4. for (int i = 0; i != shards.size(); ++i) {
  5. final S shardInfo = shards.get(i);
  6. if (shardInfo.getName() == null) for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
  7. nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo);
  8. }
  9. else for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
  10. nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo);
  11. }
  12. resources.put(shardInfo, shardInfo.createResource());
  13. }
  14. }

至于为什么创建160个虚拟节点与一致性hash一致,单一的节点很可能导致数据的分布不均。

其后只要遵循同样的 规则,set和get,即可满足相同的 key到相同的 节点上,其代码如下:

其后我们在每次之心jedis操作是先通过可以获取其对应的连接,其代码如下,其依赖于treemapd.tailMap()实现:

  1. public R getShard(String key) {
  2. return resources.get(getShardInfo(key));
  3. }
  4.  
  5. public S getShardInfo(byte[] key) {
  6. SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));
  7. if (tail.isEmpty()) {
  8. return nodes.get(nodes.firstKey());
  9. }
  10. return tail.get(tail.firstKey());
  11. }
  12.  
  13. public S getShardInfo(String key) {
  14. return getShardInfo(SafeEncoder.encode(getKeyTag(key)));
  15. }

回到我们的问题,扩容

虚拟节点的创建将数据均匀的分布到各个节点,但是随着节点的扩容,伴随的问题节点数据的迁移与拷贝,但是什么节点此hash并不是一致性hash,也不是集群模式可以很容易的分配槽点,我们也很难确定什么样的数据需要拷贝到什么新的节点,所以这就给节点扩容带来了困难,扩容必然存在redis数据的丢失,需要有相应的 兼容策略,如数据缺失的兜底策略。

那么我们有什么办法来避免这种情况么 ?

最简单的 就是 prehash,即提前创建相对多的分片,可以将多个集中在单台服务器上,这虽然会带来一定资源的浪费,但是在数据膨胀需要迁移时,我们只需将相应的节点迁移出去,就避免了扩容的 问题。


同时 我们可以注意到 jedis采用的 hash算法是 MurmurHash,这个hash算法是一种非加密型算法,其会比MD5,SHA1,SHA256这些加密算法快很多倍,目前Redis,Memcached,Cassandra,HBase,Lucene都是使用这个hash算法。

jedis的ShardedJedisPool链接池的扩容问题的更多相关文章

  1. jedis 链接池使用(转)

    Jedis作为redis的最佳客户端,它提供了连接池的特性,“连接池”在通常情况下可以有效的提高应用的通信能力,并且这是一种良好的设计模式.Jedis的连接池设计基于apache commons-po ...

  2. Jedis分片Sentinel连接池实验

    Jedis分片Sentinel连接池实验 1.起因 众所周知,Redis官方HA工具Sentinel已经问世很久了,但令人费解的是,Jedis官方却迟迟没有更新它的连接池.到目前Maven库中最新的2 ...

  3. c3p0链接池

    频繁的链接数据库是非常消耗性能的,所以就采用了将一定量的链接保存在一个池中,这个池我们叫做链接池. 详细请看:http://baike.baidu.com/link?url=dlTW-fTS3N_-j ...

  4. ServiceStack.Redis 使用链接池方法

    PooledRedisClientManager 1.RedisManage.cs public static class RedisManager { private static PooledRe ...

  5. 自定义JDBC链接池

    上篇简单介绍了jdbc链接数据库: 本篇就说一下自定义连接池以及增删改查的测试: 自定义连接池 自定义链接池的原因 JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  ...

  6. 数据库链接池c3p0的配置

    由于我看的是远古教程,所以里面各种驱动jar包还有c3p0包都是远古版本,对于最新版本的jdbc已经失去的作用,所以我在这里重写一下! 1.首先是c3p0的位置,package的外面,src的里面 2 ...

  7. c3p0链接池配置使用

    c3p0链接池初步使用:直接上代码 c3p0是开源面粉的连接池,目前使用它的开源项目主要有:Spring,Hibernate等,使用时需要导入相关jar包及配置文件c3p0-config.xml文件 ...

  8. 诡异的druid链接池链接断开故障经验总结

    背景 症状 排查 修复 背景 最近在陆续做机房升级相关工作,配合DBA对产线数据库链接方式做个调整,将原来直接链接读库的地址切换到统一的读负载均衡的代理 haproxy 上,方便机柜和服务器的搬迁. ...

  9. java 代码实现使用Druid 链接池获取数据库链接

    因为原先使用的c3p0链接池,时常出现:APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks,以及出 ...

随机推荐

  1. PLSQL设置显示的字符集及设置

    一.关于PLSQL无法正确显示中文 刚才下载安装了PLSQL Developer 9.0.0.1601 汉化绿色版,执行SQL查询语句,发现显示的数据中只要有中文都会以?表示.经过网上查询得知这是客户 ...

  2. Kafka源码系列之源码分析zookeeper在kafka的作用

    浪尖的kafka源码系列以kafka0.8.2.2源码为例给大家进行讲解的.纯属个人爱好,希望大家对不足之处批评指正. 一,zookeeper在分布式集群的作用 1,数据发布与订阅(配置中心) 发布与 ...

  3. Java对象根据属性排序

    参考:https://blog.csdn.net/wangtaocsdn/article/details/71500500

  4. 十六、myeclipse导入别人项目报错java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServle异常

    问题原因:java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServle异常    我是把别人的源码项目直接导 ...

  5. Linux设备树学习

    1.概念 设备树用于实现驱动代码与设备信息相分离.驱动代码只负责处理驱动的逻辑而关于设备的具体信息存放到设备树文件中.(dts文件,编译后为dtb文件).一个dts文件对应一个ARM的machine, ...

  6. MySQL部分语法

    MySQL 1.先进入到d盘根目录(自己安装MySQL的盘符) cd d:\2.输入net start mysql3.在d盘的根目录下输入mysql -u root -p就可以进入mysql的命令提示 ...

  7. Oracle性能优化小结

    Oracle性能优化小结 原则一.注意where子句中的连接顺序 Oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须卸载其他where条件之前,哪些可以滤掉最大数量记录的 ...

  8. 计算机网络中OSI参考模型

    OSI参考模型 应用层 包括所有能产生网络流量的程序 DNS属于这一层 表示层 用来判断传输之前是否进行加密或压缩处理(二进制.ASCII) 比如出现乱码情况,可能就是表示层的问题 会话层 一个浏览器 ...

  9. docker安装mysql中注意事项

    前言 怎么安装docker和拉mysql镜像不是本文的重点,在这里我主要讲我安装mysql容器的三个注意事项:启动容器, 修改密码,远程登录 run容器 docker run -di --name f ...

  10. Jmeter测试入门——分析HBase访问服务性能瓶颈

    开启HBase服务 新建线程组,设定线程数为10:  设定请求方法和请求参数: 查看请求的返回结果: 查看服务响应的性能分析结果: 可能出问题的地方:Phoenix.数据库连接池(操作Phoenix)