首先解释一下我的标题,用到了 分布式 和 集群两个单词,
为什么是集群?
解决[相同业务]问题的服务器多个以上就称为集群.这里memcached就是做相同任务的(提供缓存服务)
为什么是分布式?
虽然针对的是同样的任务(缓存),但是每一台memcached存储的数据不一样,这就叫分布式.

有很多架构是 分布式的但不叫集群(比如 把订单处理,和商品库存 分配到不同服务器上独立部署,这叫分布式),
有很多是 集群架构但是不一定是分布式的(比如 应用服务器集群,每一台服务器上的资源一样)

通常来说一般的集群部署表现为  一群memcached服务器 加  一台或多台 负载均衡服务器,
应用程序 要set 一个缓存,首先是发送到 负载均衡服务器,然后由负载均衡服务器通过负载均衡算法
分配到一台memcached服务器来存储,get 一个缓存也是同理.如下图:

但是目前我没有看到有针对 memcached 可用的负载均衡服务器成品,
对于memcached这种火热的缓存没道理没有解决方案啊,难道有其他的架构方式?

我翻阅了网上很多关于memcached的分布式解决方案,都没有中间负载均衡服务器,而是把均衡算法交给
了应用程序(客户端)来完成

常见的两种负载算法  取模,一致性hash

取模算法的原理:
根据 set/get 的hash(key)值 对集群中memcached的个数取模,就可以均匀的分配到每一台memcached服务器
例如 有3台memcacehed,如果 hash(key)=200923780;  200923780 mod 3 = 1
现在需要往集群里面添加一台memcached , 200923780 mod 4 = 0;
看出来了吗,还是原来的key  但是因为集群的memcached数量不一样了,导致最后链接的memcached server变了,
3台memcached扩容到4台,大约有75%的缓存不能正确命中,当100台集群中加一台,不能命中的概率是 99% (n(n+1)),
这个结果在大型系统中是不允许的.
当然不考虑集群的伸缩性,这种算法效率其实是最高的,但是作为一个高素质的架构师
怎么可能设计一个不能伸缩性的架构呢?

一致性hash算法的原理是:

按照集群中 server的ip 计算到 hash(ip),[这个地方的hash就是crc32],得到的值 放到下面的x轴上,

如下图,有三个memcached服务器通过hash分别放到了具体位置上,现在应用程序 通过 set/get 的key也进行crc32(key) 落到了下面的位置.

如图,key1落到了mem3和mem2之间,那么规定key1朝着箭头的方向找到的第一个memcached就作为目标,根据这个

规定,key2的目标就是mem2,key3由于向箭头方向已经找不到了,那么就取反方向第一个mem1作为目标.

现在再往集群中加一台memcached服务器mem-4:

落到mem-1和mem-3上的缓存没有收到一点点影响,mem-2也只收到了一定的影响, mem-1和mem-4这一截的缓存落到了mem-4上,mem-4和mem-2这一截仍然落在mem-2上.

随着机器越多,新增和减少集群机器影响变得更小.

难道这样就完美了?

上图其实画得很理想化,因为hash的随机行很大,所以memcached 通过hash(ip)后在x轴上的分布可能是这样的:

大量的key落在了mem1上,这看起来一点都不均衡O**O

那怎么让他均衡呢,

翻阅了网上很多文章,基本上是使用虚拟环,原理是:

为每一个 物理 memcached 分配100-150个虚拟节点,key落在虚拟节点上,通过虚拟节点找到实际的物理节点.如图:

虚拟节点越多,分布越均匀,但是越多也会增加找节点的时间,需要找到一个平衡点,推荐 100-150,

php的memcached扩展中已经实现了一致性hash存储的算法,代码实例:

<?php

$mem = new Memcached();
$mem->setOption(Memcached::OPT_HASH, Memcached::HASH_CRC);
$mem->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
$servers = array(
array('127.0.0.1', 11211, 33),
array('127.0.0.1', 11212, 67)
);
$mem->addServers($servers); $mem->set('key1','value1');
echo '<br/>';
print_r($mem->get('key1'));
echo '<br/>';
$mem->set('key2','value2');
echo '<br/>';
print_r($mem->get('key2'));
echo '<br/>';

这种算法是 php-memcahed扩展提供的,如果追求灵活和可控,可以用纯php实现同样的负载算法,但是执行效率可能会下降.

如果追求效率,也可以用c语言写一个扩展.

我在接下来的博客中会进一步的扩展相关知识

Memcached 分布式集群的更多相关文章

  1. Memcached【Magent+Memcached】集群

    Memcached介绍  事件处理libevent是个程序库,它将Linux的epoll.BSD类操作系统的kqueue等事件处理功能封装成统一的接口.即使对服务器的连接数增加,也能发挥O(1)的性能 ...

  2. elasticsearch 口水篇(5)es分布式集群初探

    es有很多特性,分布式.副本集.负载均衡.容灾等. 我们先搭建一个很简单的分布式集群(伪),在同一机器上配置三个es,配置分别如下: cluster.name: foxCluster node.nam ...

  3. Twemproxy 分布式集群缓存代理服务器

    Twemproxy 分布式集群缓存代理服务器 是一个使用C语言编写.以代理的方式实现的.轻量级的Redis代理服务器, 它通过引入一个代理层,将应用程序后端的多台Redis实例进行统一管理, 使 应用 ...

  4. spring-session实现分布式集群session的共享

    前言 HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的.但是我们把应用搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户 ...

  5. Apache shiro集群实现 (五)分布式集群系统下的高可用session解决方案

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  6. Nginx+Tomcat+Memcached 实现集群部署时Session共享

    Nginx+Tomcat+Memcached 实现集群部署时Session共享 一.简介 我们系统经常要保存用户登录信息,有Cookie和Session机制,Cookie客户端保存用户信息,Sessi ...

  7. Redis面试题及分布式集群

    Reference: http://blog.csdn.net/yajlv/article/details/73467865 1. 使用Redis有哪些好处? (1) 速度快,因为数据存在内存中,类似 ...

  8. spring-session实现分布式集群session的共享(转)

    原文: https://www.cnblogs.com/youzhibing/p/7348337.html HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保 ...

  9. Elasticsearch学习系列七(Es分布式集群)

    核心概念 集群(Cluster) 一个Es集群由多个节点(Node)组成,每个集群都有一个共同的集群名称作为标识 节点(Node) 一个Es实例就是一个Node.Es的配置文件中可以通过node.ma ...

随机推荐

  1. zookeeper的原理,5分钟了解zookeeper

    一 .Zookeeper功能简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/ ...

  2. copyOf数组复制方法的使用(数组扩容练习)

    package com.Summer_0420.cn; import java.util.Arrays; /** * @author Summer * 我们使用数组存储了50名学生的考试信息 , 今天 ...

  3. Golang 爬虫-广度优先(获取html文档中的超链接)

    package main import( "fmt" "net/http" "io/ioutil" "regexp" & ...

  4. Java调用FFmpeg进行视频处理及Builder设计模式的应用

    1.FFmpeg是什么 FFmpeg(https://www.ffmpeg.org)是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.它用来干吗呢?视频采集.视频格式转化.视频 ...

  5. .NET Core中复制源文件夹下的所有内容到新文件夹

    .NET Core中没有原生的复制文件夹方法,我们可以自己写个: 新建一个.NET Core控制台项目,示例代码如下: using System; using System.IO; namespace ...

  6. [SDOI2017]天才黑客[最短路、前缀优化建图]

    题意 一个 \(n\) 点 \(m\) 边的有向图,还有一棵 \(k\) 个节点的 trie ,每条边上有一个字符串,可以用 trie 的根到某个节点的路径来表示.每经过一条边,当前携带的字符串就会变 ...

  7. Python 学习 第十三篇:数据的读写-文件、DataFrame、json

    Python的文件是一个重要的对象,使用open()函数来打开文件,创建文件对象,进行文件的读写操作.当数据用于交换信息时,通常需要把数据保存为有格式的文本数据,可以保存为有特定的行分隔符和列分隔符的 ...

  8. [C#] LINQ之LookUp

    声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢! 本文作者文采欠佳,文字表达等方面不是很好,但实际的代码例子是非常实用的,请作参考. 一.先准备要使用的类: 1.Person类: cl ...

  9. Linux 命令(二)

    man help:线上查询及帮助命令 命令  --help:简单帮助 help  cd:查看一些Linux命令行的一些内置命令 文件和目操作命令(19个) ls  cd  cp  find  mkdi ...

  10. 分解质因数FZU - 1075

    题目简述:就是给一个数,把他拆分成多个素数的乘积,这正好是算术基本定理.本题我的解决方法是埃氏素数筛+质因数保存...开始T掉了,是因为我在最后枚举了素数,保存他们的次数,然后两次for去查询他们的次 ...