搭建一個三台服務器的Memcached集群


關於memcached的基礎知識可以查看博客其他博文,這里只記錄了搭建的過程,謝謝!

 

1、分別在三台服務器上安裝Memcached並啟動

  第一、由於memcached是基於libevent的事件處理,所以需要安裝libevent

yum install libevent libevent-devel

  第二、上傳Memcached到三台服務器(192.168.176.129/192.168.176.130/192.168.176.131)解壓並安裝

tar -zxvf memcached-1.2.5.tar.gz
cd memcached-1.2.5
./configure
make
make install

默認情況下安裝到/usr/local/bin下

  第三、啟動三台服務器的memcached服務

/usr/local/bin/memcached -u root -p 1211 -m 64m -vv

-vv:用very vrebose模式啟動,調試信息和錯誤輸出到控制台
-d:座位deamon在后台啟動
-d選項是啟動一個守護進程, 
-m是分配給Memcache使用的內存數量,單位是MB,我這里是10MB, 
-u是運行Memcache的用戶,我這里是root, 
-l是監聽的服務器IP地址,如果有多個地址的話,我這里指定了服務器的IP地址192.168.0.200-p是設置Memcache監聽的端口,我這里設置了12000,最好是1024以上的端口, 
-c選項是最大運行的並發連接數,默認是1024,我這里設置了256,按照你服務器的負載量來設定, 
-P是設置保存Memcache的pid文件,我這里是保存在 /tmp/memcached.pid,

2、編寫客戶端代碼

  雖然Memcached是分布式的,但是本身是不支持的,我們需要在客戶端編寫分布式策略,具體代碼里面注釋寫的非常詳細

/**
 * 
 */
package com.benxq.test;

import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;

import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;

/**
 * @ClassName: MemcachedUtils
 * @Description: Memcached工具類
 * Created by qucf on 2016年1月14日.
 */
public class MemcachedUtils {

    private static final Logger logger = Logger.getLogger(MemcachedUtils.class);

    //如果多個memcached必須制定memcachedName
    private static SockIOPool sockIOPool=SockIOPool.getInstance("memcached1");

    //服務器列表 格式:127.0.0.1:port
    private static String[] servers=new String[]{"192.168.176.131:1211","192.168.176.129:1211"};
    //服務器權重  所有權重的最大公約數應該是1  否則會造成資源浪費
    private static Integer[] serverWeights=new Integer[]{1,1};
    
    private static MemCachedClient cachedClient;

    static {
        
        //設置服務器列表
        sockIOPool.setServers(servers);
        
        //設置服務器的權重  權重和服務器的位置一一對應
        sockIOPool.setWeights(serverWeights);
        
        //設置開始時每個cache服務器的可用連接數
        sockIOPool.setInitConn(2);
        
        //設置每個服務器最少可用連接數
        sockIOPool.setMinConn(2);
        
        //設置每個服務器最大可用連接數 
        sockIOPool.setMaxConn(10);
        
        //設置可用連接池的最長等待時間  ms
        sockIOPool.setMaxIdle(5000);
        
        /**
         *設置連接池維護線程的睡眠時間
         *設置為0,維護線程不啟動
         *維護線程主要通過log輸出socket的運行狀況,監測連接數目及空閑等待時間等參數以控制連接創建和關閉。
         */
        sockIOPool.setMaintSleep(0);
        
        //設置是否使用Nagle算法,因為我們的通訊數據量通常都比較大(相對TCP控制數據)而且要求響應及時,因此該值需要設置為false(默認是true)
        sockIOPool.setNagle(true);
        
        //設置socket的讀取等待超時值 ms
        sockIOPool.setSocketTO(3000);
        
        //設置socket的連接等待超時值  ms
        sockIOPool.setSocketConnectTO(2000);
        
        /**
         *設置連接心跳監測開關。
         *設為true則每次通信都要進行連接是否有效的監測,造成通信次數倍增,加大網絡負載,因此該參數應該在對HA要求比較高的場合設為TRUE,默認狀態是false。
         */
        sockIOPool.setAliveCheck(false);
        
        /**
         *設置連接失敗恢復開關
         *設置為TRUE,當宕機的服務器啟動或中斷的網絡連接后,這個socket連接還可繼續使用,否則將不再使用,默認狀態是true,建議保持默認。
         */
        sockIOPool.setFailback(true);
        
        /**
         *設置容錯開關
         *設置為TRUE,當當前socket不可用時,程序會自動查找可用連接並返回,否則返回NULL,默認狀態是true,建議保持默認。
         */
        sockIOPool.setFailover(true);
        
        /**
          *設置hash算法
         *        alg=0 使用String.hashCode()獲得hash code,該方法依賴JDK,可能和其他客戶端不兼容,建議不使用
         *      alg=1 使用original 兼容hash算法,兼容其他客戶端
         *       alg=2 使用CRC32兼容hash算法,兼容其他客戶端,性能優於original算法
         *       alg=3 使用MD5 hash算法
         *采用前三種hash算法的時候,查找cache服務器使用余數方法。采用最后一種hash算法查找cache服務時使用consistent方法。
         */
        sockIOPool.setHashingAlg(3);
        
        //設置完pool參數后最后調用該方法,啟動pool。
        sockIOPool.initialize();
        
        if (cachedClient == null){
            
            cachedClient = new MemCachedClient("memcached1");
            /**
             *設定是否壓縮放入cache中的數據
             *默認值是ture
             *如果設定該值為true,需要設定CompressThreshold?
             */
            cachedClient.setCompressEnable(true);
            
            // 設定需要壓縮的cache數據的閾值 默認值是30k
            cachedClient.setCompressThreshold(30);
            

            /*設置cache數據的原始類型是String
                默認值是false
                只有在確定cache的數據類型是string的情況下才設為true,這樣可以加快處理速度。
             */
            cachedClient.setPrimitiveAsString(false);
            
        }
    }

    private MemcachedUtils() {
    }

    /**
     * 向緩存添加新的鍵值對。如果鍵已經存在,則之前的值將被替換。
     * @param key 鍵
     * @param value  值
     * @return
     */
    public static boolean set(String key, Object value) {
        return setExp(key, value, null);
    }

    /**
     * 向緩存添加新的鍵值對。如果鍵已經存在,則之前的值將被替換。
     * @param key 鍵
     * @param value 值
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    public static boolean set(String key, Object value, Date expire) {
        return setExp(key, value, expire);
    }

    /**
     * 向緩存添加新的鍵值對。如果鍵已經存在,則之前的值將被替換。
     * @param key 鍵
     * @param value 值
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */

    private static boolean setExp(String key, Object value, Date expire) {

        boolean flag = false;
        try {
            flag = cachedClient.set(key, value, expire);
        } catch (Exception e) {
            // 記錄Memcached日志
            logger.error("Memcached set方法報錯,key值:" + key + "\r\n");
        }
        return flag;
    }

    /**
     * 
     * 僅當緩存中不存在鍵時,add 命令才會向緩存中添加一個鍵值對。
     * @param key 鍵
     * @param value  值
     * @return
     */
    public static boolean add(String key, Object value) {
        return addExp(key, value, null);
    }

    /**
     * 僅當緩存中不存在鍵時,add 命令才會向緩存中添加一個鍵值對。
     * @param key 鍵
     * @param value 值
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    public static boolean add(String key, Object value, Date expire) {
        return addExp(key, value, expire);
    }

    /**
     * 僅當緩存中不存在鍵時,add 命令才會向緩存中添加一個鍵值對。
     * @param key  鍵
     * @param value  值
     * @param expire  過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    private static boolean addExp(String key, Object value, Date expire) {
        boolean flag = false;
        try {
            flag = cachedClient.add(key, value, expire);
        } catch (Exception e) {
            // 記錄Memcached日志
            logger.error("Memcached add方法報錯,key值:" + key + "\r\n");
        }
        return flag;
    }

    /**
     * 僅當鍵已經存在時,replace 命令才會替換緩存中的鍵。
     * @param key 鍵
     * @param value 值
     * @return
     */
    public static boolean replace(String key, Object value) {
        return replaceExp(key, value, null);
    }

    /**
     * 僅當鍵已經存在時,replace 命令才會替換緩存中的鍵。
     * @param key 鍵
     * @param value 值
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */

    public static boolean replace(String key, Object value, Date expire) {
        return replaceExp(key, value, expire);
    }

    /**
     * 僅當鍵已經存在時,replace 命令才會替換緩存中的鍵。
     * @param key 鍵
     * @param value  值
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    private static boolean replaceExp(String key, Object value, Date expire) {
        boolean flag = false;
        try {
            flag = cachedClient.replace(key, value, expire);
        } catch (Exception e) {
            logger.error("Memcached replace方法報錯,key值:" + key + "\r\n");
        }
        return flag;
    }

    /**
     * get 命令用於檢索與之前添加的鍵值對相關的值。
     * @param key  鍵
     * @return
     */
    public static Object get(String key) {
        Object obj = null;
        try {
            obj = cachedClient.get(key);
        } catch (Exception e) {
            logger.error("Memcached get方法報錯,key值:" + key + "\r\n");
        }
        return obj;
    }

    /**
     * 刪除 memcached 中的任何現有值。
     * @param key 鍵
     * @return
     */
    public static boolean delete(String key) {
        return deleteExp(key, null);
    }

    /**
     * 刪除 memcached 中的任何現有值。
     * @param key   鍵
     * @param expire 過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    public static boolean delete(String key, Date expire) {
        return deleteExp(key, expire);
    }

    /**
     * 刪除 memcached 中的任何現有值。
     * @param key 鍵
     * @param expire  過期時間 New Date(1000*10):十秒后過期
     * @return
     */
    private static boolean deleteExp(String key, Date expire) {
        boolean flag = false;
        try {
            flag = cachedClient.delete(key, expire);
        } catch (Exception e) {
            logger.error("Memcached delete方法報錯,key值:" + key + "\r\n");
        }
        return flag;
    }

    /**
     * 清理緩存中的所有鍵/值對
     * @return
     */
    public static boolean flashAll() {
        boolean flag = false;
        try {
            flag = cachedClient.flushAll();
        } catch (Exception e) {
            logger.error("Memcached flashAll方法報錯\r\n");
        }
        return flag;
    }

    public static void main(String[] args) {
        MemcachedUtils.add("teacher", "zhangsan");               
//        Object obj = MemcachedUtils.get("room");
//        System.out.println("===="+obj+"====");
    }
}

 

如有問題,大家可以聯系我QQ 752432995 一同交流技術分享學習的快樂!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM