memcache分布式部署的原理分析
今天在封装memcache操作类库过程中,意识到一直以来对memcache的使用都是局限在单台服务器的情况下,还没有使用到memcache的分布式部署。虽然知道memcache的分布式是怎么回事,但是为了更加深入的理解,还是通过谷歌搜索了这方面的相关资料。
下面是精摘于网络的一些关于 memcache分布式部署 的资料。
memcache分布式部署是什么呢?下面通过一个例子来认识一下:
假设memcached服务器有node1~node3三台, 应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据。

首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后, 客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。 服务器选定后,即命令它保存“tokyo”及其值。

同样,“kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存。
接下来获取保存的数据。获取时也要将要获取的键“tokyo”传递给函数库。 函数库通过与数据保存时相同的算法,根据“键”选择服务器。 使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。 只要数据没有因为某些原因被删除,就能获得保存的值。

这样,将不同的键保存到不同的服务器上,就实现了memcached的分布式。 memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行。
下面我们具体介绍一下 Consistent hashing算法:
Consistent Hashing的简单说明

首先求出memcached服务器(节点)的哈希值, 并将其配置到0~2SUP(32)的圆(continuum)上。 然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。 然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。 如果超过2SUP(32)仍然找不到服务器,就会保存到第一台memcached服务器上。
从上图的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化 而影响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的 第一台服务器上的键会受到影响。

因此,Consistent Hashing最大限度地抑制了键的重新分布。 而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想。 使用一般的hash函数的话,服务器的映射地点的分布非常不均匀。 因此,使用虚拟节点的思想,为每个物理节点(服务器) 在continuum上分配100~200个点。这样就能抑制分布不均匀, 最大限度地减小服务器增减时的缓存重新分布。
下面再介绍一下虚拟节点
Consistent hashing算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如我们的系统中有两台 server,其环分布如下:

此时必然造成大量数据集中到Server 1上,而只有极少量会定位到Server 2上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。
具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,我们决定为每台服务器计算三个虚拟节点,于是可以分别计算“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”、“Memcached Server 2#1”、“Memcached Server 2#2”、“Memcached Server 2#3”的哈希值,于是形成六个虚拟节点:

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”三个虚拟节点的数据均定位到Server 1上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布,避免出现雪崩的情况。
例子
启动Memcache服务,比如这样
| 代码如下 | 复制代码 |
| /usr/local/bin/memcached -d -p 11213 -u root -m 10 -c 1024 -t 8 -P /tmp/memcached.pid /usr/local/bin/memcached -d -p 11214 -u root -m 10 -c 1024 -t 8 -P /tmp/memcached.pid /usr/local/bin/memcached -d -p 11215 -u root -m 10 -c 1024 -t 8 -P /tmp/memcached.pid |
|
启动三个只使用10M内存以方便测试。
分布式部署
PHP的PECL扩展中的memcache实际上在2.0.0的版本中就已经实现多服务器支持,现在都已经2.2.5了。请看如下代码
| 代码如下 | 复制代码 |
| $memcache = new Memcache; $memcache->addServer('localhost', 11213); $memcache->addServer('localhost', 11214); $memcache->addServer('localhost', 11215); $memStats = $memcache->getExtendedStats(); print_r($memStats); |
|
通过上例就已经实现Memcache的分布式部署,是不是非常简单。
分布式系统的良性运行
在Memcache的实际使用中,遇到的最严重的问题,就是在增减服务器的时候,会导致大范围的缓存丢失,从而可能会引导数据库的性能瓶颈,为了避免出现这种情况,请先看Consistent hashing算法,中文的介绍可以参考这里,通过存取时选定服务器算法的改变,来实现。
修改PHP的Memcache扩展memcache.c的源代码中的
| 代码如下 | 复制代码 |
| "memcache.hash_strategy" = standard | |
为
| 代码如下 | 复制代码 |
| "memcache.hash_strategy" = consistent | |
重新编译,这时候就是使用Consistent hashing算法来寻找服务器存取数据了。
有效测试数据表明,使用Consistent hashing可以极大的改善增删Memcache时缓存大范围丢失的情况。
| 代码如下 | 复制代码 |
| NonConsistentHash: 92% of lookups changed after adding a target to the existing 10 NonConsistentHash: 90% of lookups changed after removing 1 of 10 targets ConsistentHash: 6% of lookups changed after adding a target to the existing 10 ConsistentHash: 9% of lookups changed after removing 1 of 10 targets |
|
总结:
在动态分布式缓存系统里哈希算法承担着系统架构上的关键点。 使用分布更合理的算法可以使得多个服务节点间的负载相对均衡,可以最大程度的避免资源的浪费以及服务器过载。 使用一致性哈希算法,可以最大程度的降低服务硬件环境变化带来的数据迁移代价和风险。 使用更合理的配置策略和算法可以使分布式缓存系统更加高效稳定。
memcache分布式部署的原理分析的更多相关文章
- Memcache分布式部署方案
基础环境 其实基于PHP扩展的Memcache客户端实际上早已经实现,而且非常稳定.先解释一些名词,Memcache是danga.com的一个开源项目,可以类比于MySQL这样的服务,而PHP扩展的M ...
- Redisson 实现分布式锁的原理分析
写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题. 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有一个进程在持有锁的期间崩溃而未能主动释放锁, ...
- Redlock(redis分布式锁)原理分析
Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁: 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击) ...
- [转]Memcache的使用和协议分析详解
Memcache是什么 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应 ...
- zabbix分布式部署和主机自动发现
1.分布式部署原理 1.1Zabbix分布式部署的原理 传统的部署架构,是server直接监控所有的主机,全部主机的数据都是有server自己来采集和处理,server端的压力比较大,当监控主机数量很 ...
- 第六章 Fisco Bcos 多服务器分布式部署
想了解相关区块链开发,技术提问,请加QQ群:538327407 前提概要 前面几章,我们通过单机部署,在单台服务器上搭建四个节点,完成Fisco Bcos 底层搭建,并完成相关合约开发.sdk 开发. ...
- Android平台APK分析工具包androguard的部署使用和原理分析
原创文章,转载请注明出处,谢谢. Android应用程序分析主要有静态分析和动态分析两种,常见的静态分析工具是Apktool.dex2jar以及jdgui.今天突然主要到Google code上有个叫 ...
- Redisson 实现分布式锁原理分析
Redisson 实现分布式锁原理分析 写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题. 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有 ...
- BI系统的分布式部署原理和技术实现
1.什么是分布式 关于"分布式系统"的定义,我们先看下书中是怎么说的.<分布式系统原理和范型>一书中是这样定义分布式系统的:"分布式系统是若干独立计算机的集合 ...
随机推荐
- C#接口的经典案例
C#接口(interface)实例子(简单而经典)2008/12/04 10:04using System; using System.Collections.Generic; using Syste ...
- REST_FRAMEWORK加深记忆-第二次练习官方文档
我想,其它几个基于PYTHON的REST API模块概念都差不多吧. 先深入搞定这个吧. 前几次练习完了有一些印象,并且在工作中实践过一个,现在多弄几次,玩熟悉点. Serializers.py __ ...
- [wikioi]线段树练习
http://codevs.cn/problem/1080/ #include <vector> #include <iostream> #include <string ...
- mysql建表时拆分出常用字段和不常用字段
一对一 一张表的一条记录一定只能与另外一张表的一条记录进行对应,反之亦然. 学生表:姓名,性别,年龄,身高,体重,籍贯,家庭住址,紧急联系人 其中姓名.性别.年龄.身高,体重属于常用数据,但是籍贯.住 ...
- Excel操作--使用NPOI导入导出Excel为DataTable
1.ExcelHelper封装 namespace NPOI操作Excel { public class ExcelHelper { /// <summary> /// DataTable ...
- Quartz任务调度快速入门
Quartz任务调度快速入门 概述 了解Quartz体系结构 Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器.任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的 ...
- JDynamic :支持Json反序列化为Dynamic对象
JDynamic :支持Json反序列化为Dynamic对象 2010年 .NET 4.0 发布前后,从3.5向4.0迁移,那时也有一些异构系统的需求,主要是和PHP打交道,通信使用的HTTP 格 ...
- NDK(22)JNI编程如何避免常见缺陷
转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html 避免常见缺陷 假设您编写了一些新 JNI 代码,或者继承了别处的某些 J ...
- C#中默认的修饰符
参考自Default visibility for C# classes and members (fields, methods, etc)? Classes and structs that ar ...
- oracle 11g SQL Developer instead of isqlplus
Oracle11g的新工具SQL DEVELOPER,替代了 isqlplus 1.创建连接方式 2.SQL输入窗口 3.表的结构及其他信息查阅 4.SQL语句测试 5.创建表 6.用户授权 7.数据 ...