转载地址:http://www.cnblogs.com/phpstudy2015-6/p/6713164.html

作者:那一叶随风

1、memcached分布式简介

  memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。Memcache集群主机不能够相互通信传输数据,它的“分布式”是基于客户端的程序逻辑算法进一步实现的。

请看下面简图:

根据上图我们简述分析分布式memcached的set与get的过程

set过程:

1、首先通过应用程序set(‘key’,’value’)

2、进入程序,使用key通过逻辑算法得出这个key需要存储的节点位置

3、根据节点位置连接相应的memcached服务器,并发送set命令

get过程:

1、首先通过应用程序get(‘key’)

2、接着使用该key通过逻辑算法获取该key的存储节点

3、根据节点连接相应的memcached服务器,并发送get命令

  实现memcached有很多种方式,其中最常用的就是一致哈希思想的分布式(就简称为一致哈希分布式啦)。好的东西当然需要次劣品来衬托它的优点啦,因此在这里除了讲解一致哈希分布式,还会讲到取模分布式。从而进一步分析他们的优缺点。

  这里的例子都会采用PHP代码实现,当然啦,最重要的是思想与方法嘛!毕竟这两样东西在任何语言中都是相通的。

2、取模算法方式

  何为取模算法方式分布式?就是将key转换为32位的数字,并与memcached服务器的总数进行相除取得余数。而这个余数就是memcached服务器的节点node。有了这个node我们就可以确定memcached服务器,就可以发送命令给memcached执行了。

图示解析:

整个过程上图所示。

1)、PHP代码实现

GetModMemcache.class.php

 1 <?php
2 #分布式memcache(取模计算)
3 class GetModMemcache
4 {
5 private $total=‘‘; #存储memcache服务器的总数
6 private $servers=array(); #存储memcache服务器的具体信息
7 /**
8 * @desc 构造函数
9 *
10 * @param $serversArr array | memcache服务器具体信息
11 */
12 public function __construct($serversArr)
13 {
14 $this->total=count($serversArr);
15 $this->servers=$serversArr;
16 }
17
18 /**
19 * @desc 计算$key的存储位置(即哪个服务器)
20 *
21 * @param string | key字符串
22 *
23 * @return int 返回第几个服务器
24 */
25 protected function position($key)
26 {
27 #使用crc32(),将字符串转化为32为的数字
28 return sprintf(‘%u‘,crc32($key))%$this->total; #取余
29 }
30
31 /**
32 * @desc 获取memcached对象
33 *
34 * @param $position int | key的位置信息
35 *
36 * @return object 返回实例化memcached对象
37 */
38 protected function getMemcached($position)
39 {
40 $host=$this->servers[$position][‘host‘]; #服务器池中某台服务器host
41 $port=$this->servers[$position][‘port‘]; #服务器池中某台服务器port
42 $m= new memcached();
43 $m->addserver($host, $port);
44 return $m;
45 }
46
47 /**
48 * @desc 设置key-value值
49 *
50 * @param string | key字符串
51 * @param mixed | 值可以是任何有效的非资源型php类型
52 *
53 * @return 返回结果
54 */
55 public function setKey($key, $value)
56 {
57 $num=$this->position($key);
58 echo $num; #调试用
59 $m=$this->getMemcached($num); #获取memcached对象
60 return $m->set($key, $value);
61 }
62
63 public function getKey($key)
64 {
65 $num=$this->position($key);
66 $m=$this->getMemcached($num);
67 return $m->get($key);
68 }
69
70
71 }
72
73
74 $arr=array(
75 array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11210‘),
76 array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11211‘),
77 array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11212‘),
78 );
79 $mod=new GetModMemcache($arr);
80
81 /*
82 #存储数据
83 $a=$mod->setKey(‘key3‘, ‘key33333‘);
84 echo "<pre>";
85 print_r($a);
86 echo "</pre>";die;
87 */
88 /*
89 #获取数据
90 $b=$mod->getKey(‘key1‘);
91 echo "<pre>";
92 print_r($b);
93 echo "</pre>";die;
94 */
95 ?>

2)、进行相应测试

  1、连续插入三个数据

  #set(‘key1’,’value11111’);  #node=1

  #set(‘key2’,’value22222’);  #node=1

  #set(‘key3’,’value33333’;)  #node=0

  2、分别telnet连接192.168.95.11:(11210、11211、11212)

  11210含有key3数据

  11211含有key1、key2数据

  11212不含数据

  3、使用程序get数据

  结果都能够将数据取出来

3)、优缺点

  优点:

  1、简单实用易理解

  2、数据分布均匀

  缺点:

  1、宕了一台memcached服务器时不能自动调整群组去处理数据,使一部分数据不能使用缓存,一直持续从数据库中获取数据。

  2、当需要扩容的时候,增加多台memcached服务器,那么原来已经缓存的数据大多数都不能够被命中,即数据无用。

3、一致哈希算法方式

何为一致哈希算法方式分布式呢?

  想象一下,将32位的所有数字从小到大按顺时针分布在一个圆环上;

  其次,将每个存储节点赋予一个名字,并通过crc32函数将其转换为32位的数字,此数字就是该memcached服务器的存储节点

  接着,将key也通过crc32函数转换为32位的数字,它的所在位置按顺时针方向走第一个遇到的存储节点所对应的memcached服务器就是该key的最终存储服务器。

1)、图像解析

  假设node1节点服务器挂了,根据按顺时针最近原则,那么原本存储在node1节点的数据此时也可存储在node3节点中。

  假设有扩容的需要,增加的两台memcached服务器,又将会怎么样呢?请看下图分析

结果显示只有少量数据会受到影响,相对于整体数据来说这些影响还是在可接受的范围内。

  从上面的图示我们可以很容易发现存在这么个缺点,即是使用crc32函数我们不能控制memcached存储节点的具体位置,并且节点的总数量相对于2的32次方是显得多么的渺小。假若恰好即使这几个存储节点都距离的非常近呢,那么必将有一个memcached服务器承受绝大多数的数据缓存。

请看下图分析:

解决办法:

  将一个真实存储节点映射为多个虚拟存储节点,即真实节点+后缀再通过crc32处理(例如:node1_1、node1_2、node1_3、…..、node1_n)

看下图节点分布:

  三个真实节点在圆环上就变成了三十个存储节点,这样就可以避免存储节点相距太近而导致数据缓存分布不均匀的问题了,而且存储机制没有任何变化。

2)、PHP代码实现

ConsistentHashMemcache.class.php

  1 <?php
2 #分布式memcache 一致性哈希算法(采用环状数据结构)
3 class ConsistentHashMemcache
4 {
5 private $virtualNode=‘‘; #用于存储虚拟节点个数
6 private $realNode=array(); #用于存储真实节点
7 private $servers=array(); #用于存储memcache服务器信息
8 #private $totalNode=array(); #节点总数
9 /**
10 * @desc 构造函数
11 *
12 * @param $servers array | memcache服务器的信息
13 * @param $virtualNode int | 虚拟节点个数,默认64个
14 */
15 public function __construct($servers, $virtualNode=64)
16 {
17 $this->servers=$servers;
18 $this->realNode=array_keys($servers);
19 $this->virtualNode=$virtualNode;
20 }
21
22 /**
23 * @return int 返回32位的数字
24 */
25 private function hash($str)
26 {
27 return sprintf(‘%u‘,crc32($str)); #将字符串转换为32位的数字
28 }
29
30 /**
31 * @desc 处理节点
32 *
33 * @param $realNode array | 真实节点
34 * @param $virturalNode int | 虚拟节点个数
35 *
36 * @return array 返回所有节点信息
37 */
38 private function dealNode($realNode, $virtualNode)
39 {
40 $totalNode=array();
41 foreach ($realNode as $v)
42 {
43 for($i=0; $i<$virtualNode; $i++)
44 {
45 $hashNode=$this->hash($v.‘-‘.$i);
46 $totalNode[$hashNode]=$v;
47 }
48 }
49 ksort($totalNode); #按照索引进行排序,升序
50 return $totalNode;
51 }
52
53 /**
54 * @desc 获取key的真实存储节点
55 *
56 * @param $key string | key字符串
57 *
58 * @return string 返回真实节点
59 */
60 private function getNode($key)
61 {
62 $totalNode=$this->dealNode($this->realNode, $this->virtualNode); #获取所有虚拟节点
63 /* #查看虚拟节点总数
64 echo "<pre>";
65 print_r($totalNode);
66 echo "</pre>";die;
67 */
68 $hashNode=$this->hash($key); #key的哈希节点
69 foreach ($totalNode as $k => $v) #循环总结点环查找
70 {
71 if($k >= $hashNode) #查找第一个大于key哈希节点的值
72 {
73 return $v; #返回真实节点
74 }
75 }
76 return reset($totalNode); #假若总节点环的值都比key哈希节点小,则返回第一个总哈希环的value值
77 }
78
79 /**
80 * @desc 返回memcached对象
81 *
82 * @param $key string | key值
83 *
84 * @return object
85 */
86 private function getMemcached($key)
87 {
88 $node=$this->getNode($key); #获取真实节点
89 echo $key.‘真实节点:‘.$node.‘<br/>‘; #测试使用,查看key的真实节点
90 $host=$this->servers[$node][‘host‘]; #服务器池中某台服务器host
91 $port=$this->servers[$node][‘port‘]; #服务器池中某台服务器port
92 $m= new memcached(); #实例化
93 $m->addserver($host, $port); #添加memcache服务器
94 return $m; #返回memcached对象
95 }
96
97 /**
98 * @desc 设置key-value值
99 */
100 public function setKey($key, $value)
101 {
102 $m=$this->getMemcached($key);
103 return $m->set($key, $value);
104 }
105
106 /**
107 * @desc 获取key中的value
108 */
109 public function getKey($key)
110 {
111 $m=$this->getMemcached($key);
112 return $m->get($key);
113 }
114
115
116 }
117
118 ?>

3)、测试

1、查看所有虚拟节点

一共64*3=132个虚拟节点(虚拟节点设置还是属于偏少的,一般都会设置在100~200)

2、set测试

 1 include ‘./ConsistentHashMemcache.class.php‘;
2 header("content-type: text/html;charset=utf8;");
3 $arr=array(
4 ‘node1‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11210‘),
5 ‘node2‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11211‘),
6 ‘node3‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11212‘),
7 );
8
9 $c=new ConsistentHashMemcache($arr);
10
11 #测试set
12 $c->setKey(‘aaa‘, ‘11111‘);
13 $c->setKey(‘bbb‘, ‘22222‘);
14 $c->setKey(‘ccc‘, ‘33333‘);

分别telnet连接192.168.95.11:(11210、11211、11212)

在节点node1中get(‘aaa’)、get(‘bbb’)能取到值

在节点node3中get(‘ccc’)能取到值

3、get测试

 1 include ‘./ConsistentHashMemcache.class.php‘;
2 header("content-type: text/html;charset=utf8;");
3 $arr=array(
4 ‘node1‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11210‘),
5 ‘node2‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11211‘),
6 ‘node3‘=>array(‘host‘=>‘192.168.95.11‘, ‘port‘=>‘11212‘),
7 );
8
9 $c=new ConsistentHashMemcache($arr);
10 #测试get
11 echo $c->getKey(‘aaa‘).‘<br/>‘;
12 echo $c->getKey(‘bbb‘).‘<br/>‘;
13 echo $c->getKey(‘ccc‘).‘<br/>‘;

4、优缺点

  相对于取模方式分布式,一致性哈希方式分布式的代码复杂性要高一点,但这也在可以接受的范围内,不构成任何阻碍问题。相反它的优点就非常显著,通过虚拟节点的方式实现,可以使不可控的存储节点能够尽可能的均匀分布在圆环上,从而达到数据均匀缓存在各个主机里。其次增加与删除虚拟节点对于之前缓存的整体数据影响非常小。

memcache 分布式缓存的更多相关文章

  1. MemCache分布式缓存的一个bug

    Memcached分布式缓存策略不是由服务器端至支持的,多台服务器之间并不知道彼此的存在.分布式的实现是由客户端代码(Memcached.ClientLibrary)通过缓存key-server映射来 ...

  2. C# Memcache分布式缓存简单入门

    什么是Memcache?能做什么? 以下是百度的观点: memcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问 ...

  3. Memcached 分布式缓存系统部署与调试

    Memcache 分布式缓存系统部署与调试 工作机制:通过在内存中开辟一块区域来维持一个大的hash表来加快页面访问速度,和数据库是独立的;目前主要用来缓存数据库的数据;存放在内存的数据通过LRU算法 ...

  4. 分布式缓存之 memcache 实现分布式缓存

    最近想搞点分布式,但是不知道整点什么,来点简单的吧. 今天讲下memcache的分布式缓存 首先下载memcache的服务器端 百度下可以找到 然后执行安装和开启(关闭服务器)命令(还有其他的命令 可 ...

  5. 分布式缓存 memcache学习

    1.使用分布式缓存是为了解决多台机器共享信息的问题,通过访问一个ip和端口来可以访问不同的IIS服务器 2.memcache基础原理 在Socket服务器端存储数据是以键值对的形式存储 内存处理的算法 ...

  6. MemCache分布式内存对象缓存系统

    MemCache超详细解读 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而 ...

  7. 分布式缓存Memcached/memcached/memcache详解及区别

    先来解释下标题中的三种写法:首字母大写的Memcached,指的是Memcached服务器,就是独立运行Memcached的后台服务器,用于存储缓存数据的“容器”.memcached和memcache ...

  8. CYQ.Data 对于分布式缓存Redis、MemCache高可用的改进及性能测试

    背景: 随着.NET Core 在 Linux 下的热动,相信动不动就要分布式或集群的应用的需求,会慢慢火起来. 所以这段时间一直在研究和思考分布式集群的问题,同时也在思考把几个框架的思维相对提升到这 ...

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

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

随机推荐

  1. 离线安装Cloudera Manager 5和CDH5(最新版5.9.3) 完全教程(六)CM的安装

    一.角色分配 Cloudera Manager Agent:向server端报告当前机器服务状态. Cloudera Manager Server:接受agent角色报告服务状态,以视图界面展现,方便 ...

  2. (二 -1) 天猫精灵接入Home Assistant-控制Mqtt设备

    关于hass对接mqtt 请参考官网 https://www.hachina.io/docs/7083.html 1 登陆运行着hass的阿里云服务器 2 修改hass配置文件,添加mqtt服务信息 ...

  3. (1)HomeAssistant 安装开始

    https://www.hachina.io/docs/1843.html 在Windows中安装Python3和HomeAssistant 第一步:在浏览器中访问Python官网网址为:www.py ...

  4. maven 仓库配置 pom中repositories属性

    文章转自http://blog.csdn.net/zlgydx/article/details/51130627 什么是Maven仓库在不用Maven的时候,比如说以前我们用Ant构建项目,在项目目录 ...

  5. PAT A1028 List Sorting (25 分)——排序,字符串输出用printf

    Excel can sort records according to any column. Now you are supposed to imitate this function. Input ...

  6. vmware 12中安装苹果系统

    我用的系统是win10... 一.所需软件: 1.下载并安装VMware Workstation Pro 12 密码:7ybc和序列号 密码是:bwm0 2.下载unlocker 203(for OS ...

  7. centos 6.X下建立arduino开发环境

    一.安装arduino IDE 1.下载linux下arduino IDE安装包,从网址:http://arduino.cc/en/Main/Software下载,如果这个网址打不开,可从网盘下载:h ...

  8. TravelPort官方API解读

    TravelPort Ping通使用教程 Unit1 Lesson 1: 标签(空格分隔): 完成第1单元的三个课程后,您可以使用Travelport Universal API来提出服务请求并了解响 ...

  9. C# LINQ 详解 From Where Select Group Into OrderBy Let Join

    目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...

  10. UWP简单示例(二):快速开始你的3D编程

    准备 IDE:Visual Studio 开源库:GitHub.SharpDx 入门示例:SharpDX_D3D12HelloWorld 为什么选择 SharpDx? SharpDx 库与 UWP 兼 ...