让memcached分布式
memcached是应用最广的开源cache产品,它本身不提供分布式的解决方案,我猜想一方面它想尽量保持产品简单高效,另一方面cache的key-value的特性使得让memcached分布式起来比较简单。memcached的分布式主要在于客户端,通过客户端的路由处理来搭建memcached集群环境,因此在服务端,memcached集群环境实际上就是一个个memcached服务器的堆积品,环境的搭建比较简单。下面从客户端做路由和服务端集群环境搭建两方面来谈如何让memcached分布式。
客户端做路由
客户端做路由的原理非常简单,应用服务器在每次存取某key的value时,通过某种算法把key映射到某台memcached服务器nodeA上,因此这个key所有操作都在nodeA上,结构图如下所示:
存储某个key-value

取某个key-value

因此关键在于算法的选择,最基本的要求就是能让数据平均到所有服务器上。这自然而然让我想到了hash算法,spymemcached是一个用得比较广的java客户端,它就提供了一种简单的hash算法,实现类为ArrayModNodeLocator,从key映射到node的源码如下:
public MemcachedNode getPrimary(String k) {
return nodes[getServerForKey(k)];
}
private int getServerForKey(String key) {
int rv=(int)(hashAlg.hash(key) % nodes.length);
assert rv >= 0 : "Returned negative key for key " + key;
assert rv < nodes.length
: "Invalid server number " + rv + " for key " + key;
return rv;
}
从上面可知它是把所有node放在数组里,通过hash算法把key映射到某index,然后通过这个index在数组里取node
再则需要考虑如何容错,比如当某个node当掉了,如何自动地转到其他node上,上面的简单hash路由策略采用的方法是在数据组里顺序向下轮询node,找第一个工作正常的node即可。
最后要考虑当需要移除node或添加node的时候,如何有效地调整映射关系,这自然又让我们想到一致性hash算法,关于一致性hash算法就不多说,博文分布式设计与开发(二)------几种必须了解的分布式算法 有所涉及,这里可以看看spymemcached是如何利用这个算法来做路由的,实现类为KetamaNodeLocator,从key映射到node的源码如下:
public MemcachedNode getPrimary(final String k) {
MemcachedNode rv=getNodeForKey(hashAlg.hash(k));
assert rv != null : "Found no node for key " + k;
return rv;
}
MemcachedNode getNodeForKey(long hash) {
final MemcachedNode rv;
if(!ketamaNodes.containsKey(hash)) {
// Java 1.6 adds a ceilingKey method, but I'm still stuck in 1.5
// in a lot of places, so I'm doing this myself.
SortedMap<Long, MemcachedNode> tailMap=ketamaNodes.tailMap(hash);
if(tailMap.isEmpty()) {
hash=ketamaNodes.firstKey();
} else {
hash=tailMap.firstKey();
}
}
rv=ketamaNodes.get(hash);
return rv;
}
这段代码非常清晰,就是通过ketamaNodes这个数据结构按照一致性hash算法把node分区,每次都把映射到一个分区的key对于到负责这个分区的node上。
从上面几段代码和图示,我们大致能弄明白在客户端如何做路由来让memcached分布式,其实在大多数的项目中,以上这些简单的处理办法就足够了
memcached服务端集群
由上面可知一般的应用中memcached服务端集群不用做太多工作,部署一堆memcached服务器就可以了,大不了就是要做好监控的工作,但像facebook这样的大型互联网应用,并且又是那么依赖memcached,集群的工作就很有学问了。今年Qcom的会议上facebook就介绍了是如何通过扩展memcached来应付这么多数据量的,ppt可见Facebook的扩展Memcached实战。这个PPT比较抽象,我没看得太懂,并且facebook也只是蜻蜓点水,没透露太多的细节,但公司的资深架构师陈大峰同学做了些解析,才多多少少有点眉目。facebook所有数据的存取都基本上是在memcached上完成,后端的数据库mysql仅仅只是做持久化的作用,由于数据量巨大,做了类似与mysql的读写分离的结构,结构图如下所示:

其中非常重要的一点,当West的memcached要向East同步数据的时候,它没有采取memcached之间的同步,而是走MySQL replication,如下图所示:

这么做的原因我没法搞得太清楚,大概是比较信赖MySQL replication的简单稳定吧,并且像sns这种应用本身就不需要即时一致性,只要最终一致就行了。
另外在数据分布上是很有讲究的,facebook上面有很多很热的数据,比如LadyGaGa发布一条消息,将会有千万的人收到这个消息,如何把LadyGaGa和普通的用户同等对待就很可能会把这个memcached节点搞垮,甚至访问冲向后面的数据库后会把数据搞垮,如下图所示:

因此就需要一些策略来控制这些热点数据和热点访问,这些策略细节是什么facebook没说太清楚,一般说来可以把热点数据分布到其他节点,另外对于数据库可以加锁控制流量,只有拿到锁的访问才能直接访问数据库,没拿到的需要等候和竞争。
另外一个数据分布的难题是每个用户可能会有成百上千的好友,而这些好友的数据分布在成百上千台的memcached的节点,这样一个客户端就需要连接成千上万的memcached的节点,如下图所示:

这种问题一般说来可以采取数据重组,把有关联的数据重组在一起,而不是分布在n台机器上。
以上的这些facebook的实践只能说是走马观花地看看了,从我们可以看到一个简简单单memcached也能完成这么多玩样来,可以猜想到facebook的那些天才工程师们在亿万数据压力下被逼出了多少创新的设计,这些设计不一定适用于我们,不了解情景也没办法深究里面的细节,我们要做的是围绕我们自己的应用,让memcached玩出点味道来。
让memcached分布式的更多相关文章
- memcached 分布式
memcached定义 memcached 是一套分布式的高速缓存系统,被广泛应用于应用系统的缓存层来提升应用程序的访问速度:memcache缺乏认证以及安全管制,这表明应将memcached服务器放 ...
- Memcached 分布式缓存实现原理
摘要 在高并发环境下,大量的读.写请求涌向数据库,此时磁盘IO将成为瓶颈,从而导致过高的响应延迟,因此缓存应运而生.无论是单机缓存还是分布式缓存都有其适应场景和优缺点,当今存在的缓存产品也是数不胜数, ...
- memcached分布式实现原理
摘要 在高并发环境下,大量的读.写请求涌向数据库,此时磁盘IO将成为瓶颈,从而导致过高的响应延迟,因此缓存应运而生.无论是单机缓存还是分布式缓存都有其适应场景和优缺点,当今存在的缓存产品也是数不胜数, ...
- memcached 分布式聚类算法
memcached 分布式集群,该决定必须书面开发商自己.和redis 由分布式server决定.上 memcached 有两个选项用于分布式.第一个是:模运算 另一种是:一致性hash 分布式算法. ...
- memcached分布式缓存
1.memcached分布式简介 memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能.Memcache集群主机不能够相互通信传输数据,它的“分布式”是基于客户端的程序逻辑算 ...
- 09 Memcached 分布式之取模算法的缺陷
一: Memcached 分布式之取模算法的缺陷(1)假设你有8台服务器,运行中突然down一台,则求余数的底数就7. 后果: key_0%8==0 ,key_0%7==0 =>hist(命中) ...
- Memcached 分布式缓存实现原理简介
摘要 在高并发环境下,大量的读.写请求涌向数据库,此时磁盘IO将成为瓶颈,从而导致过高的响应延迟,因此缓存应运而生.无论是单机缓存还是分布式缓存都有其适应场景和优缺点,当今存在的缓存产品也是数不胜数, ...
- Memcached分布式缓存初体验
1 Memcached简介/下载/安装 Memcached是一个高性能的不是内存对象缓存系统,用于动态Web应用以减轻数据库负载.Memcached基于一个存储键/值对的HashMap.其客户端可以使 ...
- 缓存应用--Memcached分布式缓存简介
一. 什么是Memcached Memcached 是一个高性能的分布式内存 对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象 来减少读取数据库的次数,从而提供动态. ...
随机推荐
- NumPy字节交换
NumPy - 字节交换 我们已经知道,存储在计算机内存中的数据取决于 CPU 使用的架构. 它可以是小端(最小有效位存储在最小地址中)或大端(最小有效字节存储在最大地址中). numpy.ndarr ...
- Jni_Linux_01_转
1.Linux下JNI的使用(http://www.cnblogs.com/bastard/archive/2012/05/17/2506877.html) Linux下 JNI的使用 学习Andro ...
- thrift安装及常见问题
一.安装thrift (macOS / Linux) 1. 下载thrift0.10.0源码 https://github.com/apache/thrift/releases/tag/0.10.0 ...
- LeetCode第[69]题(Java):Sqrt(x)
题目:求平方根 难度:Easy 题目内容: Compute and return the square root of x, where x is guaranteed to be a non-neg ...
- spring3: AOP 之 6.2 AOP的HelloWorld
6.2.1 准备环境 首先准备开发需要的jar包,请到spring-framework-3.0.5.RELEASE-dependencies.zip和spring-framework-3.0.5.R ...
- Confluence 6 配置系统属性
在这个页面中描述 Confluence 启动时如何设置 Java 属性和其他选项. 请查看 How to fix out of memory errors by increasing availabl ...
- Django进阶Model篇005 - QuerySet常用的API
django.db.models.query.QuerySet QuerySet特点: 1.可迭代 2.可切片 查询相关API 1.get(**kwargs):返回与所给的筛选条件相匹配的对象,返回结 ...
- LinuxMint Mate 安装Google拼音输入法(Fcitx)
安装Google拼音输入法(Fcitx)$ sudo apt-get install fcitx fcitx-config-gtk fcitx-frontend-all fcitx-ui-classi ...
- H5手机端按钮点击一次却触发了多次点击事件
方案:在点击事件方法中加入以下语句 event.stopPropagation();
- Qt类型转换
(转自:http://qimo601.iteye.com/blog/1260479) 1.char * 与 const char *的转换 char *ch1="hello11"; ...