由于项目特殊需求,必须稳定key到特定的分片。因为目前的redis集群是通过客户端来实现的,为此研究了jedis客户端。
具体的原理参照这篇文章http://blog.csdn.net/guanxinquan/article/details/10231899说的挺明白,很感谢这位兄弟。主要涉及到treeMap(红黑树算法)
原理是将每个redis的实例映射到空间的一部分上,即生成n倍的虚拟节点,然后根据hash(key)算法的落点去映射空间,找到最近的节点。
下面是我的Java代码:依赖jedis
package com.hash;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import redis.clients.util.MurmurHash;
/**
* 生成可以稳定到分片的key
* @author sugongp
* @创建时间 2014-4
*/
public class MurmurHashTest {
//jedis中使用的murmur hash
MurmurHash murmur = new MurmurHash();
//每个value都相当于是一个分片编号
TreeMap<Long, Integer> tm = new TreeMap<Long, Integer>();
//计数器
static Map<String,Integer> countMap = new HashMap<String,Integer>();
//可认为是实际的server分片
List<Shard> shards = null;
//实际server端分片数量,根据实际情况而定,这里以server为16个分片为例
int serverShards =16;
//key=shard编号 value 第一个放入shard的key
static Map<Integer, String> keyShardMap = new HashMap<Integer, String>();
void init(){
shards = new ArrayList<Shard>();
Shard sd = null;
for(int i=0; i<serverShards; i++){
sd = new Shard();
/**
* 默认权重是1,如果修改,即使将全部的shard都修改为10
* 那么key映射到的shard也会随之改变
*/
sd.setWeiht(1);
//默认情况下没有名字,name也会影响hash分片的结果
//sd.setName("shard"+i);
shards.add(sd);
}
}
void start(){
int i=0;
//遍历分片
for (Shard sd : shards) {
if(sd.getName() == null) {
//将每个分片,分散的映射到treeMap空间,即在红黑树上生成了大量的虚拟分片
for (int n = 0; n < 160 * sd.getWeiht(); n++) {
tm.put(murmur.hash("SHARD-" + i + "-NODE-" + n), i);
}
}else {
for (int n = 0; n < 160 * sd.getWeiht(); n++) {
tm.put(murmur.hash(sd.getName() + "*" + sd.getWeiht() + n), i);
}
}
i++;
}
}
void test(){
String key;
//随机生成一万个key
for(int i=0; i<10000; i++){
key = "key"+i;
SortedMap<Long, Integer> sm = tm.tailMap(murmur.hash(key));
int d ;
if(sm.isEmpty()) {
//找到了她的shard
d = tm.get(tm.firstKey());
System.out.println(String.format("%s = shard%s" ,key, d));
count(d);
if(!keyShardMap.containsKey(d)){
keyShardMap.put(d, key);
}
continue;
}
d = tm.get(sm.firstKey());
System.out.println(String.format("%s = shard%s" ,key, d));
count(d);
if(!keyShardMap.containsKey(d)){
keyShardMap.put(d, key);
}
}
}
static void count(int d){
if(countMap.containsKey("shard" + d)){
int c = countMap.get("shard" + d);
countMap.put("shard" + d, ++c);
}else {
countMap.put("shard" + d, 1);
}
}
static void print(){
System.out.println(String.format("----------%d个分片中key的数量统计-------------",countMap.size()));
for(String mkey : countMap.keySet()){
System.out.println(String.format("分片%s中key的数量%s个", mkey ,countMap.get(mkey)));
}
System.out.println(String.format("-----------%d个分片中稳定的key统计-------------",keyShardMap.size()));
for(int i : keyShardMap.keySet()){
System.out.println(String.format("第一个稳定到分片%s的key是%s", i, keyShardMap.get(i)));
}
}
public static void main(String[] args) {
MurmurHashTest m = new MurmurHashTest();
m.init();
m.start();
m.test();
print();
}
}
依赖的类
package com.hash;
public class Shard {
String name;
int weiht;
public int getWeiht() {
return weiht;
}
public void setWeiht(int weiht) {
this.weiht = weiht;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
程序执行结果:
----------16个分片中key的数量统计-------------
分片shard13中key的数量606个
分片shard14中key的数量581个
分片shard15中key的数量553个
分片shard0中key的数量645个
分片shard1中key的数量633个
分片shard11中key的数量673个
分片shard4中key的数量559个
分片shard5中key的数量596个
分片shard12中key的数量646个
分片shard2中key的数量712个
分片shard10中key的数量699个
分片shard3中key的数量611个
分片shard8中key的数量591个
分片shard9中key的数量649个
分片shard6中key的数量647个
分片shard7中key的数量599个
-----------16个分片中稳定的key统计-------------
keyShardMap size = 16
第一个稳定到分片0的key是key4
第一个稳定到分片1的key是key0
第一个稳定到分片2的key是key14
第一个稳定到分片3的key是key10
第一个稳定到分片4的key是key5
第一个稳定到分片5的key是key9
第一个稳定到分片6的key是key23
第一个稳定到分片7的key是key32
第一个稳定到分片8的key是key12
第一个稳定到分片9的key是key62
第一个稳定到分片10的key是key3
第一个稳定到分片11的key是key60
第一个稳定到分片12的key是key18
第一个稳定到分片13的key是key51
第一个稳定到分片14的key是key1
第一个稳定到分片15的key是key35
相关推荐
jedis 各个版本 jedis 连接 redis 数据库 jedis-sources 源码
在开发过程中,jedis-3.0.0-javadoc.jar和jedis-3.0.0-sources.jar可以帮助开发者更好地理解和调试代码。API文档提供清晰的接口说明,而源代码则揭示了这些接口背后的实现逻辑。 总结来说,这三个JAR文件构成了一个...
赠送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-x64-3.2.100.jar`和`commons-pool2-2.4.2.jar`都应添加到项目的类路径中,否则可能会出现运行时错误。对于现代Java项目,这通常可以通过Maven或Gradle等构建工具来实现,将...
赠送jar包:jedis-3.6.0.jar; 赠送原API文档:jedis-3.6.0-javadoc.jar; 赠送源代码:jedis-3.6.0-sources.jar; 赠送Maven依赖信息文件:jedis-3.6.0.pom; 包含翻译后的API文档:jedis-3.6.0-javadoc-API文档-...
赠送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信息:...
标题中的"jedis-2.9.0+commons-pool2-2.4.2redis依赖包"指的是一款基于Java实现的Redis客户端库Jedis的2.9.0版本,与Apache Commons Pool 2.4.2版本相结合的依赖包。这个组合主要用于优化Redis连接池管理,提高应用...
jedis2.3---jedis2.9版本jar包,附赠commons-pool.jar包
6. **分片和集群支持**:Jedis支持Redis的分片和集群模式,能够在多个Redis实例之间分散负载。 7. **复制**:Jedis提供了主从复制的配置和操作,便于数据备份和故障恢复。 8. **Pipeline和Transaction**:这两个...
标题中的"jedis-3.2.0.jar + commons-pool2-2.6.2.jar"提到了两个关键的Java库:Jedis和Apache Commons Pool2。Jedis是Java编程语言中广泛使用的Redis客户端,而Apache Commons Pool2则是一个对象池实现,用于有效地...
`jedis-jedis-1.5.0-RC1.zip`是一个包含Jedis 1.5.0 Release Candidate 1版本的压缩包,它可能包含了源代码、文档、示例和测试用例等内容,用于开发者在项目中集成或测试Jedis的最新功能。 Jedis的主要特点包括: 1...
在标题"jedis-jedis-3.6.0-rc1.tar.gz"中,我们可以看出这是Jedis的一个版本,即3.6.0的候选发布1版(Release Candidate 1,简称RC1)。RC1通常是软件正式发布前的最后一个测试版本,意味着它在功能和稳定性上已经...
赠送jar包:jedis-3.6.0.jar; 赠送原API文档:jedis-3.6.0-javadoc.jar; 赠送源代码:jedis-3.6.0-sources.jar; 赠送Maven依赖信息文件:jedis-3.6.0.pom; 包含翻译后的API文档:jedis-3.6.0-javadoc-API文档-...
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-jedis-1.5.0-RC2.tar.gz"指的是Jedis的一个版本,即1.5.0的候选发布版2(Release Candidate 2),通常在正式版本发布之前,RC版本会进行最后的测试和调整,以确保软件的稳定性和兼容性。 在Java应用...
赠送jar包:jedis-3.0.1.jar; 赠送原API文档:jedis-3.0.1-javadoc.jar; 赠送源代码:jedis-3.0.1-sources.jar; 赠送Maven依赖信息文件:jedis-3.0.1.pom; 包含翻译后的API文档:jedis-3.0.1-javadoc-API文档-...
jedis-2.8.0-SNAPSHOT.jar
赠送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-jedis-3.1.0-rc.zip"表明这是一个关于Jedis的3.1.0 release candidate版本的压缩包,通常在正式版本发布前,release candidate(RC)是最后测试阶段的版本,意味着它可能包含了所有计划的新功能和改进,...
标题"jedis-2.9.0.jar和commons-pool2-2.6.0.jar下载(jedis连接redis数据库)"指的是两个Java库的下载信息,用于连接Redis数据库。其中,`jedis-2.9.0.jar`是Jedis的特定版本,它是Java开发人员用来操作Redis的...