memcached六:分布式集群算法

memcached本身不是分布式缓存;所谓memcached的分布式缓存,是由用户自己定义的。而且多个memcached节点之间互不通信。

所以,它本身不是分布式的。

 

假设有30万个key,有10台memcached服务器,我们该怎么将这30万个key放在10台服务上?

根据一致性哈希算法,来分配。

一致性哈希算法:将各服务器节点映射到钟表的各个时刻上;把key也映射到钟表的某个时刻上;

该key沿钟表顺时针走,碰到的第1个节点,即为该key的存储点。

各服务器节点和key,都是根据某种相同的规则,转化为整数。

down机示例:

假设有N个节点memcached服务器,当2号节点down,该查找2号节点的key,转到下一节点3号节点上查找;此时只会影响2号节点的key不会被命中,其它节点不受影响;因此整体命中率只减少1/N。

这样做的影响,将减到最少。

但是压力都在3号节点上。进一步优化:将其压力均匀分布到其它节点。

各节点的key不一定负载相近。进一步优化:引入虚拟节点。

虚拟节点:N个真实节点,把每个真实节点映射成M个虚拟节点,再把M*N个虚拟节点散列在圆环上。

各真实节点对应的虚拟节点相互交错分布。

这样,当某真实节点down之后,则把其影响平均分担到其它所有节点上。

 

 

用PHP代码实现基于取余的分布式算法:

# 计算某个键的hash
interface hasher {
   public function _hash($str)  
}
# 计算某个键应该存放的圆盘位置
interface distribution {
  public function lookup($key);
}

class Moder implements haser, distribution {
  protected $_server = [];
  protected $_serverNum = 0
  public function _hash($str) {
     return sprintf('%u', crc32($str));   # 将一个字符串,转化为一个有符号数字  
}
  public function lookup ($key) {
     $index = $this->_hash(&key) % $this->_serverNum;
     return $this->_server[$index];
}
  public function addNode($s) {
     $this->_server[] = $s;
     $this-> _serverNum += 1;
}
  public function delNode($s) {
     foreach($this->_server as $k=$v) {
        if($s == $v) {
            unset($this->_server[$k];
            $this->_serverNum -=1;
}
}  $this->_server = array_merge($this->_server;   #重新排列数组
}
}

 

 

$moder = new moder();
$moder->addNode('a');
$moder->addNode('b');
$moder->addNode('c');
$moder->addNode('d');

for($i=1;$i<=100;$i++) {
  $key = 'key_'.$i;
  echo $key , '--> ' , $moder->lookup($key), "\n";
}

 

 

用PHP实现基于一致性哈希的分布式算法:

# 计算某个键的hash
interface hasher {
   public function _hash($str)
}
# 计算某个键应该存放的圆盘位置
interface distribution {
  public function lookup($key);
}

class Moder implements haser, distribution {
  protected $nodes = [];
  protected $points = [];
  protected $_mul = 64;
  public function _hash($str) {
     return sprintf('%u', crc32($str));   # 将一个字符串,转化为一个有符号数字
}
  public function lookup($key) {
    $position = $this->_hash($key);
   reset($this->points);
$neddle = key($this->points) foreach($this->points as $p=>$v) { if($p >= $postion) { $neddle = $p; break; } return $this->points[$p]; } } public function addNode($node){ $this->nodes[$node] = []; for($i=0;$i<$this->_mul;$i+=1) { $point = $node . '_' . $i; $point = $this->_hash($point); //虚拟节点转化为数字 $this->points[$point] = $node; $this->nodes[$node][] = $point; //虚拟节点与真实节点建立对应关系 } $this->resort(); } protected function resort() { ksort($this->points); } public function delNone($node) { //删除64个虚拟节点 foreach($this->nodes[$node] as $p) { unset($this->points[$p]); } unset($this->nodes[$node]); //删除真实节点 } }

 

图表展示工具:http://www.hcharts.cn/

 

posted on 2018-08-19 16:36  myworldworld  阅读(111)  评论(0)    收藏  举报

导航