Memcached基礎知識


主要內容:

  Memcached基本的工作原理

  Memcached的兩階段哈希

  Memcached的數據存儲方式

  Memcached新建Item分配內存過程

  Memcached的數據過期方式

  Memcached與Spring集成

------------------------------------------------------------------------------------------

Memcached基本的工作原理

  Memcached是以守候程序的方式運行於一個或者多個服務器中,隨時等待客戶端的鏈接請求,通過啟動Memcached服務端,配置相應的監聽IP、端口等參數,客戶端可通過指定的服務器IP 將數據以key-value的方式存儲到Memcached實例中。

  如下圖所示,有N個Memcached實例部署在一台專門的機器上,應用程序在查詢數據時首先去Memcached里面查詢,如果有數據則直接返回客戶端使用,如果Memcached里面沒有需要的數據或者數據過期了,則應用程序先去查詢數據庫,然后把查詢的結果放到Memcached實例里面去,最后返回給客戶端。

Memcached的兩階段哈希

  第一階段哈希是計算"key-value"存儲在哪個Memcached實例上,第二階段哈希是計算"key-value"是存儲存儲在Memcached實例的哪個chunk里面。

  客戶端存取數據時,首先參考Memcached實例列表計算出key的哈希值(階段一哈希),進而選中一個Memcached實例;客戶端將請求發送給選中的Memcached實例節點,然后該Memcached節點通過內部的哈希算法(階段二哈希) 進行真正的數據(Item)存取。 Memcached的服務器和客戶端通信並不使用復雜的XML等格式,而是使用簡單的基於文本行的協議。

  如下圖所示:
    比如我們要在Memcached上存儲 key為"Hello",value為"World" 的這么一個鍵值對。
    階段一哈希: 首先在客戶端根據key計算出該"鍵值對"會存儲在哪個Memcached實例中,假如是m2
    階段二哈希: 在Memcached實例二中 再次根據key計算出該"鍵值對"在m2實例中存在的位置。

 

Memcached的數據存儲方式

  Memcached的數據存儲方式被稱為Slab Allocator,其基本方式是:

  (a)先把內存分成很多個Slab,這個大小是預先規定好的,以解決內存碎片問題。

    分配給Slab的內存空間被稱為Page,默認是1M。一個Slab下可以有多個Page。

    (如下圖:在Memcached實例中先把內存分了n個slab,然后每個slab里面分了n個page)

  (b)然后把一個Page分成很多個chunk塊,chunk塊是用於緩存記錄的空間。Chunk的大小是先有一個基本值,然后根據增長因子來增大。
Slab Allocation的原理——將分配的內存分割成各種尺寸的塊(chunk), 並把尺寸相同的塊分成組(chunk的集合),每個chunk集合被稱為slab。
  (借用網上一張圖來說明:)

 

  (c)slab class:內存區類別(48byte-1M),每個類別有一個slab classId

 

(d)Memcached里面保存着slab內存空間的chunk列表,當收到要保存的item時,它會根據item的大小去選擇一個最適合的slab,然后找到空閑的chunk,把數據存放進去。

Memcached新建Item分配內存過程

  第一步: 快速定位slab classid,先計算Item長度
    key鍵長+flag+suffix(16字節)+value值長+結構大小(32字節),比如計算出來有90byte
    如果Item長度計算出來>1M,則無法存儲丟棄
    取最小冗余的slab class進行存儲,比如有:48、96、120, 存儲90就會選96
  第二步:按順序尋找可用的chunk
    (a) slot : 檢查slab回收空間slot里是否有剩余chunk
      delete: delete時標記到slot
      exptime: get時檢查的過期對象標記到slot
    (b)end_page_ptr: 檢查page中是否有剩余chunk
    (c)memory: 內存還有剩余空間可以用於開辟新的slab
    (d)LRU
  (PS:Memcached的數據存儲方式的缺點,由於chunk的大小是預先分配好的特定長度,因此如果數據不能完全填滿chunk,那么chunk中剩余的空間就浪費了。)

Memcached的數據過期方式
  (1)Lazy Expiration(延遲/惰性 過期)
    Memcached不會監控記錄是否過期,而是當客戶端來獲取數據的時候,才會檢查記錄的時間戳,因此成為Lazy Expiration
  (2)LRU(Least Recently Used 最近最少使用)
    當空間不足的時候,Memcached會優先使用已經過期的數據空間,如果還不夠的話,那么就會把最近最少使用的對象的空間釋放出來。
    (ps:要特別注意,Memcached的LRU不是全局的,而是針對slab的,可以說是區域性的)
  (3)惰性刪除機制
    刪除item對象時,不釋放內存,作刪除標記,指針放入slot回收插槽,下次分配的時候直接使用。

Memcached與Spring集成

(1)先把jar包添加到本地倉庫中:

  mvn install:install-file -Dfile=java_memcached-release_2.6.6.jar -DgroupId=com.danga -DartifactId=memcached -Dversion=2.6.6 -Dpackaging=jar -DgeneratePom=true

  (ps:注意 -Dfile=java_memcached-release_2.6.6.jar  一定要輸入jar包的全路徑名 )

(2)在pom中添加memcached的lib依賴和common-pool的lib依賴:

 1         <dependency>
 2             <groupId>commons-pool</groupId>
 3             <artifactId>commons-pool</artifactId>
 4             <version>1.5.6</version>
 5         </dependency>
 6         <dependency>
 7             <groupId>com.danga</groupId>
 8             <artifactId>memcached</artifactId>
 9             <version>2.6.6</version>
10         </dependency>

(3)在spring的applicationContext.xml文件中加入memcached的配置

 1 <bean id="memcachedPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance"
 2     init-method="initialize" destroy-method="shutDown">
 3         <constructor-arg>
 4             <value>neeaMemcachedPool</value>
 5         </constructor-arg>
 6         <property name="servers">
 7             <list>
 8                 <value>192.168.1.81:3333</value>
 9             </list>
10         </property>
11         <property name="weights">
12             <list>
13                 <value>1</value>
14             </list>
15         </property>
16         <property name="initConn">
17             <value>5</value>
18         </property>
19         <property name="minConn">
20             <value>5</value>
21         </property>
22         <property name="maxConn">
23             <value>5</value>
24         </property>
25         <property name="maintSleep">
26             <value>30</value>
27         </property>
28         <property name="nagle">
29             <value>false</value>
30         </property>
31         <property name="maxIdle">
32             <value>6000</value>
33         </property>
34         <property name="socketTO">
35             <value>3000</value>
36         </property>
37     </bean>
38     
39     <bean id="memCachedClient" class="com.danga.MemCached.MemCachedClient">
40         <constructor-arg>
41             <value>neeaMemcachedPool</value>
42         </constructor-arg>
43     </bean>

 在程序中就可以通過 MemCachedClient的get、set方法來往Memcached里面獲取和設置item了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  


免責聲明!

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



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