文档章节

jedis默认切片实现及对应python版本实现

hongliuliao
 hongliuliao
发布于 2015/04/16 19:00
字数 863
阅读 893
收藏 0

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

想了解这个算法的同学请移步至:http://murmurhash.googlepages.com/

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

 接下来是,根据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的实现版本,功能比较简单,如果有什么问题,望指正!


© 著作权归作者所有

共有 人打赏支持
hongliuliao
粉丝 13
博文 4
码字总数 3703
作品 3
海淀
高级程序员
Python 编码时应该注意的几件事情

在编程过程中,多了解语言周边的一些知识,以及一些技巧,可以让你加速成为一个优秀的程序员。 对于Python程序员,你需要注意一下本文所提到的这些事情。 你也可以看看Zen of Python(Pytho...

justjavac
2012/11/19
0
0
Python 编码时应该注意的几件事情

在编程过程中,多了解语言周边的一些知识,以及一些技巧,可以让你加速成为一个优秀的程序员。 对于Python程序员,你需要注意一下本文所提到的这些事情。 你也可以看看Zen of Python(Pytho...

justjavac
2012/07/27
0
2
学习笔记(10月23日) --(列表、元组、字典)

二周一次课(10月23日) 一、学习python 列表的常用方法 列表是由一序列特定顺序排列的元素组成的。可以把字符串,数字,字典等任何东西加入到列表中,其中的元素之间没有任何关系。列表也是...

wanyang_wanyang
07/03
0
0
python(六)切片,生成式,生成器,迭代

有了前面的基础,其实掌握的比较扎实的话还是能够做出一些简单的东西的,至少解决一些个基本的数学题还是问题不大,比如说实现一个斐波那契数列,杨辉三角什么的。多数情况下使用循环 for .....

Koma
2015/01/20
0
0
Python 数据分析包:pandas 基础

pandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 类似于 Numpy 的核心是 ndarray,pandas 也是围绕着 Series 和 DataFrame 两个核心数据结构展开的 。Series 和 DataFrame ...

lionets
2014/06/10
0
5

没有更多内容

加载失败,请刷新页面

加载更多

下一页

kernel version does not match DSO version

错误信息: kernel version 384.11 does not match DSO version 384.130.0 原因是: cuda driver版本太低,不匹配DSO 简单有效的修复方法,升级nvidia driver, 步骤如下: 1. google seach ...

刘小米
今天
0
0
maven坐标和依赖

一、maven坐标详解 <groupId>com.fgt.club</groupId><artifactId>club-common-service-facade</artifactId><version>3.0.0</version><packaging>jar</packaging> maven的坐标元素说......

老韭菜
今天
1
0
springmvc-servlet.xml配置表功能解释

问:<?xml version="1.0" encoding="UTF-8" ?> 答: xml version="1.0"表示是此xml文件的版本是1.0 encoding="UTF-8"表示此文件的编码方式是UTF-8 问:<!DOCTYPE beans PUBLIC "-//SPRING//......

隐士族隐逸
今天
1
0
基于TP5的微信的公众号获取登录用户信息

之前讲过微信的公众号自动登录的菜单配置,这次记录一下在TP5项目中获取自动登录的用户信息并存到数据库的操作 基本的流程为:微信设置自动登录的菜单—>访问的URL指定的函数里获取用户信息—...

月夜中徘徊
今天
0
0
youTrack

package jetbrains.teamsys.license.runtime; 计算lis package jetbrains.ring.license.reader; 验证lis 安装后先不要生成lis,要把相关文件进行替换 ring-license-checker-1.0.41.jar char......

max佩恩
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部