redis java切片_jedis默认切片实现及对应python版本实现

1.首先它默认的散列算法是MurmurHash 2.0

2. 接下来具体介绍下是怎么实现的.

既然要做水平拆分,那就要有多个redis服务实例,同时要有一定的散列规则,这两个条件不仅仅体现在数据库方面,其他nosql数据库,或者是基于一些搜索引擎要做散列也都是这么做的

2.1我先用自然语言描述一下:它散列的规则是基于你传入的key为基础的,之后通过hash算法,获取到hash值,再从切片的集合中,获取到指定的hash值对应的redis服务器,然后发起请求.而这里比较复杂一些的是,这个集合是怎么生成的以及怎么获取对应hash值的服务的.我们还是让代码来说话吧:

以下是切片集合初始化的代码

Java代码

private void initialize(List shards) {

nodes = new TreeMap();

for (int i = 0; i != shards.size(); ++i) {

final S shardInfo = shards.get(i);

if (shardInfo.getName() == null)

for (int n = 0; n 

nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo);

}

else

for (int n = 0; n 

nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo);

}

resources.put(shardInfo, shardInfo.createResource());

}

}

接下来是,根据key获取切片的代码:

Java代码

public S getShardInfo(byte[] key) {

SortedMap tail = nodes.tailMap(algo.hash(key));

if (tail.size() == 0) {

return nodes.get(nodes.firstKey());

}

return tail.get(tail.firstKey());

}

(1)我们可以看到,切片集合的key生成策略(默认情况下)为("SHARD-"+ i +"-NODE-"+ n)的hash值,其中i,表示切片的编号,n表示0-160的数字,这么做应该是为了散列的更加均匀一些吧(有高手知道的指点一下^^).

(2)而获取切片的部分呢??看起来有点怪怪的,但是我解释下你就很容易懂了,首先key是你传入的key对应的字节数组(按utf-8的编码),首先将这个key进行hash,之后,它配合我们的切片集合中做了一个tailMap的操作,这个操作的作用是获取大于等于指定值的集合(有序),不太懂?看代码吧-_-!!!

Java代码

TreeMap treeMap = new TreeMap();

treeMap.put(1L, "A");

treeMap.put(2L, "B");

treeMap.put(4L, "E");

treeMap.put(3L, "C");

treeMap.put(5L, "F");

System.out.println(treeMap.tailMap(3L));

输出的结果是:{3=C, 4=E, 5=F}

之后将返回结果集合的第一个value

OK,了解了原理,要实现python版本的就不难了,首先我们要安装两个库--pyhash,redis(都支持easy_install)

实现的代码如下:

Python代码

import redis,pyhash;

hasher = pyhash.murmur2_x64_64a();

'''''

this is a shard redis which transplant from jedis(redis java client)

'''

class ShardJedis(object):

def __init__(self,redisServerStrs):

self.nodesMap = {};

for i in range(len(redisServerStrs)):

for n in range(160):

hashKey = "SHARD-" + str(i) + "-NODE-" + str(n);

mapKeyHash = self.getHash(hashKey);

mapKeyHash = self.changePyLong2JavaLong(mapKeyHash);

self.nodesMap[mapKeyHash] = redisServerStrs[i];

'''''

change py long value to java long

'''

def changePyLong2JavaLong(self,pyLong):

if(pyLong > 9223372036854775807):#max long value in java

pyLong = (pyLong+2**63)%2**63 - 2**63;

return pyLong;

'''''

get hash value by murmur2_x64_64a

'''

def getHash(self,key):

hashCode =  hasher(key,seed=0x1234ABCD);

hashCode = self.changePyLong2JavaLong(hashCode);

return hashCode;

def getShardInfo(self,key):

hashKey = self.getHash(key);

nodeKeys = self.nodesMap.keys();

nodeKeys.sort();

resultKey = nodeKeys[0];

print nodeKeys;

for nodeKey in nodeKeys:

if(nodeKey >= hashKey):

resultKey = nodeKey;

break;

return self.nodesMap.get(resultKey);

'''''

get redis client by key

'''

def getRedis(self,key):

redisInfo = self.getShardInfo(key);

redisInfos = redisInfo.split(":");

print redisInfo;

return redis.StrictRedis(host = redisInfos[0],port = int(redisInfo[1]));

以下是测试代码:

Python代码

def testGetRedis(self):

serverInfos = ["localhost:10000", "localhost:10001", "localhost:10002", "localhost:10003"];

sharedJedis = SharedJedis(serverInfos);

redis = sharedJedis.getRedis("aa");

print (redis)

这个是python2的实现版本,功能比较简单,如果有什么问题,望指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值