天天看點

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

redis 學習問題總結

http://aperise.iteye.com/blog/2310639

ehcache memcached redis 緩存技術總結

http://aperise.iteye.com/blog/2296219

redis-stat 離線安裝

http://aperise.iteye.com/blog/2310254

redis  cluster 非ruby方式啟動

http://aperise.iteye.com/blog/2310254

redis-sentinel安裝部署

http://aperise.iteye.com/blog/2342693

spring-data-redis使用

 http://aperise.iteye.com/blog/2342615

redis用戶端redisson實戰

http://blog.csdn.net/zilong_zilong/article/details/78252037

redisson-2.10.4源代碼分析

http://blog.csdn.net/zilong_zilong/article/details/78609423

tcmalloc jemalloc libc選擇

http://blog.csdn.net/u010994304/article/details/49906819

1.前言ehcache memcached redis 緩存技術總結

    1.1 工作中最初的緩存實作

    工作中第一次接觸緩存技術,是在一個java web程式中做權限管理功能。當時權限架構選擇的是springsecurity,springsecurity提供了需要實作的接口調取使用者關于URL相關權限資料,當時權限資料全部存放于資料庫中,為了降低對資料庫的通路,在web啟動時候,就将存放于資料庫中所有權限資料加載到記憶體中,做法如下:

//用靜态變量Map存儲使用者權限資料
//Map中key為使用者賬号,value為使用者權限對象
static Map<String,Object> rightsMap = new HashMap<String,Object>();
//web中配置一個servlet listener,web啟動後馬上加載資料到靜态變量rightsMap
//權限管理功能中增加一個通知接口,友善在修改權限後,更新靜态變量rightsMap
//springsecurity接口通路靜态變量rightsMap拿取權限資料
           

     上面可能是當時對一些緩存架構不太了解情況下很多開發者的普遍思路了。

    1.2 hibernate中接觸到的ehcache

    EhCache是工作中接觸到的第二個緩存技術,接觸到它主要是因為工作中使用到了Hibernate,而EhCache是Hibernate中預設的CacheProvider,EhCache 是一個純Java的程序内緩存架構。

    1.3 後來接觸的memcached和redis

    後來接觸的項目越來越多,陸續接觸到了memcached和redis,這裡将這些用到過的緩存自己做個總結,以便溫故知新。  

2.Ehcache

    2.1 Ehcache初識

    1)EhCache 是一個純Java的程序内緩存架構,具有快速、精幹等特點,是Hibernate中預設的CacheProvider。

    2)Ehcache是一種廣泛使用的開源Java分布式緩存。主要面向通用緩存,Java EE和輕量級容器。它具有記憶體和磁盤存儲,緩存加載器,緩存擴充,緩存異常處理程式,一個gzip緩存servlet過濾器,支援REST和SOAP api等特點。

    3)Ehcache最初是由Greg Luck于2003年開始開發。2009年,該項目被Terracotta購買。軟體仍然是開源,但一些新的主要功能(例如,快速可重新開機性之間的一緻性的)隻能在商業産品中使用,例如Enterprise EHCache and BigMemory。,維基媒體Foundationannounced目前使用的就是Ehcache技術。

    4)Ehcache詳見如下部落格:

來源 作者 标題 網址
iteye RayChase Ehcache詳細解讀 http://raychase.iteye.com/blog/1545906
cnblogs hoojo 整合Spring 使用頁面、對象緩存 http://www.cnblogs.com/hoojo/archive/2012/07/12/2587556.html
官網 http://www.ehcache.org/

    2.2 Ehcache使用

    這裡以官網http://www.ehcache.org/documentation/3.0/getting-started.html 例子進行講解

     1)eclipse中建立maven普通工程,pom.xml配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.test</groupId>
	<artifactId>ehcachetest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ehcachetest</name>
	<packaging>jar</packaging>
	<properties>
		<!-- 這裡定義所有的版本資訊,友善版本統一管理 -->
		<ehcache.version>3.0.1</ehcache.version>
	</properties>
	<dependencies>
		<!-- 這裡添加所有的依賴包 -->
		<dependency>
			<groupId>org.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>${ehcache.version}</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- 這裡添加所有插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.4.3</version>
				<configuration>
					<!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
           

     2)eclipse中windows-Preferences-Maven- Download Artifact Sources勾選上友善後續檢視依賴包源代碼

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

     3)直接調用java API管理緩存cache

  • 通過

    CacheManagerBuilder

     的靜态方法

    newCacheManagerBuilder

     執行個體化CacheManager對象
  • 通過

    CacheConfigurationBuilder

     的靜态方法

    newCacheManagerBuilder

     來建立緩存

    Cache

     的配置

    CacheConfiguration

     ,然後通過CacheManager的靜态方法

    withCache

     注冊配置
  • 通過CacheManager的靜态方法getCache擷取

    Cache

     對象
  • 拿到

    Cache

     對象後,可調用put設定緩存值key-value,可調用get通過可以擷取value
  • 通過CacheManager的靜态方法removeCache擷取删除Cache對象
  • 最後必須調用CacheManager的靜态方法close關閉CacheManager,以便釋放資源
package com.ehcache.test;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
public class ManagedCacheTest {
	public static void main(String[] args) {
		CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
				// 通過CacheManagerBuilder 的靜态方法newCacheManagerBuilder 執行個體化CacheManager對象
				.withCache(
						"preConfigured",
						//通過CacheConfigurationBuilder 的靜态方法newCacheManagerBuilder 來建立緩存Cache 的配置CacheConfiguration ,
						//然後通過CacheManager的靜态方法withCache 注冊配置
						CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
								ResourcePoolsBuilder.heap(10))).build();
		cacheManager.init();

		//通過CacheManager的靜态方法getCache擷取Cache 對象
		Cache<Long, String> preConfigured = cacheManager.getCache("preConfigured", Long.class, String.class);

		//通過CacheManager的方法createCache建立另一個不同配置Cache對象
		Cache<Long, String> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder
				.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)).build());

		//拿到Cache 對象後,可調用put設定緩存值key-value,可調用get通過可以擷取value
		//通過CacheManager的靜态方法removeCache擷取删除Cache對象
		myCache.put(1L, "da one!");
		String value = myCache.get(1L);
		System.out.println("value=" + value);
		cacheManager.removeCache("preConfigured");
		//最後可通過CacheManager的靜态方法close關閉CacheManager
		cacheManager.close();
	}
}
           

     4)Ehcache3中引入的使用者管理cache

  • UserManagedCache是EhCACHE3中的新特性,UserManagedCache不受

    CacheManager

     管理
  • 可以在build時候傳入false先不初始化UserManagedCache
  • 最後必須調用UserManagedCache.close()來釋放資源
package com.ehcache.test;
import org.ehcache.UserManagedCache;
import org.ehcache.config.builders.UserManagedCacheBuilder;
public class UserManagedCacheTest {
	public static void main(String[] args) {
		//UserManagedCache是EhCACHE3中的新特性,UserManagedCache不受CacheManager 管理
		UserManagedCache<Long, String> userManagedCache = UserManagedCacheBuilder.newUserManagedCacheBuilder(
				Long.class, String.class).build(false);//可以在build時候傳入false先不初始化UserManagedCache
		userManagedCache.init();
		userManagedCache.put(1L, "da one!");
		//最後必須調用UserManagedCache.close()來釋放資源
		userManagedCache.close();
	}
}
           

     5)EhCache中的存儲分層

        EhCache中資料預設是存儲在記憶體(堆存儲)中的,但記憶體(堆存儲)這種資源是非常寶貴的,為了高效利用資源,盡量使得頻繁使用的資料放置于記憶體(堆存儲)中,那些使用頻率低的資料可以放置在非堆存儲中,甚至持久化到資源豐富的磁盤上。

      非堆存儲Off-heap

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("tieredCache",
    CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
        ResourcePoolsBuilder.newResourcePoolsBuilder()
            .heap(10, EntryUnit.ENTRIES)
            .offheap(10, MemoryUnit.MB)) 
        )
    .build(true);
cacheManager.close();
           

      注意:上面的例子配置設定了一個隻允許10個緩存大小的非堆記憶體;

                 使用非堆記憶體時候,你必須自己序列化對象和反序列化對象,這樣速度肯定比堆記憶體慢;

                  使用非堆記憶體時候,一個優勢是不必擔心有類似堆記憶體存儲時候的垃圾回收GC影響;

                  使用非堆記憶體時候,一定不要忘記了要去設定-XX:MaxDirectMemorySize

      磁盤存儲Disk persistence

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
    .with(CacheManagerBuilder.persistence(getStoragePath() + File.separator + "myData")) 
    .withCache("persistent-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
        ResourcePoolsBuilder.newResourcePoolsBuilder()
            .heap(10, EntryUnit.ENTRIES)
            .disk(10, MemoryUnit.MB, true)) 
        )
    .build(true);
persistentCacheManager.close();
           

      注意:使用磁盤存儲,需要通過CacheManagerBuilder.persistence(String)設定存儲位置;

                 使用磁盤存儲,你必須自己去序列化和反序列化存儲對象,速度上肯定是慢與非堆存儲,更慢于堆存儲;

                 使用磁盤存儲,最大的優勢是,在Ehcache關閉後,緩存資料是可以恢複的

      三種存儲混合使用Three tiers

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
    .with(CacheManagerBuilder.persistence(getStoragePath() + File.separator + "myData")) 
    .withCache("threeTieredCache",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
            ResourcePoolsBuilder.newResourcePoolsBuilder()
                .heap(10, EntryUnit.ENTRIES) 
                .offheap(1, MemoryUnit.MB) 
                .disk(20, MemoryUnit.MB) 
            )
    ).build(true);
persistentCacheManager.close();
           

       注意:上面例子中混合使用三種存儲;

                  其中記憶體heap中機關是10個,允許最多10個key-value值,機關也可以是KB  MB等;

                  其中offheap容量為1MB ;

                  其中disk容量為20MB,注意這裡仍然要通過CacheManagerBuilder.persistence(String)設定存儲位置

      關于資源池更新Update ResourcePools

ResourcePools pools = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(20L, EntryUnit.ENTRIES).build(); 
cache.getRuntimeConfiguration().updateResourcePools(pools); 
assertThat(cache.getRuntimeConfiguration().getResourcePools()
    .getPoolForResource(ResourceType.Core.HEAP).getSize(), is(20L));
           

        注意:這裡意思是可以線上更新線上的已經存在的EhCache緩存配置資訊

      關于緩存資料有效時間設定Data freshness

CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
        ResourcePoolsBuilder.heap(100)) 
    .withExpiry(Expirations.timeToLiveExpiration(Duration.of(20, TimeUnit.SECONDS))) 
    .build();
           

         注意:這裡意思是可以設定緩存資料有效時間

    6)使用XML類配置EhCache

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="myehcache">
        <!--定義一個cache,别名為foo-->
	<cache alias="foo">
                <!--cache的可以為String類型,value這裡沒定義,預設為Object類型-->
		<key-type>java.lang.String</key-type>
		<resources>
                        <!--heap存儲且隻允許2000個key-value對象-->
			<heap unit="entries">2000</heap>
                        <!--offheap存儲且其大小最大為500MB-->
			<offheap unit="MB">500</offheap>
		</resources>
	</cache>
        <!--這裡定義一個基本的cache配置模闆,其他cache可以繼承此配置進行擴充-->
	<cache-template name="myDefaults">
		<key-type>java.lang.Long</key-type>
		<value-type>java.lang.String</value-type>
		<heap unit="entries">200</heap>
	</cache-template>
        <!--這裡定義一個cache名字為bar,其key覆寫模闆配置,value和模闆配置保持一緻-->
	<cache alias="bar" uses-template="myDefaults">
		<key-type>java.lang.Number</key-type>
	</cache>
        <!--這裡定義一個cache名字為simpleCache,全部采用模闆配置-->
	<cache alias="simpleCache" uses-template="myDefaults" />
</ehcache>
           

     上面的XML定義好後,可以通過如下java  API進行調用

final URL myUrl = this.getClass().getResource("/ecache.xml"); 
Configuration xmlConfig = new XmlConfiguration(myUrl); 
CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig); 
           

    2.3 EhCache與spring內建

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:ehcache/ehcache.xml"/>
    </bean>

    <bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcacheManager"/>
        <property name="transactionAware" value="true"/>
    </bean>
</beans>
           

     在controller中注入ehCacheCacheManager後,就可以拿到ehCacheCacheManager對象以獲得你配置的cache對象進行操作。

    2.4 EhCache在hibernate中的使用

        參見http://blog.csdn.net/lpz283929516/article/details/8084664

    2.5 EhCache三種緩存算法

  • LRU       最近最少使用
  • LFU       較少頻率使用
  • FIFO      先進先出

3.Memcached

    3.1memcach和memcached的差別

    這裡引用楊鑫奇在cnblogs的一篇關于“小白談memcache和memcached的差別”的部落格,這兩個是啥呢,部落客說的很清楚了,memcache和memcached在php關于memcached用戶端中有兩個版本:

  • memcache是pecl擴充庫版本
  • memcached是libmemcached版本

    3.2memcached完全剖析

來源 作者 标題 網址
cnblogs

作者:長野雅廣

(Masahiro Nagano)

翻譯:charlee

memcached的基礎 http://kb.cnblogs.com/page/42731/
cnblogs

作者:長野雅廣

(Masahiro Nagano)

翻譯:charlee

了解memcached的記憶體存儲 http://kb.cnblogs.com/page/42732/
cnblogs

作者:長野雅廣

(Masahiro Nagano)

翻譯:charlee

memcached的删除機制和發展方向 http://kb.cnblogs.com/page/42733/
cnblogs

作者:長野雅廣

(Masahiro Nagano)

翻譯:charlee

memcached的分布式算法 http://kb.cnblogs.com/page/42734/
cnblogs

作者:長野雅廣

(Masahiro Nagano)

翻譯:charlee

memcached的應用和相容程式 http://kb.cnblogs.com/page/42735/

        3.2.1 memcached的基礎

        1) memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 為首開發的一款軟體。memcached是高性能的分布式記憶體緩存伺服器。 一般的使用目的是,通過緩存資料庫查詢結果,減少資料庫通路次數,以提高動态Web應用的速度、 提高可擴充性。

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

        2) memcached的特征

  • 協定簡單:memcached的伺服器用戶端通信并不使用複雜的XML等格式, 而使用簡單的基于文本行的協定。是以,通過telnet 也能在memcached上儲存資料、取得資料。
  • 基于libevent的事件處理:libevent是個程式庫,它将Linux的epoll、BSD類作業系統的kqueue等事件處理功能 封裝成統一的接口。
  • 内置記憶體存儲方式:為了提高性能,memcached中儲存的資料都存儲在memcached内置的記憶體存儲空間中。 由于資料僅存在于記憶體中,是以重新開機memcached、重新開機作業系統會導緻全部資料消失。 另外,内容容量達到指定值之後,就基于LRU(Least Recently Used)算法自動删除不使用的緩存。
  • memcached不互相通信的分布式:memcached盡管是“分布式”緩存伺服器,但伺服器端并沒有分布式功能。 各個memcached不會互相通信以共享資訊。那麼,怎樣進行分布式呢? 這完全取決于用戶端的實作。
方法 說明
add 僅當存儲空間中不存在鍵相同的資料時才儲存
replace 僅當存儲空間中存在鍵相同的資料時才儲存
set 與add和replace不同,無論何時都儲存(set函數忽視該delete阻塞,照常儲存資料)
get 擷取資料
get_multi 一次取得多條資料
delete 删除資料,它有個獨特的功能delete('鍵', '阻塞時間(秒)')删除第一個參數指定的鍵的資料。第二個參數指定一個時間值,可以禁止使用同樣的鍵儲存新資料。

        3.2.2 了解memcached的記憶體存儲

        1) Slab Allocation機制:整理記憶體以便重複使用

        Slab Allocator的基本原理是按照預先規定的大小,将配置設定的記憶體分割成特定長度的塊, 以完全解決記憶體碎片問題。Slab Allocation的原理相當簡單。 将配置設定的記憶體分割成各種尺寸的塊(chunk), 并把尺寸相同的塊分成組(chunk的集合),如下圖:

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

         2) Slab Allocation的主要術語

  • Page:配置設定給Slab的記憶體空間,預設是1MB。配置設定給Slab之後根據slab的大小切分成chunk。
  • Chunk:用于緩存記錄的記憶體空間。
  • Slab Class:特定大小的chunk的組。

        3) 使用Growth Factor進行調優

        memcached在啟動時指定 Growth Factor因子(通過-f選項), 就可以在某種程度上控制slab之間的差異。預設值為1.25。 但是,在該選項出現之前,這個因子曾經固定為2,稱為“powers of 2”政策。

$ memcached -f 2 -vv
下面是啟動後的verbose輸出:
slab class   1: chunk size    128 perslab  8192
slab class   2: chunk size    256 perslab  4096
slab class   3: chunk size    512 perslab  2048
slab class   4: chunk size   1024 perslab  1024
slab class   5: chunk size   2048 perslab   512
slab class   6: chunk size   4096 perslab   256
slab class   7: chunk size   8192 perslab   128
slab class   8: chunk size  16384 perslab    64
slab class   9: chunk size  32768 perslab    32
slab class  10: chunk size  65536 perslab    16
slab class  11: chunk size 131072 perslab     8
slab class  12: chunk size 262144 perslab     4
slab class  13: chunk size 524288 perslab     2
可見,從128位元組的組開始,組的大小依次增大為原來的2倍。 這樣設定的問題是,slab之間的差别比較大,有些情況下就相當浪費記憶體。 是以,為盡量減少記憶體浪費,兩年前追加了growth factor這個選項
           
預設設定(f=1.25)時的輸出(篇幅所限,這裡隻寫到第10組):
slab class   1: chunk size     88 perslab 11915
slab class   2: chunk size    112 perslab  9362
slab class   3: chunk size    144 perslab  7281
slab class   4: chunk size    184 perslab  5698
slab class   5: chunk size    232 perslab  4519
slab class   6: chunk size    296 perslab  3542
slab class   7: chunk size    376 perslab  2788
slab class   8: chunk size    472 perslab  2221
slab class   9: chunk size    592 perslab  1771
slab class  10: chunk size    744 perslab  1409
可見,組間差距比因子為2時小得多,更适合緩存幾百位元組的記錄。 從上面的輸出結果來看,可能會覺得有些計算誤差, 這些誤差是為了保持位元組數的對齊而故意設定的
           

        3.2.3 memcached的删除機制和發展方向

        1) 資料不會真正從memcached中消失

        memcached不會釋放已配置設定的記憶體。記錄逾時後,用戶端就無法再看見該記錄(invisible,透明), 其存儲空間即可重複使用。

        memcached内部不會監視記錄是否過期,而是在get時檢視記錄的時間戳,檢查記錄是否過期。 這種技術被稱為lazy(惰性)expiration。是以,memcached不會在過期監視上耗費CPU時間。

        2) LRU:從緩存中有效删除資料的原理

        memcached會優先使用已逾時的記錄的空間,但即使如此,也會發生追加新記錄時空間不足的情況, 此時就要使用名為 Least Recently Used(LRU)機制來配置設定空間。 顧名思義,這是删除“最近最少使用”的記錄的機制。 是以,當memcached的記憶體空間不足時(無法從slab class 擷取到新的空間時),就從最近未被使用的記錄中搜尋,并将其空間配置設定給新的記錄。

#有些情況下LRU機制反倒會造成麻煩。memcached啟動時通過“-M”參數可以禁止LRU,如下所示:
#小寫的“-m”選項是用來指定最大記憶體大小的。不指定具體數值則使用預設值64MB。
#指定“-M”參數啟動後,記憶體用盡時memcached會傳回錯誤。 
$ memcached -M -m 1024
           

         3) memcached的最新發展方向

  • 二進制協定的策劃和實作:使用二進制協定的理由是它不需要文本協定的解析處理,使得原本高速的memcached的性能更上一層樓, 還能減少文本協定的漏洞
  • 外部引擎支援:世界上有許多memcached的派生軟體,其理由是希望永久儲存資料、實作資料備援等, 即使犧牲一些性能也在所不惜。我在開發memcached之前,在mixi的研發部也曾經 考慮過重新發明memcached。外部引擎的加載機制能封裝memcached的網絡功能、事件處理等複雜的處理。 是以,現階段通過強制手段或重新設計等方式使memcached和存儲引擎合作的困難 就會煙消雲散,嘗試各種引擎就會變得輕而易舉了。

        3.2.4 memcached的分布式算法

        1) memcached的分布式

         memcached雖然稱為“分布式”緩存伺服器,但伺服器端并沒有“分布式”功能。 伺服器端僅包括 第2次、 第3次 前坂介紹的記憶體存儲功能,其實作非常簡單。 memcached的分布式,則是完全由用戶端程式庫實作的。 這種分布式是memcached的最大特點。

        2)分布式算法

  • 根據伺服器台數的餘數進行分散:求得鍵的整數哈希值,再除以伺服器台數,根據其餘數來選擇伺服器。餘數計算的方法簡單,資料的分散性也相當優秀,但也有其缺點。 那就是當添加或移除伺服器時,緩存重組的代價相當巨大。 添加伺服器後,餘數就會産生巨變,這樣就無法擷取與儲存時相同的伺服器, 進而影響緩存的命中率。
  • memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”
  • Consistent Hashing:首先求出memcached伺服器(節點)的哈希值, 并将其配置到0~2的32次方的圓(continuum)上。 然後用同樣的方法求出存儲資料的鍵的哈希值,并映射到圓上。 然後從資料映射到的位置開始順時針查找,将資料儲存到找到的第一個伺服器上。 如果超過2的32次方仍然找不到伺服器,就會儲存到第一台memcached伺服器上。隻有在continuum上增加伺服器的地點逆時針方向的 第一台伺服器上的鍵會受到影響。
  • memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

    3.3 memcached的安裝    

     1)memcached依賴libevent,首先檢查libevent是否已經安裝

ls -al /usr/local/lib|grep libevent
           

     2)在http://libevent.org/ 下載下傳libevent-2.0.21-stable.tar.gz放置于/opt下

wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
           

     3)解壓libevent-2.0.21-stable.tar.gz

cd /opt
tar -zxvf libevent-2.0.21-stable.tar.gz
           

     4)安裝libevent,這裡都是預設安裝在目錄/usr/local/lib

cd /opt/libevent-2.0.21-stable
./configure
make
make install
           

     5)再次檢查libevent是否已經安裝

[[email protected] libevent-2.0.21-stable]# ls -al /usr/local/lib|grep libevent
lrwxrwxrwx   1 root root      21 May 14 17:47 libevent-2.0.so.5 -> libevent-2.0.so.5.1.9
-rwxr-xr-x   1 root root  968442 May 14 17:47 libevent-2.0.so.5.1.9
-rw-r--r--   1 root root 1571130 May 14 17:47 libevent.a
lrwxrwxrwx   1 root root      26 May 14 17:47 libevent_core-2.0.so.5 -> libevent_core-2.0.so.5.1.9
-rwxr-xr-x   1 root root  585057 May 14 17:47 libevent_core-2.0.so.5.1.9
-rw-r--r--   1 root root  977914 May 14 17:47 libevent_core.a
-rwxr-xr-x   1 root root     976 May 14 17:47 libevent_core.la
lrwxrwxrwx   1 root root      26 May 14 17:47 libevent_core.so -> libevent_core-2.0.so.5.1.9
lrwxrwxrwx   1 root root      27 May 14 17:47 libevent_extra-2.0.so.5 -> libevent_extra-2.0.so.5.1.9
-rwxr-xr-x   1 root root  404772 May 14 17:47 libevent_extra-2.0.so.5.1.9
-rw-r--r--   1 root root  593288 May 14 17:47 libevent_extra.a
-rwxr-xr-x   1 root root     983 May 14 17:47 libevent_extra.la
lrwxrwxrwx   1 root root      27 May 14 17:47 libevent_extra.so -> libevent_extra-2.0.so.5.1.9
-rwxr-xr-x   1 root root     941 May 14 17:47 libevent.la
lrwxrwxrwx   1 root root      29 May 14 17:47 libevent_openssl-2.0.so.5 -> libevent_openssl-2.0.so.5.1.9
-rwxr-xr-x   1 root root   94209 May 14 17:47 libevent_openssl-2.0.so.5.1.9
-rw-r--r--   1 root root  131836 May 14 17:47 libevent_openssl.a
-rwxr-xr-x   1 root root    1012 May 14 17:47 libevent_openssl.la
lrwxrwxrwx   1 root root      29 May 14 17:47 libevent_openssl.so -> libevent_openssl-2.0.so.5.1.9
lrwxrwxrwx   1 root root      30 May 14 17:47 libevent_pthreads-2.0.so.5 -> libevent_pthreads-2.0.so.5.1.9
-rwxr-xr-x   1 root root   18462 May 14 17:47 libevent_pthreads-2.0.so.5.1.9
-rw-r--r--   1 root root   18702 May 14 17:47 libevent_pthreads.a
-rwxr-xr-x   1 root root    1004 May 14 17:47 libevent_pthreads.la
lrwxrwxrwx   1 root root      30 May 14 17:47 libevent_pthreads.so -> libevent_pthreads-2.0.so.5.1.9
lrwxrwxrwx   1 root root      21 May 14 17:47 libevent.so -> libevent-2.0.so.5.1.9
[[email protected] libevent-2.0.21-stable]# 
           

     6)下載下傳memcached-1.4.25.tar.gz并放置于目錄/opt下

wget http://memcached.org/files/memcached-1.4.25.tar.gz
           

     7)解壓memcached-1.4.25.tar.gz

cd /opt
tar -zxvf memcached-1.4.25.tar.gz
           

     8)安裝memcached-1.4.25.tar.gz,預設安裝在/usr/local/bin/memcached

cd /opt/memcached-1.4.25
./configure
make
make test
make install
           

    遇到錯誤:

./sizes
./sizes: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory
make: *** [test] Error 127
           

   需要制定libevent安裝目錄

cd /opt/memcached-1.4.25
./configure -with-libevent=/usr/local/lib
make
make test
make install
           
[[email protected] memcached-1.4.25]# make install
make  install-recursive
make[1]: Entering directory `/opt/memcached-1.4.25'
Making install in doc
make[2]: Entering directory `/opt/memcached-1.4.25/doc'
make  install-am
make[3]: Entering directory `/opt/memcached-1.4.25/doc'
make[4]: Entering directory `/opt/memcached-1.4.25/doc'
make[4]: Nothing to be done for `install-exec-am'.
 /bin/mkdir -p '/usr/local/share/man/man1'
 /usr/bin/install -c -m 644 memcached.1 '/usr/local/share/man/man1'
make[4]: Leaving directory `/opt/memcached-1.4.25/doc'
make[3]: Leaving directory `/opt/memcached-1.4.25/doc'
make[2]: Leaving directory `/opt/memcached-1.4.25/doc'
make[2]: Entering directory `/opt/memcached-1.4.25'
make[3]: Entering directory `/opt/memcached-1.4.25'
 /bin/mkdir -p '/usr/local/bin'
  /usr/bin/install -c memcached '/usr/local/bin'
 /bin/mkdir -p '/usr/local/include/memcached'
 /usr/bin/install -c -m 644 protocol_binary.h '/usr/local/include/memcached'
make[3]: Leaving directory `/opt/memcached-1.4.25'
make[2]: Leaving directory `/opt/memcached-1.4.25'
make[1]: Leaving directory `/opt/memcached-1.4.25'
[[email protected] memcached-1.4.25]# 
           

     9)檢測memcached是否安裝成功

[[email protected] bin]#  ls -al /usr/local/bin/mem*
-rwxr-xr-x 1 root root 360338 May 14 18:04 /usr/local/bin/memcached
[[email protected] bin]# 
           

     10)啟動Memcached服務

背景模式啟動 /usr/local/bin/memcached -d -m 10 -u root -l 192.168.202.131 -p 12000 -c 256 -P /tmp/memcached.pid

調試模式啟動 [[email protected] networksettings]# /usr/local/bin/memcached -vv -m 10 -u root -l 192.168.202.131 -p 12000 -c 256 -P /tmp/memcached.pid

slab class 1: chunk size 96 perslab 10922

slab class 2: chunk size 120 perslab 8738

slab class 3: chunk size 152 perslab 6898

slab class 4: chunk size 192 perslab 5461

slab class 5: chunk size 240 perslab 4369

slab class 6: chunk size 304 perslab 3449

slab class 7: chunk size 384 perslab 2730

slab class 8: chunk size 480 perslab 2184

slab class 9: chunk size 600 perslab 1747

slab class 10: chunk size 752 perslab 1394

slab class 11: chunk size 944 perslab 1110

slab class 12: chunk size 1184 perslab 885

slab class 13: chunk size 1480 perslab 708

slab class 14: chunk size 1856 perslab 564

slab class 15: chunk size 2320 perslab 451

slab class 16: chunk size 2904 perslab 361

slab class 17: chunk size 3632 perslab 288

slab class 18: chunk size 4544 perslab 230

slab class 19: chunk size 5680 perslab 184

slab class 20: chunk size 7104 perslab 147

slab class 21: chunk size 8880 perslab 118

slab class 22: chunk size 11104 perslab 94

slab class 23: chunk size 13880 perslab 75

slab class 24: chunk size 17352 perslab 60

slab class 25: chunk size 21696 perslab 48

slab class 26: chunk size 27120 perslab 38

slab class 27: chunk size 33904 perslab 30

slab class 28: chunk size 42384 perslab 24

slab class 29: chunk size 52984 perslab 19

slab class 30: chunk size 66232 perslab 15

slab class 31: chunk size 82792 perslab 12

slab class 32: chunk size 103496 perslab 10

slab class 33: chunk size 129376 perslab 8

slab class 34: chunk size 161720 perslab 6

slab class 35: chunk size 202152 perslab 5

slab class 36: chunk size 252696 perslab 4

slab class 37: chunk size 315872 perslab 3

slab class 38: chunk size 394840 perslab 2

slab class 39: chunk size 493552 perslab 2

slab class 40: chunk size 616944 perslab 1

slab class 41: chunk size 771184 perslab 1

slab class 42: chunk size 1048576 perslab 1

<26 server listening (auto-negotiate)

<27 send buffer was 229376, now 268435456

<27 server listening (udp)

<29 server listening (udp)

<30 server listening (udp)

<28 server listening (udp) 參數說明  -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

-vv 用very vrebose模式啟動,調試資訊和錯誤輸出到控制台

     啟動時如果遇到如下錯誤:

[[email protected] bin]# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.202.131 -p 12000 -c 256 -P /tmp/memcached.pid
/usr/local/bin/memcached: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory
[[email protected] bin]#
           

     解決辦法如下:

#首先查下memcached的加載庫位置
LD_DEBUG=libs memcached -v 
#針對缺失的庫在加載目錄建立個軟連接配接
mkdir -p /usr/local/lib/lib/tls/x86_64
cd /usr/local/lib/lib/tls/x86_64
ln -s /usr/local/lib/libevent-2.0.so.5 /usr/local/lib/lib/tls/x86_64/libevent-2.0.so.5
           

     再次啟動就可以了

    11)關閉memcached

    方法一:

cat /tmp/memcached.pid|xargs kill -9
           

    方法二:

#先查程序号
ps -ef|grep memcached
#然後殺掉程序
kill -9 程序号
           

     12)測試memcached

    telnet在centos下的安裝http://blog.csdn.net/jiguang0455/article/details/8670142

telnet 192.168.202.131 12000
Trying 192.168.202.131...
Connected to 192.168.202.131 (192.168.202.131).
Escape character is '^]'.
set key1 0 60 4
zhou
STORED
get key1
VALUE key1 0 4
zhou
END
           

    3.4 memcached java API使用

         3.4.1 通過Memcached-Java-Client用戶端連接配接memcached

        Memcached-Java-Client源代碼位址:https://github.com/gwhalin/Memcached-Java-Client

        Memcached-Java-Client維基文檔位址: https://github.com/gwhalin/Memcached-Java-Client/wiki

        1)Memcached-Java-Client相關maven位址,在https://github.com/gwhalin/Memcached-Java-Client/wiki中

HOWTO中寫道 3.0.x released, features = 2.6.x, but you can now get it from maven central, please notice:

since the domain danga.com is no more under our control(according to maven’s policy, the domain should be under authors’ control), the package name was replaced with “whalin.com”. If you don’t intend to rebuild your app, please use 2.6.×.

search “com.whalin” or “memcached java client” in search.maven.org, and you will find 3.0.×.

     在maven中央倉庫http://search.maven.org/查詢結果如下:

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

        2)eclipse中建立maven工程,然後在pom.xml中配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.test</groupId>
	<artifactId>ehcachetest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ehcachetest</name>
	<packaging>jar</packaging>

	<properties>
		<!-- 這裡定義所有的版本資訊,友善版本統一管理 -->
		<ehcache.version>3.0.1</ehcache.version>
		<memcached.version>3.0.2</memcached.version>
	</properties>

	<dependencies>
		<!-- 這裡添加所有的依賴包 -->
		<!-- ehcache -->
		<dependency>
			<groupId>org.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>${ehcache.version}</version>
		</dependency>
		
		<!-- Memcached-Java-Client -->
		<dependency>
			<groupId>com.whalin</groupId>
			<artifactId>Memcached-Java-Client</artifactId>
			<version>${memcached.version}</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<!-- 這裡添加所有插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.4.3</version>
				<configuration>
					<!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
           

     這裡我需要現在我的虛拟機中啟動三個memcached節點

腳本如下: /usr/local/bin/memcached -d -m 10 -u root -l 192.168.202.131 -p 12000 -c 64 -P /tmp/memcached1.pid

/usr/local/bin/memcached -d -m 10 -u root -l 192.168.202.131 -p 12001 -c 64 -P /tmp/memcached2.pid

/usr/local/bin/memcached -d -m 10 -u root -l 192.168.202.131 -p 12002 -c 64 -P /tmp/memcached3.pid

package com.memcached.test;
import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;
public class MyClass {
	//建立單例
	protected static MemCachedClient mcc = new MemCachedClient();

	//初始化連接配接池
	static {
		//memcached伺服器清單和各伺服器權重
		String[] servers =
			{
			  "192.168.202.131:12000",
			  "192.168.202.131:12001",
			  "192.168.202.131:12002"
			};
		Integer[] weights = { 3, 3, 2 };

		//擷取連接配接池
		SockIOPool pool = SockIOPool.getInstance();

		//設定服務清單和權重
		pool.setServers( servers );
		pool.setWeights( weights );

		// 設定連接配接池配置資訊
		// 初始化5連接配接,最小5連接配接,最大250連接配接
		// 設定最大逾時時間為6小時
		pool.setInitConn( 5 );
		pool.setMinConn( 5 );
		pool.setMaxConn( 250 );
		pool.setMaxIdle( 1000 * 60 * 60 * 6 );

		// 設定連接配接池主線程休眠時間為30秒
		pool.setMaintSleep( 30 );

		// 設定TCP連接配接資訊set some TCP settings
		// 禁用nagle
		// 設定讀逾時時間為3秒
		// 禁用連接配接逾時
		pool.setNagle( false );
		pool.setSocketTO( 3000 );
		pool.setSocketConnectTO( 0 );

		// 這裡開始初始化連接配接池
		pool.initialize();


		// 這裡是一些壓縮方面設定,不過在2.0.2版本中已經抛棄不再使用
		// compress anything larger than 64k
		// mcc.setCompressEnable( true );
		// mcc.setCompressThreshold( 64 * 1024 );
	}

	// 隻要上面設定OK後,就能根據MemCachedClient調用memcached API
	public static void main(String[] args) {
        mcc.set( "foo", "This is a test String" );
		String bar = (String) mcc.get( "foo" );
		System.out.println(bar);
	}
}
           

     如果你需要讓你的memcached伺服器對Java, PHP, Perl等等用戶端提供服務,你需要配置如下設定:

// 設定HASH算法,預設是SockIOPool.NATIVE_HASH
		pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH );

		// 是否将基本類型Boolean,Byte,String,Character,StringBuffer,StringBuilder,Short,Long,Double,Float,Date,Integer轉換為String存儲,預設是不轉換的,設定轉換的目的是節省空間和資源
		// 對于非基本類型,這個參數設定是不起作用的
		mcc.setPrimitiveAsString( true );

		// 設定是否對key進行URL ENCODE,預設java用戶端是進行URL ENCODE的
		// 其他用戶端是預設不進行URL ENCODE的
		mcc.setSanitizeKeys( false );
           

     關于memcached叢集時候的故障轉移參數設定

//叢集中設定池的故障轉移的标志
//當一個memcached伺服器失效的時候用戶端預設會failover另一個服務去
//如果失效的伺服器恢複運作,用戶端會failback到原來連接配接的伺服器
//一般不要使用該功能
	pool.setFailover( false );
	pool.setFailback( false );
           

          3.4.2 通過alisoft-xplatform-asf-cache用戶端連接配接memcached

         alisoft-xplatform-asf-cache是阿裡軟體的架構師岑文初進行封裝的裡面的注釋都是中文的。目前沒找到阿裡正式釋出該開源項目,也沒在maven中央倉庫找到相關資訊,隻在網上找到關于alisoft-xplatform-asf-cache的源代碼,這裡自己建了個maven工程,maven工程源代碼詳見附件alisoft-xplatform-asf-cache-src.zip(注意檔案是GBK編碼的,eclipse中自己設定下,無意冒犯阿裡,這裡實在是找不到其相關URL連接配接)

        1)先自己下載下傳alisoft-xplatform-asf-cache-src.zip将其install到本地maven倉庫,然後pom.xml配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.test</groupId>
	<artifactId>ehcachetest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ehcachetest</name>
	<packaging>jar</packaging>

	<properties>
		<!-- 這裡定義所有的版本資訊,友善版本統一管理 -->
		<ehcache.version>3.0.1</ehcache.version>
		<memcached.version>3.0.2</memcached.version>
		<alisoft.memcached.version>2.5.1</alisoft.memcached.version>
	</properties>

	<dependencies>
		<!-- 這裡添加所有的依賴包 -->
		<!-- ehcache -->
		<dependency>
			<groupId>org.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>${ehcache.version}</version>
		</dependency>
		
		<!-- Memcached-Java-Client -->
		<dependency>
			<groupId>com.whalin</groupId>
			<artifactId>Memcached-Java-Client</artifactId>
			<version>${memcached.version}</version>
		</dependency>
		<dependency>
			<groupId>com.alisoft</groupId>
			<artifactId>alisoft-xplatform-asf-cache</artifactId>
			<version>${alisoft.memcached.version}</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<!-- 這裡添加所有插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.4.3</version>
				<configuration>
					<!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
           

         2)配置alisoft-xplatform-asf-cache需要的XML檔案alisoft-memcached.xml

<?xml version="1.0" encoding="UTF-8"?>
<memcached>
	<!-- 
		name 屬性是程式中使用Cache的唯一辨別
		socketpool 屬性将會關聯到後面的socketpool配置; 
	-->
	<client name="client_test_name" compressEnable="true" defaultEncoding="UTF-8"
		socketpool="poo_test_name">
		<!-- 可選,用來處理出錯情況 -->
		<errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler
		</errorHandler>
	</client>

	<!-- 
		name          屬性和client 配置中的socketpool 屬性相關聯
		maintSleep  屬性是背景線程管理SocketIO池的檢查間隔時間,如果設定為0,則表明不需要背景線程維護SocketIO線程池,預設需要管理
		socketTO    屬性是Socket操作逾時配置,機關ms。 aliveCheck 屬性表示在使用Socket以前是否先檢查Socket狀态
	 -->
	<socketpool name="poo_test_name" maintSleep="5000" socketTO="3000"
		failover="true" aliveCheck="true" initConn="5" minConn="5" maxConn="250"
		nagle="false">
		<!-- 設定memcache服務端執行個體位址.多個位址用","隔開 -->
		<servers>192.168.202.131:12000,192.168.202.131:12001,192.168.202.131:12002</servers>
		<!-- 
			可選配置。表明了上面設定的伺服器執行個體的Load權重. 
			例如 <weights>3,3,4</weights>  表示30% load 在 192.168.202.131:12000
			                                                   , 30% load 在 192.168.202.131:12001
			                                                   , 40% load 在 192.168.202.131:12002
		-->
			<weights>3,3,4</weights> 
	</socketpool>
</memcached>  
           

         3)測試java代碼如下:

package com.memcached.test;

import com.alisoft.xplatform.asf.cache.ICacheManager;
import com.alisoft.xplatform.asf.cache.IMemcachedCache;
import com.alisoft.xplatform.asf.cache.memcached.CacheUtil;
import com.alisoft.xplatform.asf.cache.memcached.MemcachedCacheManager;

public class AlisoftMemcachedTest {
	public static void main(String[] args) {
		ICacheManager<IMemcachedCache> manager;
		manager = CacheUtil.getCacheManager(IMemcachedCache.class, MemcachedCacheManager.class.getName());
		manager.setConfigFile("alisoft-memcached.xml");
		manager.start();
		try {
			IMemcachedCache cache = manager.getCache("client_test_name");
			cache.put("key", "value");
			System.out.println(cache.get("key"));
		} finally {
			manager.stop();
		}
	}
}
           

     3.5 利用magent搭建memcached叢集

    之前例子中使用memcached時緩存資料分布圖如下:

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

    上面的問題是如果中間一台機器當機,那麼緩存的部分資料就會丢失了,如下

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

        magent的出現正是為了解決這個問題,

    3.5.1 magent介紹

        magent是一款開源的Memcached代理伺服器軟體。

        magent項目網址為:http://code.google.com/p/memagent/ 

        magent下載下傳位址:https://code.google.com/archive/p/memagent/downloads

        magent代理memcached實作主從備份來保證緩存資料完好無損,而且magent還可以作為從繼續使用。

    3.5.2 magent安裝

    這裡完全參考http://www.php-note.com/article/detail/820,比較詳細,這裡說下自己真實安裝遇到的問題。

     1)主要安裝步驟

#這裡安裝版本為magent-0.6,先建立個目錄放置下載下傳的安裝檔案
mkdir -p /opt/magent-0.6
cd /opt/magent-0.6
#下載下傳
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/memagent/magent-0.6.tar.gz
#解壓
tar -zxvf magent-0.6.tar.gz
#安裝
/sbin/ldconfig
sed -i "s#LIBS = -levent#LIBS = -levent -lm#g" Makefile
cd /opt/magent-0.6
make
#安裝完後拷貝
cp /opt/magent-0.6/magent /usr/bin/magent
           

     2)執行make是報錯1

gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
magent.c: In function 'writev_list':
magent.c:729: error: 'SSIZE_MAX' undeclared (first use in this function)
magent.c:729: error: (Each undeclared identifier is reported only once
magent.c:729: error: for each function it appears in.)
make: *** [magent.o] Error 1
           

     解決辦法:編輯檔案/opt/magent-0.6/ketama.h,在開頭添加如下内容:

#ifndef SSIZE_MAX 
#define SSIZE_MAX 32767 
#endif 
           

     3)執行make遇到的錯誤2

gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o ketama.o ketama.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a 
gcc: /usr/lib64/libevent.a: No such file or directory
gcc: /usr/lib64/libm.a: No such file or directory
           

     解決辦法:

    因為我之前libevent是安裝在/usr/local/lib,是以缺檔案的話就執行下面指令建立了個軟連接配接

ln -s /usr/local/lib/libevent*  /usr/lib64/
           

     4)執行make報錯3

gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a 
gcc: /usr/lib64/libm.a: No such file or directory
make: *** [magent] Error 1
           

     文章中說是要重新安裝glibc glibc-devel,需要執行yum install -y glibc glibc-devel ,但我的不是這個問題

,最後是通過如下方式解決的

cp /usr/lib64/libm.so /usr/lib64/libm.a
           

     5)執行make報錯4

gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a 
/usr/lib64/libevent.a(event.o): In function `detect_monotonic':
event.c:(.text+0xc79): undefined reference to `clock_gettime'
/usr/lib64/libevent.a(event.o): In function `gettime':
event.c:(.text+0xd60): undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
make: *** [magent] Error 1
           

     解決辦法,編輯檔案/opt/magent-0.6/Makefile,修改前内容如下:

ARCH := $(shell uname -m)
X64 = x86_64
CC = gcc
PROGS = magent
ifeq ($(ARCH), $(X64))
        M64 = -m64
        LIBS = /usr/lib64/libevent.a /usr/lib64/libm.a 
else
        LIBS = -levent -lm -lm -L/usr/local/lib
endif

CFLAGS = -Wall -g -O2 -I/usr/local/include $(M64)

all: $(PROGS)

STPROG = magent.o ketama.o

ketama.o: ketama.c ketama.h
        $(CC) $(CFLAGS) -c -o [email protected] ketama.c

magent.o: magent.c ketama.h
        $(CC) $(CFLAGS) -c -o $@ magent.c

magent: $(STPROG)
        $(CC) $(CFLAGS) -o [email protected] $^ $(LIBS)

clean:
        rm -f *.o *~ $(PROGS)
           

     編輯檔案/opt/magent-0.6/Makefile,修改後内容如下:

ARCH := $(shell uname -m)
X64 = x86_64
CC = gcc
PROGS = magent
ifeq ($(ARCH), $(X64))
        M64 = -m64
        LIBS = /usr/lib64/libevent.a /usr/lib64/libm.a 
else
        LIBS = -levent -lm -lm -L/usr/local/lib
endif

CFLAGS = -lrt -Wall -g -O2 -I/usr/local/include $(M64)

all: $(PROGS)

STPROG = magent.o ketama.o

ketama.o: ketama.c ketama.h
        $(CC) $(CFLAGS) -c -o [email protected] ketama.c

magent.o: magent.c ketama.h
        $(CC) $(CFLAGS) -c -o [email protected] magent.c

magent: $(STPROG)
        $(CC) $(CFLAGS) -o [email protected] $^ $(LIBS)

clean:
        rm -f *.o *~ $(PROGS)
           

     6)最後執行make成功,記錄如下:

[[email protected] magent-0.6]# make
gcc -lrt -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a 
[[email protected] magent-0.6]# pwd
/opt/magent-0.6
[[email protected] magent-0.6]# ll
total 624
-rw-rw-r-- 1 hadoop mysql  12822 Apr 10  2010 ketama.c
-rw-rw-r-- 1 hadoop mysql    393 May 15 21:08 ketama.h
-rw-r--r-- 1 root   root   23616 May 15 21:08 ketama.o
-rwxr-xr-x 1 root   root  394126 May 15 21:24 magent
-rw-r--r-- 1 root   root   17257 May 15 20:52 magent-0.6.tar.gz
-rw-rw-r-- 1 hadoop mysql  54813 Apr 15  2010 magent.c
-rw-r--r-- 1 root   root  112200 May 15 21:08 magent.o
-rw-rw-r-- 1 hadoop mysql    510 May 15 21:24 Makefile
[[email protected] magent-0.6]#
           

     7)magent指令

magent指令詳解 -h this message

-u uid

-g gid

-p port, default is 11211. (0 to disable tcp support)

-s ip:port, set memcached server ip and port

-b ip:port, set backup memcached server ip and port

-l ip, local bind ip address, default is 0.0.0.0

-n number, set max connections, default is 4096

-D do not go to background

-k use ketama key allocation algorithm

-f file, unix socket path to listen on. default is off

-i number, max keep alive connections for one memcached server, default is 20

-v verbose

    3.5.3 magent搭建的memcached叢集執行個體

    這裡參見的文章為:http://www.2cto.com/os/201506/406932.html

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

工作流程: 1.magent1,magent2接受寫請求,将key分别寫入mecached1-mecached4中,同時也将key寫入從memcached上,也就是magent3上,magent3再分别寫入mecached5,mecached6中;主和從都是用的同一個配置設定算法

2.magent1,magent2接受讀請求,将分别向主memcached中進行讀取,而不想從memcached中讀取;

3.一旦mecached1-mecached4中有一個memcached宕掉,此時magent1和magent2将向從memcached,也就是magent3中讀取資料,達到緩存資料不丢失的效果;

4.當主中的memcache恢複後,将再次加入主memcached中,此時magent1和magent2将不會向從memcached中讀資料了,但是寫仍正常進行

啟動腳本 #memcached1-memcached6節點服務啟動

memcached -d -m 10 -u root -l 192.168.202.131 -p 12001 -c 102400 -P /tmp/memcached1.pid

memcached -d -m 10 -u root -l 192.168.202.131 -p 12002 -c 102400 -P /tmp/memcached2.pid

memcached -d -m 10 -u root -l 192.168.202.131 -p 12003 -c 102400 -P /tmp/memcached3.pid

memcached -d -m 10 -u root -l 192.168.202.131 -p 12004 -c 102400 -P /tmp/memcached4.pid

memcached -d -m 10 -u root -l 192.168.202.131 -p 12005 -c 102400 -P /tmp/memcached5.pid

memcached -d -m 10 -u root -l 192.168.202.131 -p 12006 -c 102400 -P /tmp/memcached6.pid

#magent3代理服務啟動

/usr/bin/magent -u root -n 102400 -l 192.168.202.131 -p 13003 -s 192.168.202.131:12005 -s 192.168.202.131:12006

#magent1代理服務啟動

/usr/bin/magent -u root -n 102400 -l 192.168.202.131 -p 13001 -s 192.168.202.131:12001 -s 192.168.202.131:12002 -s 192.168.202.131:12003 -s 192.168.202.131:12004 -b 192.168.202.131:13003

#magent2代理服務啟動

/usr/bin/magent -u root -n 102400 -l 192.168.202.131 -p 13002 -s 192.168.202.131:12001 -s 192.168.202.131:12002 -s 192.168.202.131:12003 -s 192.168.202.131:12004 -b 192.168.202.131:13003

     啟動後檢視memcached服務如下:

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

     啟動後檢視magent服務如下:

memcached完全剖析ehcache memcached redis 緩存技術總結1.前言ehcache memcached redis 緩存技術總結2.Ehcache3.Memcached4.redis        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

     3.5.4 java API調用magent搭建的memcached叢集服務

與之前不使用magent的差別  程式上的主要差別就是,以前提供的是memcached伺服器的位址清單,現在隻需提供magent伺服器的位址清單就行了

     java代碼如下:

package com.memcached.test;
import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;
public class MagentMemCachedClientTest {
	//建立單例  
    protected static MemCachedClient mcc = new MemCachedClient();  
  
    //初始化連接配接池  
    static {  
        //memcached伺服器清單和各伺服器權重 ,這裡現在配置magent代理伺服器位址清單
        String[] servers =  
            {  
              "192.168.202.131:13001",  
              "192.168.202.131:13002" 
            };  
        Integer[] weights = { 5, 5};  
  
        //擷取連接配接池  
        SockIOPool pool = SockIOPool.getInstance();  
  
        //設定服務清單和權重  
        pool.setServers( servers );  
        pool.setWeights( weights );  
  
        // 設定連接配接池配置資訊  
        // 初始化5連接配接,最小5連接配接,最大250連接配接  
        // 設定最大逾時時間為6小時  
        pool.setInitConn( 5 );  
        pool.setMinConn( 5 );  
        pool.setMaxConn( 250 );  
        pool.setMaxIdle( 1000 * 60 * 60 * 6 );  
  
        // 設定連接配接池主線程休眠時間為30秒  
        pool.setMaintSleep( 30 );  
  
        // 設定TCP連接配接資訊set some TCP settings  
        // 禁用nagle  
        // 設定讀逾時時間為3秒  
        // 禁用連接配接逾時  
        pool.setNagle( false );  
        pool.setSocketTO( 3000 );  
        pool.setSocketConnectTO( 0 );  
  
        // 這裡開始初始化連接配接池  
        pool.initialize();  
  
        /*        
        	alg=0,SockIOPool.NATIVE_HASH     使用String.hashCode()獲得hash code,該方法依賴JDK,可能和其他用戶端不相容,建議不使用 
        	alg=1,SockIOPool.OLD_COMPAT_HASH 使用original 相容hash算法,相容其他用戶端 
        	alg=2,SockIOPool.NEW_COMPAT_HASH 使用CRC32相容hash算法,相容其他用戶端,性能優于original算法 
        	alg=3,SockIOPool.CONSISTENT_HASH 使用MD5 hash算法 
        	采用前三種hash算法的時候,查找cache伺服器使用餘數方法。采用最後一種hash算法查找cache服務時使用consistent方法。 
        */
        pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH ); 
        // 這裡是一些壓縮方面設定,不過在2.0.2版本中已經抛棄不再使用  
        // compress anything larger than 64k  
        // mcc.setCompressEnable( true );  
        // mcc.setCompressThreshold( 64 * 1024 );  
    }  
  
    // 隻要上面設定OK後,就能根據MemCachedClient調用memcached API  
    public static void main(String[] args) {  
        mcc.set( "foo", "This is a test String" );  
        String bar = (String) mcc.get( "foo" );  
        System.out.println(bar);  
    }  
}
           

4.redis

    4.1 redis介紹 

        redis是一個key-value存儲系統。和Memcached類似,它支援存儲的value類型相對更多,包括string(字元串)、list(連結清單)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些資料類型都支援push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,為了保證效率,資料都是緩存在記憶體中。差別的是redis會周期性的把更新的資料寫入磁盤或者把修改操作寫入追加的記錄檔案,并且在此基礎上實作了master-slave(主從)同步。

        Redis 是一個高性能的key-value資料庫。 redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部 分場合可以對關系資料庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等用戶端,使用很友善。[1]

Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複制。存盤可以有意無意的對資料進行寫操作。由于完全實作了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道并接收主伺服器完整的消息釋出記錄。同步對讀取操作的可擴充性和資料備援很有幫助。

        redis的官網位址,非常好記,是redis.io。(特意查了一下,域名字尾io屬于國家域名,是british Indian Ocean territory,即英屬印度洋領地)

        目前,Vmware在資助着redis項目的開發和維護。 

    4.2 redis叢集安裝

        1)下載下傳、解壓并編譯redis

cd /opt
wget http://download.redis.io/releases/redis-3.2.0.tar.gz
tar -zxvf redis-3.2.0.tar.gz
cd /opt/redis-3.2.0
make
make install
           

         在centos 7下遇到無法正常編譯問題,主要是gcc和tcl未安裝導緻,報錯是“/bin/sh: cc: command not found”和“You need tcl 8.5 or newer in order to run the Redis test”,解決方法是安裝一下gcc和tcl,如下:  yum -y install gcc tcl     2)修改/opt/redis-3.2.0/redis.conf中配置檔案,建立叢集配置檔案夾并将配置檔案分發到各個配置目錄 

#建立配置檔案夾目錄
mkdir -p /home/hadoopmanage/rediscluster/conf/7000
mkdir -p /home/hadoopmanage/rediscluster/conf/7001
mkdir -p /home/hadoopmanage/rediscluster/conf/7002
mkdir -p /home/hadoopmanage/rediscluster/conf/7003
mkdir -p /home/hadoopmanage/rediscluster/conf/7004
mkdir -p /home/hadoopmanage/rediscluster/conf/7005

#修改配置檔案中的下面選項
vi /opt/redis-3.2.0/redis.conf
port 7000
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

#複制配置檔案到個配置目錄
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7000
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7001
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7002
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7003
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7004
cp /opt/redis-3.2.0/redis.conf /home/hadoopmanage/rediscluster/conf/7005

#修改檔案/home/hadoopmanage/rediscluster/conf/7000/redis.conf中端口port為7000
#修改檔案/home/hadoopmanage/rediscluster/conf/7001/redis.conf中端口port為7001
#修改檔案/home/hadoopmanage/rediscluster/conf/7002/redis.conf中端口port為7002
#修改檔案/home/hadoopmanage/rediscluster/conf/7003/redis.conf中端口port為7003
#修改檔案/home/hadoopmanage/rediscluster/conf/7004/redis.conf中端口port為7004
#修改檔案/home/hadoopmanage/rediscluster/conf/7005/redis.conf中端口port為7005
           

    3)redis中提供了通過ruby腳本檔案/opt/redis-3.2.0/src/redis-trib.rb來啟動叢集,這裡首先要安裝ruby及其元件,以便後續能使用該腳本。  redis-trib.rb是redis作者開發的基于ruby的管理工具,沒有這個工具照樣能玩轉redis叢集啟動,參見我的另外一個部落格 redis cluster 非ruby方式啟動   #必要的linux庫安裝

yum -y install zlib-devel openssl-devel cmake build-essential autoconf automake libtool zlib1g-dev pkg-config libssl-dev

#安裝ruby

cd /opt

wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz

tar -zxvf ruby-2.3.1.tar.gz

cd /opt/ruby-2.3.1

./configure

make

make install

#ruby的擴充庫zlib安裝

cd /opt/ruby-2.3.1/ext/zlib

ruby ./extconf.rb

make

make install

#ruby的擴充庫openssl安裝

cd /opt/ruby-2.3.1/ext/openssl

ruby ./extconf.rb

#如果遇到報錯make: *** No rule to make target `/include/ruby.h', needed by `ossl_ssl_session.o'. Stop.

#在檔案/opt/ruby-2.3.1/ext/openssl/Makefile裡添加如下變量top_srcdir,值為ruby源代碼的根路徑/opt/ruby-2.3.1

#top_srcdir=/opt/ruby-2.3.1

make

make install

#如果遇到報錯make: *** No rule to make target `/include/ruby.h', needed by `ossl_ssl_session.o'. Stop.

#在檔案/opt/ruby-2.3.1/ext/openssl/Makefile裡添加如下變量top_srcdir,值為ruby源代碼的根路徑/opt/ruby-2.3.1

#top_srcdir=/opt/ruby-2.3.1

https://rubygems.org/

#檢測ruby環境

ruby -v

ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

#檢測rubygems

3RubyGems(簡稱 gems)是一個用于對 Ruby元件進行打包的 Ruby 打包系統。

#它提供一個分發 Ruby 程式和庫的标準格式,還提供一個管理程式包安裝的工具。

#Ruby1.9.2之後版本版本預設自帶RubyGems,如果低于這個版本的話,需要自行安裝RubyGems,

#參照這裡安裝http://storysky.blog.51cto.com/628458/1155353/

#因為我是ruby2.3.1是以不需要安裝此元件,已經自帶了

#檢查RubyGems是否安裝好的方法如下:

gem -v

2.5.1      4)執行ruby腳本,使得之前啟動的6台單獨的redis服務實作3主3從叢集服務,誰是主誰是從是ruby腳本自己決定的 

cd /opt/redis-3.2.0/src/
./redis-trib.rb  create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
           

    4.3 redis用戶端使用

[[email protected] 7005]$ cd /opt/redis-3.2.0/src/
[[email protected] src]$ redis-cli -c -p 7000
127.0.0.1:7000> set key1 value1
-> Redirected to slot [9189] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get key1
"value1"
127.0.0.1:7001> set key2 value2
-> Redirected to slot [4998] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get key2
"value2"
127.0.0.1:7000> set key1 value3
-> Redirected to slot [9189] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get key1
"value3"
127.0.0.1:7001> quit
[[email protected] src]$ 
           

    4.4 JAVA REDIS API調用

        在http://redis.io/clients#java有所有關于redis所支援的語言的用戶端API,這裡我選擇的是jedis(https://github.com/xetorthio/jedis)

        1)在maven項目的pom.xml添加如下依賴:

<!-- jedis,client for redis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>
           

        測試代碼如下:

package com.redis.test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class RedisTest {
	public static void main(String[] args) {
		Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
		// Jedis Cluster will attempt to discover cluster nodes automatically
		List<HostAndPort> serverList = new ArrayList<HostAndPort>();
		serverList.add(new HostAndPort("192.168.202.131", 7000));
		serverList.add(new HostAndPort("192.168.202.131", 7001));
		serverList.add(new HostAndPort("192.168.202.131", 7002));
		serverList.add(new HostAndPort("192.168.202.131", 7003));
		serverList.add(new HostAndPort("192.168.202.131", 7004));
		serverList.add(new HostAndPort("192.168.202.131", 7005));
		jedisClusterNodes.addAll(serverList);
		JedisCluster jc = new JedisCluster(jedisClusterNodes);
		jc.set("foo", "bar");
		System.out.println(jc.get("foo"));
	}
}
           

    按照之前搭建的叢集,會出現如下錯誤資訊:

錯誤資訊 Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: no reachable node in cluster

at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:54)

at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:113)

at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:131)

at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:30)

at redis.clients.jedis.JedisCluster.set(JedisCluster.java:60)

at com.redis.test.RedisTest.main(RedisTest.java:25)

         原因是之前我們在所有redis.conf檔案中配置了“bind 127.0.0.1” ,先更正為“192.168.202.131”,然後操作如下:

重新操作如下: #停止所有redis服務方法一  pkill redis  #停止所有redis服務方法二

ps -efww|grep redis|grep -v grep|cut -c 9-15|xargs kill -9

#删除之前緩存資料,因為是寫到磁盤了,是以這裡需要删除資料檔案

rm -rf /home/hadoopmanage/rediscluster/confdump.rdb

rm -rf /home/hadoopmanage/rediscluster/conf/*/appendonly.aof

#修改“bind 127.0.0.1”為“bind 192.168.202.131”,然後重新開機服務

cd /home/hadoopmanage/rediscluster/conf/7000/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /home/hadoopmanage/rediscluster/conf/7001/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /home/hadoopmanage/rediscluster/conf/7002/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /home/hadoopmanage/rediscluster/conf/7003/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /home/hadoopmanage/rediscluster/conf/7004/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /home/hadoopmanage/rediscluster/conf/7005/

/opt/redis-3.2.0/src/redis-server redis.conf

cd /opt/redis-3.2.0/src/

./redis-trib.rb create --replicas 1 192.168.202.131:7000 192.168.202.131:7001 192.168.202.131:7002 192.168.202.131:7003 192.168.202.131:7004 192.168.202.131:7005

         再次執行測試代碼,不會出現錯誤。

        以上所有測試代碼見附件“緩存技術總結所有測試代碼.zip”

繼續閱讀