文档章节

Jedis之ShardedJedis一致性哈希分析

秋风醉了
 秋风醉了
发布于 2015/03/25 18:41
字数 602
阅读 5897
收藏 7

Jedis之ShardedJedis一致性哈希分析

ShardedJedis通过一致性哈希实现的的分布式缓存。主要思路:

  • redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)

  • 将划分虚拟节点采用TreeMap存储

  • 对每个redis服务器的物理连接采用LinkedHashMap存储

  • 对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点

  • sharded采用的hash算法:MD5 和 MurmurHash两种;默认采用64位的MurmurHash算法;

源码:

public class Sharded<R, S extends ShardInfo<R>> {

  public static final int DEFAULT_WEIGHT = 1;
  private TreeMap<Long, S> nodes;
  private final Hashing algo;
  private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();
  ........................
  ........................
}

这个类维护了一致性哈希后的物理机器和虚拟节点的映射关系,看一张图你会秒懂,

 

TreeMap<Long, S> nodes,存储的是虚拟节点和key的映射关系。有了虚拟节点,还要找到真正的存储位置。

Map<ShardInfo<R>, R> resources维护了虚拟节点和真正的存储位置的映射关系。

也是说,hash(key) -> virtual node -> real node; 

jedis划分虚拟节点的逻辑代码,在Sharded类中,方法是initialize。这是在实例化对象池ShardedJedisPool过程中执行的划分虚拟节点。 

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());
    }
}

以上代码就是划分虚拟节点的逻辑。

 

那么ShardedJedis客户端是如何执行set key value呢?

通过这里可以看出还是通过Jedis客户端执行的set key value。

public String set(String key, String value) {
  Jedis j = getShard(key);
  return j.set(key, value);
}

看一下代码中大体的逻辑,首先通过key得到ShardInfo,然后通过ShardInfo得到泛型Jedis客户端。

Sharded.java

public R getShard(byte[] key) {
  return resources.get(getShardInfo(key));
}
public S getShardInfo(byte[] key) {
  SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));
  if (tail.isEmpty()) {
    return nodes.get(nodes.firstKey());
  }
  return tail.get(tail.firstKey());
}

来看一下ShardedJedis的继承关系吧,

还有ShardInfo和JedisShardInfo继承关系,

参考:http://yychao.iteye.com/blog/1751583

=================END=================

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 244
博文 546
码字总数 414070
作品 0
朝阳
程序员
私信 提问
Jedis 与 ShardedJedis 设计

Jedis设计 Jedis作为推荐的java语言redis客户端,其抽象封装为三部分: 对象池设计:Pool,JedisPool,GenericObjectPool,BasePoolableObjectFactory,JedisFactory 面向用户的redis操作封装...

tantexian
2016/06/07
49
0
shardedJedis无法设置DB的问题

本人一直从事java研发,java版本的redis客户端通常使用的是jedis。在之前生产开发过程中,redis主要以单机形式或者主备读写分离形式使用,并未涉及到分片等高级功能。最近,由于业务量激增,...

萧十一郎君
2016/10/21
318
0
征服 Redis + Jedis

用Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET 等。基于这些限制,有必要考虑Redis! 相关链接: 征服 Redis 征服 Redis + Jedis 征服 Redi...

凯文加内特
2015/03/18
0
0
redis缓存Hash操作的在主数据中的应用

Redis hash是一个string类型的field和value的映射表.一个key可对应多个field,一个field对应一个value 1、如何主数据在redis缓存中实现初始化? 1)加载主数据,建立MasterMain.java package c...

0了凡0
2016/04/28
56
0
哈希一致性、哈希取余、自定义轮询分片的比较

一、自定义轮询分片 按照上图所示,自己写一段逻辑,根据客户端请求循环写入不同Redis服务器 优点: 理解简单 数据分布平均 缺点: 如果增加redis内存数据库服务器,需要改代码,需要发布代码...

特拉仔
2018/04/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Android Messenger进程间客户端向服务端传递数据

Messenger:客户端向服务端传递数据 1.Service: public class MessengerService extends Service { private Messenger messenger = new Messenger(new Handler() { public void handleMess......

Coding缘
4分钟前
0
0
Pod在多可用区worker节点上的高可用部署

一、 需求分析 当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用...

zhaowei121
22分钟前
0
0
oracle XTTS介绍

一、什么是XTTS 首先什么是XTTS。XTTS其实是从TTS来的,TTS其实也是传输数据的一种手段,传输数据的时候可能用过EXP的方式,再往后可能用数据泵导入导出一些数据,或者去做备份然后再恢复。其...

突突突酱
22分钟前
0
0
[缺陷分析]半同步下多从库复制异常

引 言 本文是由爱可生研发团队出品的「图解MySQL」系列文章,不定期更新,但篇篇精品。 爱可生开源社区持续运营维护的小目标: 每周至少推送一篇高质量技术文章 每月研发团队发布开源组件新版...

爱可生
23分钟前
0
0
二维数组序号重置

public static function unique_arr($array2D,$stkeep=false,$ndformat=true){ // 判断是否保留一级数组键 (一级数组键可以为非数字) if($stkeep) $stArr = array_keys($array2D); // 判断是......

dragon_tech
25分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部