• 关于Memcached一致性hash的探究


    参考文章

    http://blog.chinaunix.net/uid-20498361-id-4303232.html

    http://blog.csdn.net/kongqz/article/details/6695417

    https://my.oschina.net/goal/blog/203593?p=1

    一直认为一致性hash是个很神奇的东东,技术大牛的想法果然不同凡响。

    下列代码并没有作优化处理,仅供参考理解ketama算法,当然也有助于自己理解记忆。如果有错误的地方欢迎指出

     1 function addServer($hostName = array()){
     2     $serverList = array();
     3     foreach($hostName as $val) {
     4         for($i = 0;$i<40;$i++) {
     5             $digest = md5($val.'_'.$i, true);
     6             for ($h = 0; $h < 4; $h++) {
     7                 $hash = (ord($digest[3 + $h * 4]) << 24) | (ord($digest[2 + $h * 4]) << 16)
     8                     | (ord($digest[1 + $h * 4]) << 8) | ord($digest[$h * 4]);
     9                 $serverList[$val][$i*4+$h] = $hash;
    10             }
    11         }
    12     }
    13     return $serverList;
    14 }
    15 //md5的原因是怕用户输入前缀一致  hash一样  分布不均匀??
    16 function getKeyHash($str){
    17     $digest = md5($str,1);
    18     return (ord($digest[3])<<24) | (ord($digest[2])<<16) | (ord($digest[3])<<8) | (ord($digest[0]));
    19 }
    20 
    21 
    22 function findKey($str){
    23     $hostName = array(
    24         '10.100.20.1',
    25         '10.100.20.2',
    26         '10.100.20.3',
    27         '10.100.20.4',
    28         '10.100.20.5',
    29         '10.100.20.6',
    30     );
    31     $serverList  = addServer($hostName);
    32     $serverHash = array();
    33     foreach($serverList as $server){
    34         $serverHash = array_merge($serverHash,$server);
    35     }
    36     sort($serverHash);
    37     $i = 0;
    38     $len = count($serverHash);
    39     $keyHash = getKeyHash($str);
    40     if($keyHash>$serverHash[$len-1]){
    41         foreach($serverList as $key=>$val){
    42             if(in_array($serverHash[$len-1],$val)){
    43                 return $key;
    44             }
    45         }
    46         return 0;
    47     }
    48     while($i<$len){
    49         $curr = $serverHash[$i];
    50         $next = $serverHash[++$i];
    51         if($next>=$keyHash && $keyHash>=$curr){
    52             foreach($serverList as $key=>$val){
    53                 if(in_array($serverHash[$i],$val)){
    54                     return $key;
    55                 }
    56             }
    57         }
    58     }
    59     return false;
    60 }
    61 $result = array();
    62 for($i=1;$i<1000;$i++){
    63     $tmp = findKey('key'.$i);
    64     if(isset($result[$tmp])){
    65         $result[$tmp]++;
    66     }else{
    67         $result[$tmp] = 0;
    68     }
    69 }
    70 print_r($result);

     上面输出结果如下,所以说该算法分布还是相当均匀的。

    [root@silence suanfa]# php ketama.php
    Array
    (
    [10.100.20.6] => 149
    [10.100.20.5] => 162
    [10.100.20.4] => 171
    [10.100.20.2] => 146
    [10.100.20.3] => 196
    [10.100.20.1] => 169
    )

    查找键值所在服务器可以采用下列折半的方式

     1 $rangeArr =
     2 array (
     3     0 => 19,
     4     1 => 99,
     5     2 => 47,
     6     3 => 49,
     7     4 => 74,
     8     5 => 77,
     9     6 => 45,
    10     7 => 95,
    11     8 => 87,
    12     9 => 15,
    13     10 => 14,
    14     11 => 29,
    15     12 => 57,
    16     13 => 3,
    17     14 => 8,
    18     15 => 38,
    19     16 => 28,
    20     17 => 67,
    21     18 => 55,
    22     19 => 43,
    23     20 => 5,
    24     21 => 25,
    25     22 => 48,
    26     23 => 32,
    27     24 => 58,
    28     25 => 90,
    29     26 => 27,
    30     27 => 50,
    31     28 => 6,
    32     29 => 63,
    33     30 => 65,
    34     31 => 81,
    35     32 => 51,
    36     33 => 52,
    37     34 => 66,
    38     35 => 30,
    39     36 => 56,
    40     37 => 54,
    41     38 => 86,
    42     39 => 84,
    43     40 => 83,
    44     41 => 64,
    45     42 => 42,
    46     43 => 26,
    47     44 => 46,
    48     45 => 79,
    49     46 => 69,
    50     47 => 98,
    51     48 => 24,
    52     49 => 37,
    53 );
    54 sort($rangeArr);
    55 function findPoint($num,$rangeArr){
    56     $len = count($rangeArr);
    57     if($num> $rangeArr[$len-1] || $num<$rangeArr[0]){
    58         return $num.'in'.$rangeArr[0];
    59     }
    60     if($len == 2){
    61         return $num.'in'.$rangeArr[1];
    62     }
    63     if($len == 1){
    64         return $num.'in'.$rangeArr[0];
    65     }
    66     $half  =(int)floor($len/2);
    67     if($num<$rangeArr[$half]){
    68         $tmp = array_slice($rangeArr,0,$half+1);
    69         return findPoint($num,$tmp);
    70     }else{
    71         $tmp = array_slice($rangeArr,$half,$len-$half);
    72         return findPoint($num,$tmp);
    73     }
    74 }
    75 echo findPoint(4,$rangeArr);exit;
  • 相关阅读:
    oracle表管理
    Eclipse快捷键指南
    Oracle 命令行导入导出方法
    oracle 查询优化
    Asp.net DataTable添加列和行的方法
    C#实现程序开机启动
    sql分组查询
    10_基址重定向.md
    通用寄存器.md
    小甲鱼.md
  • 原文地址:https://www.cnblogs.com/yuerdongni/p/6249755.html
Copyright © 2020-2023  润新知