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

相關文章
相關標籤/搜索