Memcached 集群的高可用(HA)架构

Memcache自身并无实现集群功能,若是想用Memcahce实现集群须要借助第三方软件或者本身设计编程实现,这里将采用memagent代理实现,memagent又名magent,你们注意下,不要将这两者当成两种工具。至于memcache、magent的安装请参考文章 在Linux上安装Memcached服务 和  magent编译安装及常见错误       java

总体架构

直接上图:linux

从图中能够看到有两个magent节点,两个memcached节点,每一个magent节点又分别代理两个memcached节点,应用系统端使用magent pool来调用memcache进行存储。硬件结构为两台linux服务器,每台服务器上分别安装magent和memcached服务,并设为开机启动。这样作的好处是任何一台服务器宕机后都不影响magent pool获取memcache信息,即实现了memcached的高可用(HA),若是两台机器都宕机了,只能说明你RP太差了。固然,也能够用三台、四台或者更多服务器来提升HA。编程

测试HA

测试背景,本地局域网内两台服务器172.18.117.71(memcache端口11211,magent端口11210),172.18.117.113(memcache端口11211,magent端口11210),和两台服务器在同一局域网内的测试机器,下边是测试代码:服务器

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MainTest {
  
  public static void main(String[] arg){
    SockIOPool pool = SockIOPool.getInstance();
    //magent链接池
    pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
    pool.setSocketTO(3000);
    pool.setNagle(false);
    pool.setSocketConnectTO(0);
    pool.initialize();
    MemCachedClient memCachedClient = new MemCachedClient();
    memCachedClient.set("becd0000", "测试例子");
    //System.out.println(memCachedClient.get("becd0000"));
    //System.out.println(memCachedClient.flushAll());
  }

}

  

步骤1:将key为“becd0000”,value为“测试例子”经过magent的pool放到memcache中架构

步骤2:修改magent链接池为单个memcache链接,代码以下memcached

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MainTest {
  
  public static void main(String[] arg){
    SockIOPool pool = SockIOPool.getInstance();
    //magent链接池
    pool.setServers(new String[] { "172.18.117.71:11211"});
    pool.setSocketTO(3000);
    pool.setNagle(false);
    pool.setSocketConnectTO(0);
    pool.initialize();
    MemCachedClient memCachedClient = new MemCachedClient();
    //memCachedClient.set("becd0000", "测试例子");
    System.out.println(memCachedClient.get("becd0000"));
    //System.out.println(memCachedClient.flushAll());
  }

}

  

能够看到单独访问memcache是能够取到刚才所存储的值的。工具

步骤3:修改测试

pool.setServers(new String[] { "172.18.117.71:11211"});

ui

pool.setServers(new String[] { "172.18.117.113:11211"});

再次执行能够看到和步骤2同样的结果,均可以取到值,说明经过magent代理存的值会分别放到两个memcache中spa

步骤4:中止172.18.117.113上的memcached服务

中止memcached服务命令:kill "cat /tmp/memcached.pid"

步骤5:再次经过magent代理取值,代码以下:

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MainTest {
  
  public static void main(String[] arg){
    SockIOPool pool = SockIOPool.getInstance();
    //magent链接池
    pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
    pool.setSocketTO(3000);
    pool.setNagle(false);
    pool.setSocketConnectTO(0);
    pool.initialize();
    MemCachedClient memCachedClient = new MemCachedClient();
    //memCachedClient.set("becd0000", "测试例子");
    System.out.println(memCachedClient.get("becd0000"));
    //System.out.println(memCachedClient.flushAll());
  }

}

  

能够看到依然可以取到值。

步骤6:启动刚才停掉的memcached服务,重启后memcache中全部信息将清空

步骤7:再次经过magent代理池去取key为“becd0000”的值,代码以下:

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MainTest {
  
  public static void main(String[] arg){
    SockIOPool pool = SockIOPool.getInstance();
    //magent链接池
    pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
    pool.setSocketTO(3000);
    pool.setNagle(false);
    pool.setSocketConnectTO(0);
    pool.initialize();
    MemCachedClient memCachedClient = new MemCachedClient();
    //memCachedClient.set("becd0000", "测试例子");
    System.out.println(memCachedClient.get("becd0000"));
    //System.out.println(memCachedClient.flushAll());
  }

}

  

能够看到这里取到的值为null。

结果分析

经过以上测试能够得出结论

一、经过magent的链接池放的值会分别存在magent代理的全部memcached上去

二、若是有一个memcached宕机经过magent代理方式还能取到值

三、若是memcached修复重启后经过magent代理方式取到的值就会为Null,这是因为memcache重启后里边的值随着memcache服务的中止就消失了(由于在内存中),可是magent是经过key进行哈希计算分配到某台机器上的,memcache重启后会还从这台机器上取值,全部取到的值就没空。

解决办法

一、在每次memcache宕机修复后能够写一个程序把集群中的其余memcache的全部信息全给拷贝到当前宕机修复后的memcache中。

二、本身写代理,当从一个memcached服务上取到的值为null时再去其余memcached上取值

注意事项

magent的调用方式同memcached同样,客户端能够不用改代码便可实现切换到magent模式下

原文地址 : http://www.tuicool.com/articles/VJfEfyv