zoukankan      html  css  js  c++  java
  • Memcached 分布式集群

    首先解释一下我的标题,用到了 分布式 和 集群两个单词,
    为什么是集群?
    解决[相同业务]问题的服务器多个以上就称为集群.这里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语言写一个扩展.

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

  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/codeAB/p/7040575.html
Copyright © 2011-2022 走看看