一、概述
Memcached和mysql一样,是一款客户端/服务器端(C/S)系统管理软件,有IP、端口,一旦启动,服务器就一直处于可用状态。
Mysql是通过SQL语句管理“磁盘中”的文件,Memcached是通过客户端发送的命令管理“内存中缓存”的数据。 
需要缓存的对象或数据以 key/value 对的形式保存在服务器端,key的值通过hash(hash算法的意义在于提供一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系)进行转换,把value传递到对应的具体的某台服务器上。

Memcached的分布式不是在服务器端实现的,而是在客户端应用中实现的,即通过内置算法制定目标数据的节点。
多台服务器之间是没有任何通信联系的,每台服务器只是对自己的数据进行管理。

* 布置多台Memcached服务器。怎么确定一个数据应该保存到哪台服务器上?
* 方案一:普通Hash分布。
* 方案二:一致性Hash分布。
理论参考:https://blog.csdn.net/u011489043/article/details/78944985 二、简单hash算法
function simpleHash(string $key)
{
$md5 = md5($key);
$hash = 0;
for ($i = 0; $i < strlen($md5); $i++) {
$hash += ord($md5{$i});
}
return $hash;
}

三、普通hash分布

/**
* 普通Hash分布
* 取模算法算法的原理是:hash(key)%N
*/
$servers = ['192.168.1.12', '192.168.1.20'];
echo PHP_EOL . '普通hash算法' . PHP_EOL;
echo 'save key1 in server:' . $servers[simpleHash('this is key1') % 2] . PHP_EOL;
echo 'save key2 in server:' . $servers[simpleHash('this is key2') % 2] . PHP_EOL;

四、一致性哈希

* 一致哈希(Consistent Hashing)算法,分布式系统负载均衡的首选算法
*
* 步骤:
* 1、通常,一个缓存数据的key经过hash后会得到一个32位的值,
* 将一个32位整数(0~2^32-1)想象成一个环
* 2、通过hash函数把可以处理成整数,在环中找到一个位置与之对应
* 3、使用hash函数处理服务器使用的IP地址,把Memcached服务器群也映射到环上
* 4、把数据映射到服务器上
* 沿着圆环顺时针方向的key出发,直到遇到一个服务器为止,把key对应的数据保存到这个服务器上
* 5、移除服务器
* 受影响的仅是当前服务器节点沿着逆时针出发直到遇到下一个服务器之间的数据,
* 把这些数据按操作4重新映射即可
* 6、添加服务器
* 受影响的是当前服务器节点沿着逆时针出发直到遇到下一个服务器之间的数据,
* 重新映射
PHP的一种实现
class FlexiHash
{
// 保存服务器列表
private $serverList = [];
// 记录服务器列表是否已经排过序
private $isSorted = false; /**
* 添加一个服务器到服务器列表中
*/
public function addServer($server)
{
$hash = simpleHash($server);
if (!isset($this->serverList[$hash])) {
$this->serverList[$hash] = $server;
}
$this->isSorted = false;
return true;
} /**
* 从服务器列表中删除一个服务器
*/
public function removeServer($server)
{
$hash = simpleHash($server);
if (isset($this->serverList[$hash])) {
unset($this->serverList[$hash]);
}
$this->isSorted = false;
return true;
} /**
* 在当前的服务器列表中找到合适的服务器存放数据
* 逆时针的圆环
*/
public function lookup($key)
{
$hash = simpleHash($key);
if (!$this->isSorted) {
krsort($this->serverList, SORT_NUMERIC);
$this->isSorted = true;
}
foreach ($this->serverList as $pos => $server) {
if ($hash >= $pos) {
return $server;
}
}
$index = array_search(min($this->serverList), $this->serverList);
return $this->serverList[$index];
}
} // 测试
echo PHP_EOL . '一致性hash算法' . PHP_EOL;
$hserver = new FlexiHash();
$hserver->addServer('192.168.1.1');
$hserver->addServer('192.168.1.2');
$hserver->addServer('192.168.1.3');
$hserver->addServer('192.168.1.4');
$hserver->addServer('192.168.1.5');
echo '初始分布' . PHP_EOL;
echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;
echo '===============================================' . PHP_EOL;
$hserver->removeServer('192.168.1.4');
echo '删除一台服务器后' . PHP_EOL;
echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;
echo '===============================================' . PHP_EOL;
$hserver->addServer('192.168.1.6');
echo '添加一台服务器后' . PHP_EOL;
echo 'save key1 in server:' . $hserver->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $hserver->lookup('key2') . PHP_EOL;

另一种实现 增加虚拟节点
class ConsistentHashing
{
// 每个节点对应虚拟节点数
const VIRTUAL_NODES = 32;
// server 拥有的hash(节点+虚拟节点)
protected $nodes = [];
// hash映射server
protected $position = [];
// 记录服务器列表是否已经排过序
protected $isSorted = false; /**
* 添加节点
*/
public function addNode($server)
{
if (isset($this->nodes[$server])) {
return;
} // 添加节点和虚拟节点
for ($i = 0; $i < self::VIRTUAL_NODES; $i++) {
$hash = $this->myHash($server . '#' . $i);
$this->position[$hash] = $server;
$this->nodes[$server][] = $hash;
} $this->isSorted = false;
} /**
* 删除节点
*/
public function delNode($server)
{
if (!isset($this->nodes[$server])) return; // 循环删除虚拟节点
foreach ($this->nodes[$server] as $val) {
unset($this->position[$val]);
} // 删除节点
unset($this->nodes[$server]); $this->isSorted = false;
} /**
* 定位key所属节点
* 顺时针环
*/
public function lookup($key)
{
if (!$this->isSorted) {
$this->sortPosition();
$this->isSorted = true;
} $hash = $this->myHash($key); // 先取圆环上最小的一个节点,当成结果
$server = current($this->position); // 循环获取相近的节点
foreach ($this->position as $pos => $val) {
if ($hash <= $pos) {
$server = $val;
break;
}
} return $server;
} /**
* 按键名顺序排序
*/
private function sortPosition()
{
ksort($this->position);
} /**
* 自定义哈希函数,把key转为32位符号整数
*/
private function myHash($key)
{ // return sprintf('%u', crc32($key));
return simpleHash($key);
}
} // 测试
echo PHP_EOL . '另一种hash一致性算法' . PHP_EOL;
$ch = new ConsistentHashing();
$ch->addNode('192.168.1.1');
$ch->addNode('192.168.1.2');
$ch->addNode('192.168.1.3');
$ch->addNode('192.168.1.4');
$ch->addNode('192.168.1.5');
echo '初始化' . PHP_EOL;
echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;
echo '==========================================' . PHP_EOL;
$ch->delNode('192.168.1.4');
echo '删除节点后' . PHP_EOL;
echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;
echo '==========================================' . PHP_EOL;
$ch->addNode('192.168.1.6');
echo '添加一台服务器后' . PHP_EOL;
echo 'save key1 in server:' . $ch->lookup('key1') . PHP_EOL;
echo 'save key2 in server:' . $ch->lookup('key2') . PHP_EOL;

php hash算法实现memcached分布式的更多相关文章

  1. 一致性Hash算法在Redis分布式中的使用

    由于redis是单点,但是项目中不可避免的会使用多台Redis缓存服务器,那么怎么把缓存的Key均匀的映射到多台Redis服务器上,且随着缓存服务器的增加或减少时做到最小化的减少缓存Key的命中率呢? ...

  2. 一致性Hash算法在Memcached中的应用

    前言 大家应该都知道Memcached要想实现分布式只能在客户端来完成,目前比较流行的是通过一致性hash算法来实现.常规的方法是将server的hash值与server的总台数进行求余,即hash% ...

  3. Nginx+Memcache+一致性hash算法 实现页面分布式缓存(转)

    网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化.实现分布式高速缓存就是其中的一个很好的解决方案... 1)先来看看Nginx负载均衡 Nginx负载均衡依赖自带的 ngx_h ...

  4. (转) 一致性Hash算法在Memcached中的应用

    前言 大家应该都知道Memcached要想实现分布式只能在客户端来完成,目前比较流行的是通过一致性hash算法来实现.常规的方法是将 server的hash值与server的总台数进行求余,即hash ...

  5. 一致性hash算法在memcached中的使用

    一.概述 1.我们的memcacheclient(这里我看的spymemcache的源代码).使用了一致性hash算法ketama进行数据存储节点的选择.与常规的hash算法思路不同.仅仅是对我们要存 ...

  6. 一致性Hash算法介绍(分布式环境算法)

    32的整数环(这个环被称作一致性Hash环),根据节点名称的Hash值(其分布范围同样为0~232)将节点放置在这个Hash 环上.然后根据KEY值计算得到其Hash值(其分布范围也同样为0~232  ...

  7. 分布式缓存技术memcached学习(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...

  8. 分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前, ...

  9. 分布式一致性hash算法

    写在前面  在学习Redis的集群内容时,看到这么一句话:Redis并没有使用一致性hash算法,而是引入哈希槽的概念.而分布式缓存Memcached则是使用分布式一致性hash算法来实现分布式存储. ...

随机推荐

  1. android studio 导入主题设置,代码风格(附带eclipse 主题代码样式)

    在这里我最想说的,android studio默认主题样式,太low.不适合长时间写代码,看代码颜色不好识别,相对于背景的代码样式,我都不想吐槽了.还是网上下载主题代码样式导入样式.在这里我推荐 Su ...

  2. GitHub vs. Bitbucket 不只是功能不同

    https://www.oschina.net/translate/bitbucket-vs-github-its-more-than-just-features 让我们回到2005年,Bitkeep ...

  3. Hibernate笔记二

    1.延迟加载(懒加载) 概念 需要用到该数据的时候才要加载 种类 类的延迟加载 案例 说明:注意:使用的是Load方法 1.  执行22行代码的时候,不发出sql语句,说明类的延迟加载和主键没有关系 ...

  4. centos7的网络管理(参考使用)

    How to Setup network on centos 7 Posted krizna Centos, Centos 7   After installing Centos 7, You may ...

  5. ubuntu修改pip的官方源为豆瓣源

    修改官方源为豆瓣源: 编辑配置文件, 如果没有, 新建一份(我这里没有): mkdir ~/.pipvim ~/.pip/pip.conf 添加内容如下: [global] index-url = h ...

  6. windows安装ActiveMQ以及点对点以及发布订阅

    一.MQ产品的分类 1.RabbitMQ 是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级 ...

  7. 杭电2019 数列有序!(STL解法)

    由于这题对于学过数据结构的我来说,真的是很简单,为了减少时间上的损失,链表无疑是最好的选择(因为数组要往后移位子).然后,因为最近想玩些STL的骚操作,所以就用<list>了,然后顺便学了 ...

  8. 含有namespace的类型如何访问

    下图中包含的String类型,如果想要在别的文件中去访问的话: 1)需要include"ApiClient.hpp" 2)需要使用oatpp::web::client::ApiCl ...

  9. 基于Modelsim的视频流仿真

    一.前言 最近在看牟新刚写的<基于FPGA的数字图像处理原理及应用>,书中关于FPGA数字图像处理的原理的原理写的非常透彻,在网上寻找了很久都没有找到完整的源代码工程,因此尝试自己做了补充 ...

  10. 整理了一下NLP中文数据集

    个人理解: 句子相似性判断.情感分析.实体识别.智能问答,本质基本上都是分类任务. 阅读理解(抽取式.回答式.完形填空)是逐个候选项的分类问题处理. 参考 https://github.com/chi ...