`

根据jedis的murmurhash算法-反推key到指定分片

 
阅读更多

由于项目特殊需求,必须稳定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-2.9.0-API文档-中文版.zip

    赠送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-2.9.0-API文档-中英对照版.zip

    赠送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-jedis-2.7.2

    jedis-jedis-2.7.2缓存技术应用

    jedis-3.6.0-API文档-中英对照版.zip

    赠送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-3.0.0.jar、jedis-3.0.0-javadoc.jar、jedis-3.0.0-sources.jar

    jedis3.0相关jar包,确认可用。包括:jedis-3.0.0.jar、jedis-3.0.0-javadoc.jar、jedis-3.0.0-sources.jar 3个jar包。

    jedis-2.8.0-API文档-中文版.zip

    赠送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-3.6.0-API文档-中文版.zip

    赠送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.8.0-SNAPSHOT.jar

    jedis-2.8.0-SNAPSHOT.jar

    jedis-3.0.1-API文档-中文版.zip

    赠送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-x64-3.2.100.jar(内含commons-pool2-2.4.2.jar)

    jedis-2.4.2.jar与comcommons-pool2-2.0.jar俩个包必须一起导入才能使用

    jedis-3.0.1-API文档-中英对照版.zip

    赠送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.9.0.jar

    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-2.5.1-API文档-中文版.zip

    赠送jar包:jedis-2.5.1.jar; 赠送原API文档:jedis-2.5.1-javadoc.jar; 赠送源代码:jedis-2.5.1-sources.jar; 赠送Maven依赖信息文件:jedis-2.5.1.pom; 包含翻译后的API文档:jedis-2.5.1-javadoc-API文档-...

    jedis.jar包commons-pool.jar包

    jedis2.3---jedis2.9版本jar包,附赠commons-pool.jar包

    jedis-2.5.1-API文档-中英对照版.zip

    赠送jar包:jedis-2.5.1.jar; 赠送原API文档:jedis-2.5.1-javadoc.jar; 赠送源代码:jedis-2.5.1-sources.jar; 赠送Maven依赖信息文件:jedis-2.5.1.pom; 包含翻译后的API文档:jedis-2.5.1-javadoc-API文档-...

    jedis2.9-common-pool

    redis的客户端jar包,和连接池,是redis目前的最新版本

    jedis-2.8.0-sources.jar

    jedis-2.8.0-sources.jar jedis-2.8.0-sources.jar

    Jedis-Common-Pool

    maven库使用最多的2.9.0 Jedis 和对应的common-pool2.jar

    jedis.jar commons-pool2-2.0.jar

    java链接Redis,内含jedis的jar包和commons-pool2-2.0.jar

    jedis-2.8.1-and-spring-4.0.8 下载

    jedis-2.8.1.jar spring-4.0.8.jar 下载, 作用于:在 Web 项目中使用 Redis 快速构建系统缓存(单机版/集群版)时需要!!!

Global site tag (gtag.js) - Google Analytics