memcached詳解

目錄

一、memcached 是什麼

二、memcached 特點

三、memcached內存分配機制

四、分佈式緩存中三種負載均衡的方法

五、memcached 過期方式

六、memcached 基於libevent的事件處理

七、memcached的安裝

八、memcached 的使用和配置

九、memcached 命令使用詳解

十、安裝PHP的擴展Memcached實現lnmp+memcached

十一、Nginx整合memcached



緩存服務器的類型:

透傳式緩存:首先得有代理功能,工作在真實服務器前端,請求先到達緩存服務器,緩存服務器中有該請求的數據並在有效期內就直接使用緩存響應給用戶,如果沒有或過期則緩存服務器請求向後端的服務器請求該數據響應給客戶並根據協議決定是否緩存在本地,緩存服務器對於客戶端是透明的

旁掛式緩存:工作在真實服務器後端,在真實服務器上要查詢數據時,應用程序調用memcached的客戶端|驅動首先查詢memcached,如果memcached中有相應的緩存數據,取得數據並響應給用戶,如果memcahed中沒有相應的緩存數據則真實服務器向mysql中查詢,並根據協議決定是否把查詢結果緩存在memcached上。



一、memcached 是什麼

       Memcached是一款開源、高性能、分佈式內存對象緩存系統,可應用各種需要緩存的場景,

其主要目的是通過降低對Database的訪問來加速web應用程序

它是一個基於內存的“鍵值對”存儲,用於存儲數據庫調用、API調用或頁面引用結果的直接數據,如字符串、對象等。

Memcached是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 爲首開發的一款軟件。現在已成爲mixi、hatena、Facebook、Vox、LiveJournal等衆多服務中提高Web應用擴展性的重要因素。

       許多Web應用都將數據保存到RDBMS(關係型數據庫管理系統)中,應用服務器從中讀取數據並在瀏覽器中顯示。 但隨着數據量的增大、訪問的集中,就會出現RDBMS的負擔加重、數據庫響應惡化、 網站顯示延遲等重大影響。

       這時就該memcached大顯身手了,通過緩存數據庫查詢結果,減少對數據庫訪問次數,來加速Web應用程序的速度、 提高可擴展性。如下圖,

wKioL1ZigaLjrqqSAAB0gGZB1xA276.png

二、memcached 特點

Memcached是一款開發工具,它既不是一個代碼加速器,也不是數據庫中間件。

其設計哲學思想主要反映在如下方面:

  • 簡單key/value存儲:服務器不關心數據本身的意義及結構,只要是可序列化數據即可。

    存儲項由“鍵、過期時間、可選的標誌及數據”四個部分組成;

  • 功能的實現一半依賴於客戶端,一半基於服務器端:客戶負責發送存儲項至服務器端、從服務端獲取數據以及無法連接至服務器時採用相應的動作;服務端負責接收、存儲數據,並負責數據項的超時過期;

  • 各服務器間彼此無視:不在服務器間進行數據同步;

  • O(1)的執行效率

  • 清理超期數據:默認情況下,Memcached是一個LRU緩存,同時,它按事先預訂的時長清理超期數據;但事實上,memcached不會刪除任何已緩存數據,只是在其過期之後不再爲客戶所見;而且,memcached也不會真正按期限清理緩存,而僅是當get命令到達時檢查其時長;

    Memcached的服務器客戶端通信並不使用複雜的XML等格式, 而使用簡單的基於文本格式和二進制格式。因此,通過telnet 也能在memcached上保存數據、取得數據。

三、Memcached內存分配機制

1、Slab Allocation機制

     memcached默認情況下采用了名爲Slab Allocator的機制分配、管理內存。在該機制出現以前,內存的分配是通過對所有記錄簡單地進行malloc()和free()來進行的。但是,這種方式會導致內存碎片,加重操作系統內存管理器的負擔,最壞的情況下,會導致操作系統比memcached進程本身還慢。

Slab Allocator就是爲解決該問題而誕生的。

Slab Allocator的基本原理是按照預先規定的大小,將分配的內存分割成特定長度的塊,以完全解決內存碎片問題。

2、Slab Allocation的主要術語

   1)page:分配給Slab用於切割的內存空間,默認是1MB。分配給Slab之後根據slab的大小切分成chunk

   2)chunk:存放數據的最小單元。用戶數據item(key、value等)最終會保存在chunk中。

   3)slab class特定大小的chunk的組,在memcached中,對數據的管理是以slab爲單元進行管理的。

每個slab class對應一個或多個空間大小相同的chunk。參考下圖一。

wKiom1ZigWzT0DATAAB6skG1y-M818.jpg


3、在Slab中緩存記錄的原理

下面說明memcached如何針對客戶端發送的數據選擇slab並緩存到chunk中

memcached根據收到的數據的大小,選擇最適合數據大小的slab(圖2)。memcached中保存着slab內空閒chunk的列表,根據該列表選擇chunk,然後將數據緩存於其中。

wKioL1ZiggGQkNdwAAA8ArWugZw617.png

 圖2 選擇存儲記錄的組的方法

4、Slab Allocator的缺點

Slab Allocator解決了當初的內存碎片問題,但新的機制也給memcached帶來了新的問題。

這個問題就是,由於分配的是特定長度的內存,因此無法有效利用分配的內存。

例如,將100字節的數據緩存到128字節的chunk中,剩餘的28字節就浪費了(圖3)。

wKiom1ZigdeC7zvfAAAXrpVUTWI008.png

                             圖3 chunk空間的使用

對於該問題目前還沒有完美的解決方案,但在文檔中記載了比較有效的解決方案。

The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all possible) common sizes of objects that the clients of this particular installation of memcached are likely to store.

就是說,如果預先知道客戶端發送的數據的公用大小,或者僅緩存大小相同的數據的情況下,只要使用適合數據大小的組的列表,就可以減少浪費。

但是很遺憾,現在還不能進行任何調優,只能期待以後的版本了。

但是,我們可以通過設置growth factor(增長係數/因子)選項來調節slab class的大小的差別

四、分佈式緩存中三種負載均衡的方法

第一種:傳統的數據分佈方法,將key的hash值對機器數取模

    對用戶的檢索關鍵詞分詞後進行hash然後對hash出的數對4(緩存服務器的個數)取模,餘數爲1則分配到,服務器1上,爲2分配到2上,依次類推。

    這個算法的實現非常簡單,計算hash(key)/n,n爲機器數,得到的值就是該key需要路由到的服務器編號了。

    優點:實現簡單

    缺點:在服務器數量發生變化的時候,緩存會大量失效。 

第二種:一致性hash 

    試想下如果使用傳統取模算法。如果有一個key要存到緩存中,根據hash(key)/n (n表示有n臺緩存服務器),可以計算出緩存所在的服務器id。這個時候有一臺服務器掛掉了,剩下n-1臺服務器。這時候,同樣一個key,根據hash(key)/(n-1) ,這個時候就命中不了緩存了,基本所有的緩存都會失效,這個情況在線上可能是災難性的。 一致性hash可以解決部分問題。

    通常可以考慮[0,(2^32-1)]爲hash值的取值範圍。我們可以把取值範圍想象成一個閉環,2^32-1 和 0 相連接。如下圖所示。

wKiom1Zigg-wa03qAABTi3flMz4741.png

這個時候假設我們有4個緩存服務器節點。(node1~node4) 首先計算這四個值的hash值,並且這四個點佔據了閉環的四個位置,如上圖所示,這個時候需要根據key來路由緩存服務器,首先計算hash(key)值(這個hash算法需要保證hash(key)的值落在在區間[0,2^32-1]中)。然後我們可以想象這個hash(key)值位於閉環的其中一個點,然後用這個hash(key)依次加一,直到命中其中一個node爲止,命中的node就是key需要路由的服務器,如上圖,需要找到key2的緩存值所在的服務器,首先計算hash(key2),落在如圖的閉環中,然後順時針找到離這個hash值最近的node,可以看到是node1。key2對應的緩存值就存在node1中。

    如果這個時候如果增加了節點node5如下圖:

wKiom1ZigkLC-vgGAABgqdwboqU704.png

看下緩存失效的情況,如上圖,只有hash(key)落在node4~node5之間的key纔會有影響,在未增加node5之前落在這個範圍的key最終路由到node1,增加node5之後路由到node5了,緩存失效了。除此之外,落在其他範圍的hash值就不受影響。如上圖,增加node5之後key6原來會路由到node1的,現在路由到node5。而key1不受影響,還是路由到node1。

    同理,如果少掉一個節點,還是上圖爲例,假如這個時候node5失效了,node5失效之前落在node4~node5之間的hash值,會路由到node5,失效之後會路由到node1,也就是原本落在node4~node5之間的hash值失效了。由此可見一致性hash能在節點變動的時候減少緩存失效的比例。  

    還有一種情況,當cache的數量很少的或者緩存服務器很少的時候,會導致緩存分佈不均衡。如下圖所示:

wKioL1ZigtORsusLAABT1yEcLSI036.png

當只有很少節點的時候,例如上圖的兩個,這個時候就會分配得很不均衡。

這個時候引入一個叫虛擬節點的概念,原理就是增加更多的虛擬節點,讓每個節點承受的壓力盡量均衡。

這些增加的節點並不是真正新增的服務器節點,而是由原來的節點”複製“出來的。

例如下圖,”複製“了兩個新節點,node3,node4。實際上,落到node3,node4的key最終訪問的服務器是node2,node1.

wKiom1Zigoyw85EYAABcTrJs9Yo569.png

 這樣就可以把壓力盡量分配到各個機器上。另外需要維護一張表格,用來記錄虛擬節點指向的真正節點。 

    優點:相比簡單的對機器數取模算法,當節點變動的時候只有相對較少的key失效,實現也相對簡單。不需要進行數據遷移,每個服務器是獨立的。

    缺點:還是會有部分的key失效,如果訪問量非常大的時候,如果訪問到失效的key的時候,就會直接訪問到數據源上面去了,可能會導致數據源直接壓掛。
  

第三種:fair負載均衡算法,構造一張對照表
 

    首先看下如何構建一張對照表。

    tair中數據的存儲是以bucket爲單位的,一個bucket對應一個dateServer,一個dateServer中會有多個bucket。bucket的數目是固定的,這裏假設bucket的數量爲1024個,並且每個bucket有屬於自己的id,依次從0到1023。如下圖:

wKioL1ZigxzDPdsqAABpzQphGz4427.png

可以看到對key進行hash之後首先會路由到某個bucket然後根據對應關係,再路由到對應的dataServer。    
在tair中,你可以設置同一個bucket的備份數目,我們稱其中一個bucket爲master,其他的備份稱爲slave。configServer啓動的時候會構造三張bucket和dataServer的對照表,分別是hash_table, m_hash_table, d_hash_table,這三張對照表在初始構建的時候都是一樣的,但是在dataServer發生增加的時候會暫時不一樣,但是最終會趨向一致,三張表分別有什麼用處下面會講到。configServer在構建對照表的時候有兩種模式,一種是均衡模式,這種模式會盡量保證每個節點的bucket數目差不多。一種是安全模式,這種模式會盡量保證一份數據以及它的備份分配在不同的區域的服務器上。client通過configServer獲取對照表(hash_table)之後,根據(hash(key)%bucket的總數)算出bucket的id並且參照對照表,就能知道這個key對應的dataServer了。對照表的結構大概如下(這裏爲了簡化,一共只有5個bucket,4個dataServer(ds1,ds2,ds3,ds4),這個是初始時的對照表,hash_table, m_hash_table, d_hash_table的內容都是一樣的)。

wKiom1Ziguzh14TYAAA8tg5tVyQ748.jpg

 當服務器變化之後configserver是如何重構對照表的?重構對照表的時候,數據是怎麼遷移的?

    configServer會定時發送心跳包給dataServer,用來檢測dataServer是否還存活,如果沒有存活的話就會重新構造對照表。或者如果有新加dataServer的話也會重新構造對照表。

當有一個dataServer當機之後,這個機器 上的存儲的bucket數據都會丟失,如果是master bucket丟失之後其中一個slave bucket會補上成爲master bucket。至於選擇哪個slave bucket成爲master bucket的是根據slave 上負載的master bucket有沒有超標,並且總bucket數有沒有超標等標準。舉個例子,上圖中當ds2失效之後,hash_table, m_hash_table, d_hash_table三個表分別是這樣子的。

 hash_table :

wKioL1Zig32hXnvBAAA3vSK7rJM484.jpg

m_hash_table:

wKioL1Zig6CAOxiIAAA3vSK7rJM666.jpg

d_hash_table:

wKiom1Zig2LT19e9AAA-wxYhJmk993.jpg

hash_table發送給client,client不至於不能工作,m_hash_table和d_hash_table發送到dataServer,dataServer根據這兩張表就可以知道自己是否需要遷移數據和遷移到哪裏了。例如這裏第一列,第三排,對比兩表,可以知道,ds1需要把數據遷移到ds4。 

   如果是要增加新的dataServer,原理就差不多了,configServer新建對照表,然後把對照表發送到dateServer,然後dataServer再根據新對照表來做數據遷移,完成之後,client就可以使用新的對照表了。

    優點:當需要增加機器的時候,不會有key失效。

    缺點:實現比較複雜,需要進行數據的遷移。

五、memcached 過期方式

數據過期方式:Lazy Expiration + LRU

1.Lazy Expiration(惰性過期)

根據緩存對象的ttl進行清理

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

2.LRU(最近最少使用算法)

       memcached會優先使用已超時的記錄的空間,但即使如此,也會發生追加新記錄時空間不足的情況,此時就要使用名爲 Least Recently Used(LRU)機制來分配空間。當memcached的內存空間不足時(無法從slab class 獲取到新的空間時),就從最近未被使用的記錄中搜索,並將其空間分配給新的記錄。可以支持禁用此功能

六、memcached 基於libevent的事件處理

       libevent是個程序庫,它將Linux的epoll、epool,select,BSD類操作系統的kqueue等事件處理功能封裝成統一的接口。即使對服務器的連接數增加,也能發揮O(1)的性能。memcached使用這個libevent庫,因此能在Linux、BSD、Solaris等操作系統上發揮其高性能。 

memcached依賴於libevent API,因此要事先安裝之,項目主頁:http://libevent.org/,

讀者可自行選擇需要的版本下載。可以使用yum安裝libevent

也可以使用源碼包編譯安裝。安裝過程:

# tar xf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21
# ./configure --prefix=/usr/local/libevent
# make && make install
# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
# ldconfig

七、memcached 安裝

1、直接yum安裝

[root@BAIYU_173 yum.repos.d]# yum install memcached -y
[root@BAIYU_173 ~]# rpm -ql memcached
/etc/rc.d/init.d/memcached
/etc/sysconfig/memcached
/usr/bin/memcached
/usr/bin/memcached-tool
/usr/share/doc/memcached-1.4.4
/usr/share/doc/memcached-1.4.4/AUTHORS
/usr/share/doc/memcached-1.4.4/CONTRIBUTORS
/usr/share/doc/memcached-1.4.4/COPYING
/usr/share/doc/memcached-1.4.4/ChangeLog
/usr/share/doc/memcached-1.4.4/NEWS
/usr/share/doc/memcached-1.4.4/README
/usr/share/doc/memcached-1.4.4/protocol.txt
/usr/share/doc/memcached-1.4.4/readme.txt
/usr/share/doc/memcached-1.4.4/threads.txt
/usr/share/man/man1/memcached.1.gz
/var/run/memcached

2、編譯安裝

 1)安裝libevent

注,在上文中提到memcached是基於libevent進行事件處理的,所以我們得先安裝libevent。

[root@memcache src]# tar xf libevent-2.0.21-stable.tar.gz
[root@memcache src]# cd libevent-2.0.21-stable
[root@memcache libevent-2.0.21-stable]# ./configure --prefix=/usr/local/libevent
[root@memcache libevent-2.0.21-stable]# make && make install

2)安裝memcached

[root@memcache src]# tar xf memcached-1.4.15.tar.gz
[root@memcache src]# cd memcached-1.4.15
[root@memcache memcached-1.4.15]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
[root@memcache memcached-1.4.15]# make && make install

3)後續配置

[root@memcache ~]# vim /etc/profile.d/memcache.sh 
[root@memcache ~]# cat /etc/profile.d/memcache.sh  
export PATH=$PATH:/usr/local/memcached/bin/  
[root@memcache ~]# source /etc/profile


八、memcached使用和配置

1、memcached選項

-p TCP監聽端口 (default: 11211),小寫
-U UDP 監聽端口 (default: 11211, 0 is off),大寫
-s UNIX socket監聽路徑,不支持網絡
-a UNIX socket訪問掩碼, 八進制 (default: 0700)
-l 監聽的服務器IP地址 (default: all addresses)
-d 運行爲守護進程
-r 最大限度利用核心文件限制
-u 運行memcached用戶
-m #:最大的內存使用 (default: 64 MB),也不宜過大
-M 內存耗盡返回錯誤,而不是刪除緩存對象,
-c 最大併發連接 (default: 1024)
-k 鎖定所有分頁內存
-v 輸出警告和錯誤信息
-vv 同時打印客戶端請求和返回信息
-vvv 打印內部狀態轉換信息
-i 打印memcached 和 libevent 版本信息
-P 設置保存pid文件, only used with -d option
-f 指定增長因子|倍數 (default: 1.25)
-n key+value+flags最小分配空間(default: 48)
-L 嘗試使用大內存頁。增加內存頁大小可以減少失誤的TLB數量,提高性能。
-D 指定key和IDs的分隔符 default is “:” (colon). 如果指定此選項,統計信息收集自動開啓;
-t 使用的線程數量 (default: 4)
-R 每個事件的最大請求數 (default: 20)
-C 禁止使用 CAS
-b 設置積壓隊列數限制 (default: 1024)、
-B 綁定協議 – one of ascii, binary, or auto (default)
-I 分配給每個slab頁(default: 1mb, min: 1k, max: 128m)
-o 配置額外選項

2、啓動memcached

[root@BAIYU_173 ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
memcached:x:498:499:Memcached daemon:/var/run/memcached:/sbin/nologin
[root@BAIYU_173 ~]# memcached -u memcached -vv
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 8388608, now 268435456
<27 server listening (udp)
<27 server listening (udp)
<27 server listening (udp)
<27 server listening (udp)

從輸出結果可以看到memcached的內存分配過程:

[root@BAIYU_173 ~]# service memcached start
正在啓動 memcached:[確定]
[root@BAIYU_173 ~]# netstat -nlptu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      25006/memcached     
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1455/sshd           
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1552/master         
udp        0      0 0.0.0.0:11211               0.0.0.0:*                               25006/memcached


3、memcached 基本命令

Memcached提供了爲數不多的幾個命令來完成與服務器端的交互,這些命令基於memcached的協議實現。

存儲類命令:set, add, replace, append(在一個緩存後附加內容), prepend(在一個緩存之前附加內容)

獲取數據類命令:get, delete, incr/decr(自加1/自減1)

統計類命令:stats, stats items, stats slabs, stats sizes

清理命令: flush_all


add命令

add keyname flag(修飾符)  timeout  datasize

如:

add mykey 0(表示沒有修飾符) 10(生成周期) 12(數據大小)

Hello world!


get命令:

get keyname

如:get mykey

VALUE mykey 0 12

Hello world!

END

[root@BAIYU_173 ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
add 4key 0 20 3
abc
STORED
get mykey
END
get 4key
VALUE 4key 0 3
abc
END
add 4key 0 20 3
abc

九、memcached 常用命令

(1).增加值命令

說明:無論如何都添加或更新的set 命令 (值不存在則添加,存在則更新)  set設置後可以用get命令獲取值,也可以使用delete命令刪除該值。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 3
100
STORED
get mykey
VALUE mykey 0 3
100
END
delete mykey
DELETED
get mykey
END

說明:只有數據不存在時添加值的add命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
add mykey 0 0 4 #第一次添加成功
test
STORED
add mykey 0 0 4 #第二次添加失敗
test
NOT_STORED

說明:只有數據存在時替換的replace命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
replace testkey 0 0 2 #元素不存在替換失敗
11
NOT_STORED
add testkey 0 0 2
22
STORED
get testkey
VALUE testkey 0 2
22
END
replace testkey 0 0 3 #元素存在替換成功
100
STORED
get testkey
VALUE testkey 0 3
100
END

(2).刪除命令 delete

get mykey
VALUE mykey 0 3
100
END
delete mykey
DELETED
get mykey
END

(3).讀取命令

說明:get 命令 獲取一個鍵或多個鍵的值 多個鍵以空格分開。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set testkey 0 0 2
20
STORED
get mykey testkey
VALUE mykey 0 2
10
VALUE testkey 0 2
20
END

說明:gets 命令比get返回的值多一個數字,用來判斷數據是否發生過改變。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set testkey 0 0 2
20
STORED
get mykey testkey
VALUE mykey 0 2
10
VALUE testkey 0 2
20
END

gets mykey testkey
VALUE mykey 0 2 5
10
VALUE testkey 0 2 6
20
END
set testkey 0 0 2
30
STORED
gets mykey testkey
VALUE mykey 0 2 5
10
VALUE testkey 0 2 7
30
END

說明:cas 的意思是 check and set 的意思,只有當最後一個參數gets獲取的那個用來判斷數據發生改變的那個值相同時纔會存儲成功,否則返回 exists。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
gets mykey
VALUE mykey 0 2 5
10
END
cas mykey 0 0 2 6
50
EXISTS
cas mykey 0 0 2 5              
50
STORED
gets mykey
VALUE mykey 0 2 8
50
END

說明:自曾(incr) 自減(decr)命令。

[root@memcache ~]# telnet 192.168.18.201 11211

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set age 0 0 2
10
STORED
get age
VALUE age 0 2
10
END
incr age 2
12
incr age 2
14
get age
VALUE age 0 2
14
END
decr age 1
13
get age
VALUE age 0 2
13
END

(4).狀態命令

說明:stats 顯示memcachd狀態。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
stats
STAT pid 8279 #進程ID
STAT uptime 8000 #服務器運行秒數
STAT time 1378284623 #服務器當前unix時間戳,秒
STAT version 1.4.15 #服務器版本
STAT libevent 2.0.21-stable #libevent版本號
STAT pointer_size 64 #操作系統指針大小(這臺服務器是64位的)
STAT rusage_user 0.000999  計用戶時間
STAT rusage_system 0.003999 #進程累計系統時間
STAT curr_connections 10 #當前打開連接數
STAT total_connections 11 #曾打開的連接總數
STAT connection_structures 11 #服務器分配的連接結構數
STAT reserved_fds 20 #內部使用的FD數
STAT cmd_get 0 #執行get命令總數
STAT cmd_set 0 #執行set命令總數
STAT cmd_flush 0 #執行flush命令總數
STAT cmd_touch 0 #執行touch命令總數
STAT get_hits 0 #get命中次數
STAT get_misses 0 #get未命中次數
STAT delete_misses 0 #delete未命中次數
STAT delete_hits 0 #delete命中次數
STAT incr_misses 0 #incr未命中次數
STAT incr_hits 0 #incr命中次數
STAT decr_misses 0 #decr未命中次數
STAT decr_hits 0 #decr命中次數
STAT cas_misses 0 #cas未命中次數
STAT cas_hits 0 #cas命中次數
STAT cas_badval 0 #使用擦拭次數
STAT touch_hits 0 #touch命中次數
STAT touch_misses 0 #touch未命中次數
STAT auth_cmds 0 #認證處理的次數
STAT auth_errors 0 #認證失敗次數
STAT bytes_read 7 #讀取字節總數
STAT bytes_written 0 #寫入字節總數
STAT limit_maxbytes 134217728 #現在的內存大小爲128M
STAT accepting_conns 1 #目前接受的新接數
STAT listen_disabled_num 0 #失效的監聽數
STAT threads 4 #當前線程數
STAT conn_yields 0 #連接操作主支放棄數目
STAT hash_power_level 16 #hash等級
STAT hash_bytes 524288 #當前hash表等級
STAT hash_is_expanding 0 #hash表擴展大小
STAT bytes 0 #當前存儲佔用的字節數
STAT curr_items 0 #當前存儲數據總數
STAT total_items 0 #啓動以來存儲的數據總數
STAT expired_unfetched 0 #已過期但未獲取的對象數目
STAT evicted_unfetched 0 #已驅逐但未獲取的對象數目
STAT evictions 0 #LRU釋放的對象數目
STAT reclaimed 0 #用已過期的數據條目來存儲新數據的數目
END

說明 :flush_all 清空所有項目。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set age 0 0 2
20
STORED
get mykey age
VALUE mykey 0 2
10
VALUE age 0 2
20
END
flush_all
OK
get mykey age
END

說明:後續追加append和prepend前面插入命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set age 0 0 2
13
STORED
get age
VALUE age 0 2
13
END
append age 0 0 6
111111
STORED
get age
VALUE age 0 8
13111111
END
prepend age 0 0 6
111111
STORED
get age
VALUE age 0 14
11111113111111
END

flush_all 實際上沒有立即釋放項目所佔用的內存,而是在隨後陸續有新的項目被儲存時執行(這是由memcached的懶惰檢測和刪除機制決定的)。flush_all 效果是它導致所有更新時間早於 flush_all 所設定時間的項目,在被執行取回命令時命令被忽略。

十、安裝Memcached的PHP擴展

程序員在開發,自行調用了memcached的API,memcached的功能才能生效

Memcached:服務器

memcached:php連接memacached服務可以使用的擴展

memcache:php連接memcache服務可以使用的另一個擴展(性能更好)

libmemcached:c庫

這裏我用上篇博文安裝好的Lnmp環境來安裝memcache

環境:

192.168.100.10 CentOS6.5-x86_64 lnmp+memcache

192.168.100.173 CentOS6.5-x86_64 memcached

1、安裝php的memcache擴展

[root@www ~]# ls memcache-2.2.7.tgz 
memcache-2.2.7.tgz
[root@www ~]# tar xf memcache-2.2.7.tgz 
[root@www ~]# cd memcache-2.2.7
[root@www memcache-2.2.7]# ls
config9.m4  example.php                 memcache.php        memcache_standard_hash.c
config.m4   memcache.c                  memcache_queue.c    php_memcache.h
config.w32  memcache_consistent_hash.c  memcache_queue.h    README
CREDITS     memcache.dsp                memcache_session.c

注意:此時並沒有configure文件,memcache是作爲php的插件運行

[root@www memcache-2.2.7]# /usr/local/php/bin/phpize   #如果是yum安裝的php,要安裝了php-devel包纔有這個命令
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226
[root@www memcache-2.2.7]# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
[root@www memcache-2.2.7]# make && make install

上述安裝完後會有類似以下的提示:

Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/memcached.so

編輯/etc/php.ini,在“動態模塊”相關的位置添加如下一行來載入memcache擴展:

extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

查看phpinfo頁面可以看到已經有了memcache擴展

wKiom1ZilxWC4mIvAACPxwS7Rcs744.jpg而後對memcached功能進行測試,在網站目錄中建立測試頁面test.php,添加如下內容:

[root@www ~]# vi /www/a.com/test.php 
<?php
    $mem = new Memcache;
    $mem->connect("192.168.100.173", 11211)  or die("Could not connect");
 
    $version = $mem->getVersion();
    echo "Server's version: ".$version."<br/>\n";
 
    $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcac
hed server");
    echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";
 
    $get_result = $mem->get('hellokey');
    echo "$get_result is from memcached server.";
?>

測試:

wKiom1Zil1LiCfk2AABp7YOabho454.png

2、memcached圖形工具

 1)memcachephp

[root@www ~]# ls memcachephp.zip 
memcachephp.zip
[root@www ~]# unzip memcachephp.zip                
Archive:  memcachephp.zip
  inflating: memcache.php            
[root@www ~]# mv memcache.php /www/a.com/
[root@www ~]# ls /www/a.com/
admin  index.html  index.php  memcache.php  test.php

vi memcache.php可以看到裏面定義了管理員默認登錄用戶和密碼,並設置要連接memcached服務器

$MEMCACHE_SERVERS[] = '192.168.100.173:11211';

測試:

wKiom1Zil9mTH5-OAAE6ywNbyrg345.png

可以查看緩存服務器詳細使用狀態,

 2)memadmin-master(中文界面)

MemAdmin是一款可視化的Memcached管理與監控工具,使用PHP開發,體積小,操作簡單。

主要功能:

  • 服務器參數監控:STATS、SETTINGS、ITEMS、SLABS、SIZES實時刷新
    服務器性能監控:GET、DELETE、INCR、DECR、CAS等常用操作命中率實時監控
    支持數據遍歷,方便對存儲內容進行監視
    支持條件查詢,篩選出滿足條件的KEY或VALUE
    數組、JSON等序列化字符反序列顯示
    兼容memcache協議的其他服務,如Tokyo Tyrant (遍歷功能除外)
    支持服務器連接池,多服務器管理切換方便簡潔
[root@www ~]# unzip memadmin-master.zip
[root@www ~]# cd memadmin-master
[root@www memadmin-master]# ls
[root@www memadmin-master]# vi config.php    #查看配置文件
<?php
if (!defined('IN_MADM')) exit();
 
$config['user'] = "admin"; // your username         #默認用戶名admin
$config['passwd'] = "admin"; // your password       #默認密碼admin
[root@www memadmin-master]# cd ..
[root@www ~]# mv memadmin-master /www/a.com         #應該放到php-fpm服務器上,不能放在nginx服務器上,否則會響應影響

下面我們來登錄一下:

wKiom1ZimILC1Mk2AABSPD8coaw626.png

連接memcached服務器並演示:

注,修改memcached服務器的IP與端口,我這裏是192.168.11.202,端口是默認11211。

wKiom1ZimPXheZOTAABazM0yYQY977.jpg

注,點擊 “高級參數”,選擇 “持久化連接”,我這裏設置是30s。最後,點擊增加按鈕。

wKioL1Zima3xgeYNAABkFqfv5rY153.jpg注,點擊默認連接,就可以看到我們設置的參數,點擊“開始管理”,進入管理界面。

wKiom1ZimWqT7OQ6AABHn-YHStw521.png注,進入管理界面。進入的第一個頁面是“連接參數”頁面。由於memadmin工具使用簡單,我在這裏就不詳細講解了。大家自己看一下!

wKiom1ZimY2B6XtFAABPPLoQatw806.png

十一、Nginx整合memcached

        nginx的memcached_module模塊可以直接從memcached服務器中讀取內容後輸出,後續的請求不再經過應用程序處理,如php-fpm、django,大大的提升動態頁面的速度。nginx只負責從memcached服務器中讀取數據,要往memcached寫入數據還得需要後臺的應用程序來完成,主動的將要緩存的頁面緩存到memcached中,可以通過404重定向到後端去處理的。    
ngx_http_memcached_module可以操作任何兼用memcached協議的軟件。如ttserver、membase等。

結構圖如下:

wKioL1Zimh7gziJiAABit9AH2GU854.jpg

memcached的key可以通過memcached_key變量來設置,如以$uri。如果命中,那麼直接輸出內容,沒有命中就意味着nginx需要從應用程序請求頁面。同時,我們還希望該應用程序將鍵值對寫入到memcached,以便下一個請求可以直接從memcached獲取。如果鍵值不存在,nginx將報告not found錯誤。最好的方法是使用error_page指定和location請求處理。同時包含”Bad Gateway”錯誤和”Gateway Timeout”錯誤,如:error_page 404 502 504 = @app;。注意:需要設置default_type,否則可能會顯示不正常。

1、nginx整合memcache

server {
     location / {
 
                   set $memcached_key "$uri?$args";     
                memcached_pass     192.168.100.173:11211;
               # default_type       text/html;
                error_page         404 @fallback;    #調用一個叫fallback的location
        }
 
        location @fallback {                        #定義一個叫fallback的location
                proxy_pass     
        }
}

從上面的配置文件我們可以看出,一個請求到達後,會其uri作爲key去Memcached服務器192.168.18.202:11211上查找value,如果沒有命中,則返回404。這時通過error_page將404接收轉到@fallback,返回給Web服務去處理請求。

2、模塊說明

  • memcached_bind    
    語法: memcached_bind address | off;     
    默認值: none     
    配置段: http, server, location     
    指定從哪個IP來連接memcached服務器


  • memcached_buffer_size    
    語法: memcached_buffer_size size;     
    默認值: 4k|8k;     
    配置段: http, server, location     
    讀取從memcached服務器接收到響應的緩衝大小。儘快的將響應同步傳給客戶端。


  • memcached_connect_timeout    
    語法:memcached_connect_timeout time;     
    默認值:60s;     
    配置段:http, server, location     
    與memcached服務器建立連接的超時時間。通常不超過75s。


  • memcached_gzip_flag    
    語法:memcached_gzip_flag flag;     
    默認值:none     
    配置段:http, server, location     
    測試memcached服務器響應標誌。如果設置了,將在響應頭部添加了Content-Encoding:gzip。


  • memcached_next_upstream    
    語法: memcached_next_upstream error | timeout | invalid_response | not_found | off …;     
    默認值: error timeout;     
    配置段: http, server, location     
    指定在哪些狀態下請求將轉發到另外的負載均衡服務器上,僅當memcached_pass有兩個或兩個以上時使用。


  • memcached_pass    
    語法:memcached_pass address:port or socket;     
    默認值:none     
    配置段:location, if in location     
    指定memcached服務器地址。使用變量$memcached_key爲key查詢值,如果沒有相應的值則返回error_page 404。


  • memcached_read_timeout    
    語法:memcached_read_timeout time;     
    默認值:60s;     
    配置段:http, server, location     
    定義從memcached服務器讀取響應超時時間。


  • memcached_send_timeout    
    語法:memcached_send_timeout     
    默認值:60s     
    配置段:http, server, location     
    設置發送請求到memcached服務器的超時時間。

用法:$memcached_key變量:memcached key的值。


4.nginx memcached的增強版ngx_http_enhanced_memcached_module

基於nginx memcached 模塊的,添加的新特性有:

  • 自定義HTTP頭,如Content-Type, Last-Modified。

  • hash鍵可超過250個字符,memcached受限。

  • 通過HTTP請求將數據存儲到memcached。

  • 通過HTTP請求從memcached刪除數據。

  • 通過HTTP請求清除所有memcached緩存數據。

  • 通過HTTP請求獲取memcached狀態數據。

  • 鍵名空間管理,來部分刷新緩存。

  • 緩存通過If-Modified-Since頭和內容Last-Modified來回復304Not Modified請求。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章