Memcached基礎
What is Memcached ?
Free & open source, high-performance, distributed memory object caching system
一個開源,免費的高性能,分布式記憶體緩存系統。
在我們的應用程式中,一般會将資料庫的一些經常需要查詢用到的資料緩存至Memcached,以提高動态Web應用的響應速度。如下圖所示:
<a href="http://s3.51cto.com/wyfs02/M00/58/00/wKiom1SmQaGTfoRKAAE4oHmqY6s517.jpg" target="_blank"></a>
快速體驗Memcached
【關于libevent的簡要說明:libevent就是一個程式庫,他将Linux的epoll、BSD系統的kqueue等事件處理機制封裝成統一的接口,即使對伺服器的連接配接增加,也能發揮0(1)的性能。Memcached使用這個庫,可以在Linux平台上發揮其高性能。】
過程如下:
1
2
3
4
5
6
7
8
9
<code>tar</code> <code>-xf libevent-2.0.20-stable.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>libevent-2.0.20-stable</code>
<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/libevent</code>
<code>make</code>
<code>make</code> <code>install</code>
<code>tar</code> <code>-xf memcached-1.4.22.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>memcached-1.4.22</code>
<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/memached</code> <code>--with-libevent=</code><code>/usr/local/libevent/</code>
<code>make</code> <code>&& </code><code>make</code> <code>install</code>
啟動Memcached
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<code>[root@www bin]</code><code># ./memcached -p 11211 -m 64 -f 1.5 -u nobody -vvv -d</code>
<code>slab class 1: chunk size 80 perslab 13107</code>
<code>slab class 2: chunk size 120 perslab 8738</code>
<code>slab class 3: chunk size 184 perslab 5698</code>
<code>slab class 4: chunk size 280 perslab 3744</code>
<code>slab class 5: chunk size 424 perslab 2473</code>
<code>slab class 6: chunk size 640 perslab 1638</code>
<code>slab class 7: chunk size 960 perslab 1092</code>
<code>slab class 8: chunk size 1440 perslab 728</code>
<code>slab class 9: chunk size 2160 perslab 485</code>
<code>slab class 10: chunk size 3240 perslab 323</code>
<code>slab class 11: chunk size 4864 perslab 215</code>
<code>slab class 12: chunk size 7296 perslab 143</code>
<code>slab class 13: chunk size 10944 perslab 95</code>
<code>slab class 14: chunk size 16416 perslab 63</code>
<code>slab class 15: chunk size 24624 perslab 42</code>
<code>slab class 16: chunk size 36936 perslab 28</code>
<code>slab class 17: chunk size 55408 perslab 18</code>
<code>slab class 18: chunk size 83112 perslab 12</code>
<code>slab class 19: chunk size 124672 perslab 8</code>
<code>slab class 20: chunk size 187008 perslab 5</code>
<code>slab class 21: chunk size 280512 perslab 3</code>
<code>slab class 22: chunk size 420768 perslab 2</code>
<code>slab class 23: chunk size 631152 perslab 1</code>
<code>slab class 24: chunk size 1048576 perslab 1</code>
可以利用./memcached -h的方式來了解一些選項的作用:
-p <num> TCP port number to listen on (default: 11211) 指定端口
-l <addr> interface to listen on (default: INADDR_ANY, all addresses)
監聽位址,想一想,如果我們的機器上有多個網卡我們監聽在哪個網卡上呢?
-d run as a daemon 表示以一個背景服務的方式運作
-u <username> assume identity of <username> (only when run as root)
以哪個使用者的身份運作
-m <num> max memory to use for items in megabytes (default: 64 MB)
以M為機關指定最大的記憶體空間
-f <factor> chunk size growth factor (default: 1.25)
指定增長因子
-n <bytes> minimum space allocated for key+value+flags (default: 48)
最小存儲機關。實際上,這裡指定的是最小的slab chunk大小
在上面啟動過程中,我們使用了-vvv的方式輸出了啟動過程的詳細資訊,那麼slab class , chunk這些是什麼呢?增長因子又是幹什麼的?
端口驗證:
<code>[root@www ~]</code><code># netstat -tnlp | grep 11211</code>
<code>tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 3292</code><code>/memcached</code>
<code>tcp 0 0 :::11211 :::* LISTEN 3292</code><code>/memcached</code>
Memcached啟動後,我們怎麼連接配接進行操作呢?
要知道Memcached是基于Client/Server架構的,上面的是啟動Server端,表示Memcached已經有64M記憶體空間來進行緩存資料管理。至于設定哪些緩存資料,資料有效期是多少等這些都是用戶端的事情。很多語言都實作了Memcached用戶端,比如Java/PHP等。需要注意的是,Memcached的一個重要特征--協定簡單。比如,我們就可以使用telnet來操作Memcached:
<code>[root@www ~]</code><code># telnet 192.168.204.88 11211</code>
<code>Trying 192.168.204.88...</code>
<code>Connected to www.zfz2.com (192.168.204.88).</code>
<code>Escape character is </code><code>'^]'</code><code>.</code>
<code>stats</code>
stats指令可以擷取到Memcached運作時相關資訊。
一些常用指令:
add指令 添加新鍵
add keyname flag timeout datasize
<code>add name 0 30 5</code>
<code>hello</code>
<code>STORED</code>
get指令 取得鍵值
get keyname
<code>get name</code>
<code>VALUE name 0 5</code>
<code>END</code>
set 無條件設定一個鍵
說白了,就是有鍵則覆寫,無鍵則添加。
set keyname flag timeout datasize
replace 替換已經存在的KEY
replace keyname flag timeout datasize
append keyname flag timeout append_datasize
prepend keyname flag timeout prepend_datasize
<code>add name 0 60 5</code>
<code>append name 0 60 2</code>
<code>aa</code>
<code>VALUE name 0 7</code>
<code>helloaa</code>
incr keyname increments 對鍵值增長
decr keyname decrements 對鍵值減少
<code>add score 0 120 1</code>
<code>1</code>
<code>incr score 2</code>
<code>3</code>
<code>get score</code>
<code>VALUE score 0 1</code>
delete keyname 删除指定鍵
flush_all 清理所有鍵
stats 狀态資訊
quit 表示退出
version 檢視版本
Memcached的記憶體存儲和删除機制
Memcached是一個緩存伺服器,并且它認為自己緩存的資料并不是關鍵性資料,也就是如果Memcached重新開機,緩存資料會丢失,需要重建立立。Memcached對高可用的支援不是很好,但是對分布式提供了很好的支援。下面我們來分析下Memcached的記憶體存儲機制:
Memcached的記憶體存儲機制采用了Slab Allocator的方式,按照預先規定的大小,将配置設定的記憶體分割成特定長度的塊,以減少記憶體碎片問題。Slab Allocator可以重複使用以配置設定的記憶體。如下圖所示:
<a href="http://s3.51cto.com/wyfs02/M00/58/00/wKioL1SnTinAkEbvAAFO-dwM2f8650.jpg" target="_blank"></a>
有多個Slab Class類别,每一個Slab Class裡面有多個相同大小的Chunk,而Chunk就是Memcached存儲資料的最小單元。當Memcached接受到資料需要緩存時,會選擇最适合資料大小的Slab,然後從Slab中選擇空閑的Chunk進行存儲。當然這種方式是無法避免記憶體浪費的。
在啟動Memcached時,我們指定了-f選項,其實是在指定Slab中Chunk大小的增長因子,這是Memcached為我們提供的一個可以進行調優的選項。我們可以根據用戶端緩存資料的大小,做一個預估,通過增長因子來調整Slab的差别,以獲得最恰當的設定。
在Memcached中緩存資料的時候,我們可以指定資料的失效期,可以指定到秒。那麼如果時間到了,Memcached會怎麼做呢?
Memcached并不會釋放已經配置設定的記憶體,逾時後,用戶端就無法在看到該記錄了。Memcached的删除機制思想如下:
LAZY機制
Memcached内部不會去監控記錄是否過期,而是在get的時候去判斷一下時間戳,這樣就知道是不是過期了。這樣的話,Memcached因為LAZY的機制不會在這個方面去占用CPU。
LRU算法
最近最少使用原理,當Memcached空間不足時,要清理,怎麼清理呢?就是清理那些最近未被使用的記錄的空間,将這些空間重新配置設定給新的記錄。
Memcached的分布式機制與一緻性雜湊演算法
當我們使用多台Memcached來緩存資料時,就利用到了Memcached的分布式。Memcached的分布式的最大特點是不互相通信。在分布式的情況下,當我們要儲存一個鍵時,可以簡單的根據鍵計算一個值,進而決定存儲至哪個Memcached中,當要get這個鍵的時候,利用同樣的方式到對應的Memcached伺服器中去取。比如,我們有10台Memcached(編号0-9),現在要儲存一個key,通過對key進行計算,比如取得它的HASH值,然後對10取餘,假設得到8,我們就将這個KEY存儲至編号為8的伺服器中。這樣的話,雖然算法上簡單,存取上實作了分布式,但是有一個明顯的缺點,就是如果增加或者減少了Memcached的節點個數,我們的大部分緩存就失效了,需要重建立立了。【原因在于取餘的結果發生了巨變】那麼有沒有一種方式,當我們增加或者減少Memcached節點個數時,帶來的影響最小呢?
關于一緻性HASH算法(Consistent Hashing)
<a href="http://s3.51cto.com/wyfs02/M01/58/03/wKiom1SnVK6A-pyRAAFR1OdEa2U133.jpg" target="_blank"></a>
基本原理說明:
有一個HASH環,分布着2的32次方個點,然後求出各個Memcached伺服器的HASH值,将其置于環上的各個點上。用相同的方式計算需要儲存的資料的鍵的HASH值,并映射到環上的位置,從映射處開始順時針開始查找最近的Memcached,找到後就儲存至這個伺服器。如果要取得資料,也采用相同的方式定位伺服器。
這種算法就是一緻性HASH算法,通過這樣可以在添加、删除伺服器時,最大限度的抑制鍵的重新分布。
本文轉自zfz_linux_boy 51CTO部落格,原文連結:http://blog.51cto.com/zhangfengzhe/1598626,如需轉載請自行聯系原作者