从源码层面分析shardedJedis使用虚拟节点如何实现负载均衡

转载:https://www.iteblog.com/archives/2499.html
http://www.zsythink.net/archives/1182

上面两篇文章对一致性哈希算法的原理讲的非常好,但对虚拟节点方面讲的粒度比较粗,下面我结合ShardedJedis的源码,简单说下自己的理解。

当我们的项目启动好之后,根据业务的需要,去操作redis服务器时,需要通过这个命令

ShardedJedis jedis = pool.getResource();在线程池里获取连接;在执行这行命令的过程中,会初始化各个redis实体节点对应的虚拟节点,代码如下:

//List<S> shards:各个redis实体节点

//nodes:存放各个redis实体节点对应的160个虚拟节点;nodes的类型是TreeMap,而TreeMap的底层实现是红黑树,红黑树其实是一棵自平衡的排序二叉树,其执行查找、插入、删除等操作的时间复杂度为O(logn)。看到这里的小伙伴,应该明白为什么使用TreeMap来存储redis实体节点的虚拟节点了吧。

private void initialize(List<S> shards) {
  nodes = new TreeMap<Long, S>();
  //shards.size():redis实体节点的个数
  for (int i = 0; i != shards.size(); ++i) {
    final S shardInfo = shards.get(i);
    if (shardInfo.getName() == null) 
       //每个redis实体节点会产生160个虚拟节点,把这160个虚拟节点存入ThreeMap中,这160个虚拟节点的value都是对应自己的redis实体节点,每个虚拟节点的key在TreeMap中都是唯一的--i的值决定了一个虚拟节点属于哪个redis实体节点,n的值决定了属于哪个redis实体节点的哪个虚拟节点
       for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
          nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo);
       }
    else 
       for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
          nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo);
       }
    resources.put(shardInfo, shardInfo.createResource());
  }
}

有了上面的初始化之后,在操作redis服务器时,首先根据key计算出对应的哈希值,然后再根据这个哈希值在TreeMap中找到离它最近的虚拟节点,再通过虚拟节点找到对应的redis实体节点,这样,就可以操作对应的redis服务器了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值