Memcached 笔记与总结(7)增加虚拟节点
仅仅把 Memcached 服务器集群地址通过一致性哈希转映射在圆环上,可能会出现数据不能均匀地分配给各台 Memcached 服务器。
解决方案是引入虚拟节点,就是把每个映射在圆环上的服务器地址(物理节点)转变成更多的(注:关于虚拟节点的个数参考①)虚拟节点。
修改 Memcached 笔记与总结(6)PHP 实现 Memcached 的一致性哈希分布算法 中的代码:
类 consistentHash 增加私有的成员属性:$position,以键值形式保存所有虚拟节点的哈希值(键)和对应的服务器(值)的一维数组
结构如下:
array(
1589449412 => '192.168.1.1'
2566189294 => '192.168.1.1'
4025729144 => '192.168.1.2'
2135743977 => '192.168.1.2'
139193727 => '192.168.1.3'
1522140696 => '192.168.1.3'
)
私有成员属性 $serverList 修改为 以二维数组保存服务器列表和每一个服务器下虚拟节点的哈希值,结构如下:
array(
'192.168.1.1' => array(
0 => 1589449412,
1 => 700064338
),
'192.168.1.2' => array(
0 => 1559997597,
1 => 737975307
)
)
私有成员属性 isSorted 修改为 记录虚拟节点哈希值列表是否已经排列过序
addServer 方法的实现:
public function addServer($server, $nodesNum = 25){ if (isset($this->serverList[$server])) {
return;
} //增加虚拟节点,默认每个物理节点变成25个虚拟节点
for($i = 0; $i < $nodesNum; $i++){
$hash = $this->_hash($server.'-'.$i);//计算虚拟节点的Hash值
$this->position[$hash] = $server;
$this->serverList[$server][] = $hash;
} //此时虚拟节点表发生了变化,因此标识为FALSE
$this->isSorted = FALSE;
return TRUE;
}
removeServer 方法的实现:
public function removeServer($server){ if (!isset($this->serverList[$server])) {
return;
} //循环position数组,如果要删除的服务器的值等于position数组某个元素的值,则删除该元素
foreach($this->position as $k=>$v){
if($server == $v){
unset($this->position[$k]);
}
} unset($this->serverList[$server]); $this->isSorted = FALSE;
return TRUE;
}
lookup 方法的实现:
public function lookup($key){
//计算出服务器的Hash值
$hash = $this->_hash($key); //判断服务器列表是否排过序
if (!$this->isSorted) {
//倒序排列(把虚拟节点列表转换成逆时针圆环)
krsort($this->position, SORT_NUMERIC);
$this->isSorted = TRUE;
} //遍历虚拟节点列表,找到合适的服务器并返回
foreach($this->position as $server_hash=> $server){
if ($hash >= $server_hash) return $server;
}
return end($this->position);
}
完整代码:
<?php
//把字符串转换为整数
interface hash{
public function _hash($str);
} interface distribute{
//在当前的服务器列表中找到合适的服务器存放数据
public function lookup($key); //添加一个服务器到服务器列表中
public function addServer($server); //从服务器列表中删除一个服务器
public function removeServer($server);
} class consistentHash implements hash, distribute{ private $serverList = array();//以二维数组保存服务器列表和每一个服务器下虚拟节点的哈希值
private $position = array();//以键值形式保存所有虚拟节点的哈希值(键)和对应的服务器(值)的一维数组
private $isSorted = FALSE; //记录虚拟节点哈希值列表是否已经排列过序 public function _hash($str){
return sprintf('%u', crc32($str));//把字符串转成32为无符号整数
} public function lookup($key){
//计算出服务器的Hash值
$hash = $this->_hash($key); //判断服务器列表是否排过序
if (!$this->isSorted) {
//倒序排列(把虚拟节点列表转换成逆时针圆环)
krsort($this->position, SORT_NUMERIC);
$this->isSorted = TRUE;
} //遍历虚拟节点列表,找到合适的服务器并返回
foreach($this->position as $server_hash=> $server){
if ($hash >= $server_hash) return $server;
}
return end($this->position);
} public function addServer($server, $nodesNum = 25){ if (isset($this->serverList[$server])) {
return;
} //增加虚拟节点,默认每个物理节点变成25个虚拟节点
for($i = 0; $i < $nodesNum; $i++){
$hash = $this->_hash($server.'-'.$i);//计算虚拟节点的Hash值
$this->position[$hash] = $server;
$this->serverList[$server][] = $hash;
} //此时虚拟节点列表发生了变化,因此标识为FALSE
$this->isSorted = FALSE;
return TRUE;
} public function removeServer($server){ if (!isset($this->serverList[$server])) {
return;
} //循环position数组,如果要删除的服务器的值等于position数组某个元素的值,则删除该元素
foreach($this->position as $k=>$v){
if($server == $v){
unset($this->position[$k]);
}
} unset($this->serverList[$server]); $this->isSorted = FALSE;
return TRUE;
}
} $hashserver = new consistentHash(); $hashserver->addServer('192.168.1.1');
$hashserver->addServer('192.168.1.2');
$hashserver->addServer('192.168.1.3');
$hashserver->addServer('192.168.1.4');
$hashserver->addServer('192.168.1.5'); echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br /><br />'; $hashserver->removeServer('192.168.1.2');
echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br /><br />'; $hashserver->addServer('192.168.1.6');
echo 'save key1 on server:',$hashserver->lookup('key1'),'<br />';
echo 'save key2 on server:',$hashserver->lookup('key2'),'<br /><br />';
输出:
save key1 on server:192.168.1.2
save key2 on server:192.168.1.1 save key1 on server:192.168.1.3
save key2 on server:192.168.1.1 save key1 on server:192.168.1.6
save key2 on server:192.168.1.1
参考:
①Memcached中一致性哈希(Consistent Hashing)的运用
Memcached 笔记与总结(7)增加虚拟节点的更多相关文章
- memcached学习——分布式算法(Consistant hash + 虚拟节点)(三)
1.取余算法 优点:数据分布均匀缺点:当服务器动态的添加.删除节点或者某台server down掉,会导致命中率超大幅度下降,甚至导致服务不可用 2.Consistant Hash算法:一致性哈希算法 ...
- Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比
准备工作: ① 配置文件 config.php ② 封装 Memcached 类 hash.class.php,包含普通哈希算法(取模)和一致性哈希算法 ③ 初始化 Memcached 节点信息 in ...
- Memcached笔记之分布式算法
1.根据余数进行分散:离散度高,但是增加或者移除服务器的时候,缓存充足的代价非常大.添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而音像缓存的命中率. 2.Consistent ...
- Hadoop学习笔记—13.分布式集群中节点的动态添加与下架
开篇:在本笔记系列的第一篇中,我们介绍了如何搭建伪分布与分布模式的Hadoop集群.现在,我们来了解一下在一个Hadoop分布式集群中,如何动态(不关机且正在运行的情况下)地添加一个Hadoop节点与 ...
- Memcached笔记——(四)应对高并发攻击【转】
http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...
- 快速增加controller节点
# controller1节点部署成功后,再添加controller节点,复制配置文件并修改即可openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p ...
- ACK容器服务虚拟节点使用阿里云日志服务来收集业务容器日志
按照这篇博文的介绍,可以在ACK集群上通过Helm的方式部署虚拟节点,提升集群的弹性能力.现在,通过虚拟节点部署的ECI弹性容器实例也支持将stdout输出.日志文件同步到阿里云日志服务(SLS)进行 ...
- Memcached笔记——(四)应对高并发攻击
近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...
- Memcached笔记——(二)XMemcached&Spring集成
今天研究Memcached的Java的Client,使用XMemcached 1.3.5,做个简单的测试,并介绍如何与Spring集成. 相关链接: Memcached笔记--(一)安装&常规 ...
随机推荐
- [技术学习]js接口继承
js是面向对象语言,但是js又缺乏了面向对象的诸多特性,比如继承,没有接口继承也没有父类继承,因此有时候需要人工来实现继承. 一.首先看下java中面向对象的继承: //定义类鸟类的飞行动作 inte ...
- 蚂蚁【A001】
[1005]出自附中练习场,其他编号(1005)[难度A]——————————————————————————————————————————————————————————————————————— ...
- http://www.cnblogs.com/younggun/archive/2013/07/16/3193800.html
http://www.cnblogs.com/younggun/archive/2013/07/16/3193800.html
- JSP获取客户端的IP地址的方法
//声明以下方法 <%! public String getRemortIP(HttpServletRequest request) { if (request.getHeader(" ...
- git 学习笔记7--branch
分支是git的必杀技. 站点另一个角度,分支是的快照移动有向图,刚好是拓扑排序的一种例子. basic git branch testing #创建分支 git checkout testing #切 ...
- PE的一些水 3-50
T3: 分解质因数. lalala T4: 暴模. 然而数学方法怎么搞?---->也就是怎么手算?... 于是看了一下讨论区...发现原来我的数学已经低于小学生水平了... 我们把答案abccb ...
- CentOS6.4 增加一个SFTP上传的用户
#创建sftp组 groupadd sftp #创建一个用户dsideal useradd -g sftp -s /bin/false dsideal #设置dsideal用户的密码 passwd d ...
- POJ 1127 Jack Straws(计算几何)
题目链接 抄的模版,居然1Y了.就是简单的线段相交+并查集. #include <iostream> #include <cstring> #include <cstdi ...
- SQL 学习笔记
1.判断数据库中某个值是否为null(而不是'null',空字符串'',若干个空格' ') 一定不能用=null 或 !=null,而要用is null 或 is not null. 2.在sqlse ...
- Java_JAVA6动态编译的问题
摘自:http://www.iteye.com/problems/14909 在使用JAVA6动态编译时遇到的一个问题,动态编译方法已经写就.通过main方法调用的动态编译时,编译通过,并可以使用编译 ...