高效緩存Memcached集成使用說明

Memcached 介紹與分析

       Memcached是一種集中式Cache,支持分佈式橫向擴展。總結幾個它的特色來理解一下它的優勢和限制。算法

       Memory:內存存儲,不言而喻,速度快,對於內存的要求高,不指出的話所緩存的內容非持久化。對於CPU要求很低,因此經常採用將Memcached服務端和一些CPU高消耗Memory低消耗應用部屬在一塊兒。(做爲咱們AEP正好有這樣的環境,咱們的接口服務器有多臺,接口服務器對於CPU要求很高(因爲WS-Security),可是對於Memory要求很低,所以能夠用做Memcached的服務端部屬機器)數據庫

       集中式Cache:避開了分佈式Cache的傳播問題,可是須要非單點保證其可靠性,這個就是後面集成中所做的cluster的工做,能夠將多個Memcached做爲一個虛擬的cluster,同時對於cluster的讀寫和普通的memcached的讀寫性能沒有差異。緩存

       分佈式擴展:Memcached的很突出一個優勢,就是採用了可分佈式擴展的模式。能夠將部屬在一臺機器上的多個Memcached服務端或者部署在多個機器上的Memcached服務端組成一個虛擬的服務端,對於調用者來講徹底屏蔽和透明。提升的單機器的內存利用率,也提供了scale out的方式。服務器

       Socket通訊:傳輸內容的大小以及序列化的問題須要注意,雖然Memcached一般會被放置到內網做爲CacheSocket傳輸速率應該比較高(當前支持Tcpudp兩種模式,同時根據客戶端的不一樣能夠選擇使用nio的同步或者異步調用方式),可是序列化成本和帶寬成本仍是須要注意。這裏也提一下序列化,對於對象序列化的性能每每讓你們頭痛,可是若是對於同一類的Class對象序列化傳輸,第一次序列化時間比較長,後續就會優化,其實也就是說序列化最大的消耗不是對象序列化,而是類的序列化。若是穿過去的只是字符串,那麼是最好的,省去了序列化的操做,所以在Memcached中保存的每每是較小的內容。框架

       特殊的內存分配機制:首先要說明的是Memcached支持最大的存儲對象爲1M。它的內存分配比較特殊,可是這樣的分配方式其實也是對於性能考慮的,簡單的分配機制能夠更容易回收再分配,節省對於CPU的使用。這裏用一個酒窖比喻來講明這種內存分配機制,首先在Memcached起來的時候能夠經過參數設置使用的總共的Memory,這個就是建造一個酒窖,而後在有酒進入的時候,首先申請(一般是1M)的空間,用來建酒架,酒架根據這個酒瓶的大小分割酒架爲多個小格子安放酒瓶,將一樣大小範圍內的酒瓶都放置在一類酒架上面。例如500px半徑的酒瓶放置在能夠容納20-625px的酒架A上,750px半徑的酒瓶就放置在容納25-750px的酒架B上。回收機制也很簡單,首先新酒入庫,看看酒架是否有能夠回收的地方,若是有直接使用,若是沒有申請新的地方,若是申請不到,採用配置的過時策略。這個特色來看,若是要放的內容大小十分離散,同時大小比例相差梯度很明顯,那麼可能對於使用空間來講很差,可能在酒架A上就放了一瓶酒,但佔用掉了一個酒架的位置。異步

       Cache機制簡單:有時候不少開源的項目作的面面俱到,可是最後也就是由於過於注重一些非必要性的功能而拖累了性能,這裏要提到的就是Memcached的簡單性。首先它沒有什麼同步,消息分發,兩階段提交等等,它就是一個很簡單的Cache,把東西放進去,而後能夠取出來,若是發現所提供的Key沒有命中,那麼就很直白的告訴你,你這個key沒有任何對應的東西在緩存裏,去數據庫或者其餘地方取,當你在外部數據源取到的時候,能夠直接將內容置入到Cache中,這樣下次就能夠命中了。這裏會提到怎麼去同步這些數據,兩種方式,一種就是在你修改了之後馬上更新Cache內容,這樣就會即時生效。另外一種是說允許有失效時間,到了失效時間,天然就會將內容刪除,此時再去去的時候就會命中不了,而後再次將內容置入Cache,用來更新內容。後者用在一些時時性要求不高,寫入不頻繁的狀況。socket

       客戶端的重要性:Memcached是用C寫的一個服務端,客戶端沒有規定,反正是Socket傳輸,只要語言支持Socket通訊,經過Command的簡單協議就能夠通訊,可是客戶端設計的合理十分重要,同時也給使用者提供了很大的空間去擴展和設計客戶端來知足各類場景的須要,包括容錯,權重,效率,特殊的功能性需求,嵌入框架等等。分佈式

       幾個應用點:小對象的緩存(用戶的token,權限信息,資源信息)。小的靜態資源緩存。Sql結果的緩存(這部分用的好,性能提升至關大,同時因爲Memcached自身提供scale out,那麼對於db scale out的老大難問題無疑是一劑好藥)。ESB消息緩存。memcached

 

集成設計

       爲何須要集成?直接使用現有的兩個Java實現Memcached是否就能夠了?性能

       當前集成主要爲了兩方面考慮,首先是方便的配置使用,如何將Memcached內嵌到相似於ASF以及其餘框架中去,而且經過配置文件方便使用,這就須要做部分的集成工做,這部分工做主要是定義了配置文件以及經過Stax去解析配置的功能。而後是如何管理Memcached,這部份內容包括了初始化,運行期檢測,資源回收的工做。最後是擴展,這裏的擴展分紅兩部分(功能的擴展以及框架實現的擴展),功能擴展例如當前擴展了虛擬的cluster,可讓多個memcached Client組成一個虛擬的cluster,若是經過放入cluster的方式放入到其中一個Cache Client中的話,那麼就能夠在整個cluster都做好備份,這樣其實能夠根據memcached的單機多實例以及多機多實例做交互備份,提升可靠性。固然後續還有不少能夠擴展的內容,這裏只是一個開頭。框架實現的擴展指的是這裏採用了相似於JdkJAXP的框架設計,只是規定了框架API結構,至於實現者動態載入,這個和ASF等如今可擴展的框架同樣,提供了很方便的擴展點,後續的設計中會提到。

 

接口設計類圖:

1  Cache接口包類圖

       ICacheIMemcachedCache實現的是最基本的Cache的功能,只是IMemcachedCache有所加強,提供了對於虛擬的Cluster的操做,批量操做,統計的功能。ICacheManagerIMemcachedCacheManager分別是對於上面兩個Cache的管理類,根據配置文件解析,初始化客戶端池,創建虛擬集羣,銷燬客戶端池等工做。

 

2  Memcached 實現包

       省略了一些輔助類定義。這部分是具體的實現,同時能夠在圖上看到spi包內的CacheManagerFactory就是用來提供擴展使用的接口。只須要定義在jarMETA-INF下面創建services目錄,創建兩個名爲:com.alisoft.xplatform.asf.cache.IMemcachedCacheManagercom.alisoft.xplatform.asf.cache.spi.CacheManagerFactory的文件就能夠替換MemcachedCacheManagerCacheManagerFactory的實現類,從而改變Memcached Client實現機制。若是沒有這兩個文件在Classpath目錄下面,那麼默認將會使用當前框架中的兩個實現。

 

3  Memcached的結構圖

       Memcached Server就是部署在不一樣服務器或者在同一臺服務器上的Memcached實例,通常採用後臺守護進程方式運行。SocketPool是客戶端鏈接到服務端的Socket通訊層,Memcached Client能夠歸屬爲虛擬的ClusterMemcachedCacheManager做用是管理ClusterCache。從這個結構圖能夠看出客戶端的每一層都是很獨立,這樣有利於層次的交互,以及組合擴展。

測試與使用

1.  配置:

須要有一個名爲memcached.xml的文件在classpath中,能夠在jar裏面也能夠在任意classpath能夠找的到的地方,須要注意的是,CacheManager實現了對於多個memcached.xml merge的功能。

具體的配置內容以下:

<?xml version="1.0" encoding="UTF-8"?>

<memcached>//總標籤

   //memcached Client的配置,也就是一個IMemcachedCache的配置。Name必須填,表示Cache的名稱,socketpool必須填,表示使用的遠程通訊鏈接池是哪個,參看後面對於socketpool的定義。後面都是可選的,第三個參數表示傳輸的時候是否壓縮,第四個參數表示默認的編碼方式

<client name="mclient1" socketpool="pool1" compressEnable="true" defaultEncoding="UTF-8" >

        <!--errorHandler></errorHandler-->//可定義錯誤處理類,通常不須要定義

    </client>

    <client name="mclient2" socketpool="pool2" compressEnable="true" defaultEncoding="UTF-8" >

    </client>  

     //socketpool是通訊鏈接池定義,每個memcached Client要和服務端交互都必須有通訊鏈接池做爲底層數據通訊的支持,name必填,表示名字,同時也是memcached client指定socketpool的依據,failover表示對於服務器出現問題時的自動修復。initConn初始的時候鏈接數,minConn表示最小閒置鏈接數,maxConn最大鏈接數,maintSleep表示是否須要延時結束(最好設置爲0,若是設置延時的話那麼就不可以馬上回收全部的資源,若是此時重新啓動一樣的資源分配,就會出現問題),nagleTCP對於socket建立的算法,socketTOsocket鏈接超時時間,aliveCheck表示心跳檢查,肯定服務器的狀態。Serversmemcached服務端開的地址和ip列表字符串,weights是上面服務器的權重,必須數量一致,不然權重無效

    <socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"

        nagle="false" socketTO="3000" aliveCheck="true">

        <servers>10.0.68.210:12000,10.0.68.210:12222</servers>

        <weights>5,5</weights>

    </socketpool>  

    <socketpool name="pool2" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"

        nagle="false" socketTO="3000" aliveCheck="true">

        <servers>10.0.68.210:22000,10.0.68.210:22222</servers>

        <weights>5,5</weights>

    </socketpool>

    //虛擬集羣設置,這裏將幾個clientcache設置爲一個虛擬集羣,當對這些IMemcachedCache做集羣操做的時候,就會自動地對集羣中全部的Cache做插入,尋找以及刪除的操做,作一個虛擬交互備份

    <cluster name="cluster1">

        <memCachedClients>mclient1,mclient2</memCachedClients>

    </cluster>            

</memcached>

 

2.  測試代碼,這裏就附帶一個單元測試類的代碼就能夠很清楚的知道使用方法。

 

後話

沒有很差的,只有不適合的,適合的場景使用,根據場景適合的使用,纔是提升性能的最有效手段。後須要根據所需的應用場景繼續對這部分集成內容做完善,實踐完善設計。

相關文章
相關標籤/搜索