Jedis之ShardedJedis一致性哈希分析
ShardedJedis通过一致性哈希实现的的分布式缓存。主要思路:
redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)
将划分虚拟节点采用TreeMap存储
对每个redis服务器的物理连接采用LinkedHashMap存储
对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点
sharded采用的hash算法:MD5 和 MurmurHash两种;默认采用64位的MurmurHash算法;
源码:
1
2
3
4
5
6
7
8
9
|
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过程中执行的划分虚拟节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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。
1
2
3
4
|
public String set(String key, String value) {
Jedis j = getShard(key);
return j.set(key, value);
} |
看一下代码中大体的逻辑,首先通过key得到ShardInfo,然后通过ShardInfo得到泛型Jedis客户端。
Sharded.java
1
2
3
|
public R getShard( byte [] key) {
return resources.get(getShardInfo(key));
} |
1
2
3
4
5
6
7
|
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
http://my.oschina.net/xinxingegeya/blog/391713
相关推荐
NULL 博文链接:https://snowolf.iteye.com/blog/1667104
NULL 博文链接:https://laintoday.iteye.com/blog/1484520
分析了redis的: 1)java客户端实现源码 2)分析了连接channel,包括命令时客户端和服务端的socket连接;...3)分析了JedisPool连接池配置 4) 分析了命令get set hmset 等逻辑 5)分析了subscribe实现源码
jedis jar包; 版本:2.0 2.1
jedis-2.9.0.jar jedis-2.9.0 jar 包,不包含源码,源码下载地址: http://download.csdn.net/download/tan3739/9993938 测试代码: 导入依赖包: commons-lang-2.5.jar commons-pool2-2.4.2.jar jedis-2.9.0 jar ...
jedis依赖jar包, jedis-2.7.0.jar
jedis相关jar包:commons-pool2-2.3.jar、jedis-2.7.0.jar
jedis-jedis-2.7.2缓存技术应用
Jedis 是 Redis 官方首选的 Java 客户端开发包。 实例方法: ? 1 import redis.clients.jedis.* ? 1 2 3 Jedis jedis = new Jedis("localhost"); jedis.set("foo", "bar"); String value = jedis.get("foo"); 支持...
此资源为Java连接redis的工具jar,Jedis 版本为2.62; 有两个地方需要注意下;jedis 3.0新版本废弃了旧回收资源方法; 废弃方法为:JedisPool.returnResource(Jedis);回收资源 Jedis 3.0版本新回收资源: Jedis.close();...
jedis jedis
jedis源码 (学习jedis必备,附带测试用例)
赠送jar包:jedis-2.9.0.jar; 赠送原API文档:jedis-2.9.0-javadoc.jar; 赠送源代码:jedis-2.9.0-sources.jar; 包含翻译后的API文档:jedis-2.9.0-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId...
jedis-test.7z jedis 简单测试 项目工程 lib 目录包含了依赖包: commons-lang-2.5.jar commons-pool2-2.4.2.jar jedis-2.9.0.jar 另: * Jedis 的源码工程(导入 eclipse 可直接运行): ...
赠送jar包:jedis-2.8.0.jar; 赠送原API文档:jedis-2.8.0-javadoc.jar; 赠送源代码:jedis-2.8.0-sources.jar; 赠送Maven依赖信息文件:jedis-2.8.0.pom; 包含翻译后的API文档:jedis-2.8.0-javadoc-API文档-...
而且发现Jedis和ShardedJedis的方法非常多,覆盖了Redis几乎所有操作,但是没有注释,也没有异常处理,也没有资源回收,所以我就对这两个类进行了再次封装,对照着Redis官网的中文API加上了中文注释,并对接口方法...
使用redisson替代jedis中的的对应方法,以及对应的redis的命令在这三方中对应查询及操作,
1 jedis分片支持数据库 2 动态的将有故障的服务器过滤掉 使用实例 static ShardedJedisPool shareJedisPool; static List<JedisShardInfo> jdsInfoList =new ArrayList(); static{ JedisPoolConfig config =new ...
jedis安装包
要开始使用 Jedis,首先将其作为依赖项添加到您的 Java 项目中。如果使用 Maven: <groupId>redis.clients <artifactId>jedis <version>4.3.0 对于许多应用程序,最好使用连接池。实例化 Jedis 连接池: Jedis...