ShardedJedis的一致性hash

ShardedJedis是redis客户端分片的实现。
但问题是,一个key到底经过了怎样的过程,最终才找到她应该存储的Redis实例呢?
我们先看一下ShardedJedis是如何使用的
   List<JedisShardInfo> shards = Arrays.asList(
            new JedisShardInfo("localhost",6379),
            new JedisShardInfo("localhost",6380));
 
    ShardedJedis sharding = new ShardedJedis(shards);
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        String result = sharding.set("sn" + i, "n" + i);
    }
    long end = System.currentTimeMillis();
ShardedJedis继承自Sharded
而Sharded里面有两属性nodes与resources
public class Sharded<R, S extends ShardInfo<R>> {
  public static final int DEFAULT_WEIGHT = 1;
  private TreeMap<Long, S> nodes;
  private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();
  //....
 }
假如我们的redis集群就像上面的代码,有两个实例,也就是说有两个JedisShardInfo

我们看下图:


ShardedJedis为每个redis实例做出了160个虚拟节点(也可是320或者480,这个权重可以设定,默认是160)
在ShardedJedis初始化的时候,两个redis实例就会初始化320个虚拟节点,分别属于2个JedisShardInfo
他们的关系,存储在nodes这个属性里
同时JedisShardInfo与jedis这个最基础的redis客户端也是一一对应的,他们的关系存储在resources中。
ShardedJedis初始化时,会调用initialize
  private void initialize(List<S> shards) {
    nodes = new TreeMap<Long, S>();


    for (int i = 0; i != shards.size(); ++i) {
      final S shardInfo = shards.get(i);
      if (shardInfo.getName() == null) 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());
    }
  }
大家知道那320个节点的标识符的来源是什么了吧?反正结果就是一个long型的数字么


如果我们get obj1
我们就首先hash obj1 然后在在320个节点里,找到第一个大于hash(obj1)的虚拟节点,如果hash(obj1)大于最大的那个虚拟节点,就把这个obj1放在1号虚拟节点里
然后根据nodes,找到1号虚拟节点对应的JedisShardInfo
再从resources中找到jedis
然后从这个jedis实例中get obj1


为什么要这么做
如果有3个redis实例,直接hash(key)%3 是几,就存放到哪个redis实例里么。
恩,这个想法很只管
问题是,如果我现在要扩容,把3个实例升级成5个实例。
那原先obj1经过hash然后对3求余的结果和对5求余的结果能一样么?


参考资料
https://my.oschina.net/xinxingegeya/blog/391713
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值