Cassandra 源码解析 3: 分布式hashtable(DHT) 和 Locator

来源:互联网 发布:手机防热软件 编辑:程序博客网 时间:2024/03/29 17:00

原理

分布式的存储,使用多台主机作为存储机器。存放/读取[key, value]时,由key选择目标机器,即使用key值将存储的对象分散在不同的机器上. 散列最简单的方法是目标主机数取模, 假如有n台机器,依次编号(0, 1, 2, ..., n - 1),给定key值,生成一个int hash value,用hash value%n,根据模值找到对应的机器. 这种取模hash的问题在于,两个节点时%2, 三个节点时%3,大部分key的hash值随着节点的数目变化而变化.

 

cassandra DHT使用的是consistent hash

目的:在增加节点或者减少节点时,避免因为rehash而引起的server 震荡。

实现:将hash value空间固定并形成环形,0~2^32,每个node(主机)生成一个hash值,将node映射到hash空间。给定的key,计算其hash值,沿着hash顺时针找到第一个(或者N个,如果需要N个备份)node即为目标主机(如下图,借图一幅)

 

consistent_hash

 

添加节点:很显然,添加一个节点,hash空间的一小部分被node重新分割,其他区间不受影响,如下图(再借图一幅),只有node5和node2之间的区间从node2 rehash到node5

 

cassandra 实现

节点的hash值生成

如下所示,在server启动时,将node的Token(注,token即为上文所讲的hash值,可以是Integer类型的Token,也可以是String类型,只要可比较大小进行排序即可作为token)放入全局token表中(TokenMetaData,全部token表存储集群中所有节点对应的token值)。node的token首先检查“LocationInfo” table(column family),如果存在则取出,不存在则随机生成一个新的token并存储。这样每个node的token仅仅生成一次.

 

 

随机Token的生成取决于Partition的方法,默认的Partition是RandomPartitioner(注,随机生成很难保证节点均匀切分hash空间,如果有四个节点,均匀分割,则每个节点分配的hash值为(0/2^32, 2^30,  2 * 2^30, 3 * 2^30),其使用GUID来生成一个BigInteger的Token

 

GuidGenerator

 "s_id(host):System.currentTimeMillis:Random.nextLong"

       ->

  md5.hash

       ->

  hex string 

       ->

  GUID Standard Format

       ->

  md5.hash

       ->

  BigInteger

       -> 

  abs

 

 

 

TokenMetadata中维护了全局(所有节点)的token,当节点leave或者add时,更新这个全局表(下一篇中另作分析)

 

给定key值,寻找目标主机

 

很显然,读写操作都首先要确定目标Server,这里给出weak读(从一个主机读到即可)的Sequence Diagram(再借图一幅)

不见上图,简化版:

CassandraSrever.get_slice 

    -> StorageProxy.readProtocol

          -> StorageService.getNaturalEndpoints

          -> .weakReadLocal

          -> .weakReadRemote

               -> StorageService.findSuitableEndPoint

getNaturalEndpoints

寻找natural end points(目标主机hosts,N = 数据备份数目)分两步

  1. 由Partition生成key的token, RandomPartitioner用MD5 hash生成
  2. 由复制策略来找到目标主机, RackUnawareStrategy使用前文所述的consistent hash方法,将所有node的token排序,然后二分查找给定token在序列中的位置,从该位置起,序列中N个token对应的host即为目标主机。(其他的复制策略主要考虑目标主机的物理位置,try to find the host in different rack or data center)

 

findSuitableEndPoint

返回目标主机中(naturalEndPoint)最近的活着的节点

 

 

Java hit

Google collection (另作介绍)

BiMap<Token, InetAddress> tokenToEndPointMap (Token 和 host 为一对一映射)

AbstractIterator, 从(0, n-1)中的某个位置开始,依次遍历所有的数,n-1的下个数是0(ring),回到位置时(全部遍历一次)结束

 

 

判断两台主机的物理位置

 

寻找接近给定主机的hosts

 

 

关于环形(ring)中两个区间相交的判断

 

 

 

原创粉丝点击