Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。
Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信
1)完整緩存,靜態緩存(易)
例如:商品分類,商品信息,將這些變動較少的(靜態)數據提前存放到內存裏,然後再對外提供服務。用戶訪問只讀取memcached緩存,不讀取數據庫。
2)熱點緩存(難)
需要前端程序配合,將熱點數據存放到內存中,用戶訪問這些數據,直接訪問到memcached緩存。第一次訪問非熱點數據時,memcached緩存沒有,就訪問數據庫,獲取數據返回給客戶端,同時在memcached中緩存一份,第二次訪問相同內容時,就不在訪問數據庫,用Memcached緩存直接返回數據。
以php的web網站集羣爲例,可以通過修改php.ini
[root@server_02 html]# egrep "session.save" /etc/php.ini|grep -v ";" session.save_handler = files session.save_path = "/var/lib/php/session"
修改結果爲:
session.save_handler = memcache --指定通過memcache進行緩存 session.save_path = "tcp://192.168.1.112:11211" --memcahced服務器的路徑
1) Memcached Repcached
一個單master單 slave的方案,但它的 master/slave都是可讀寫的,而且可以相互同步
2)memagent又名magent
每個magent節點又分別代理多個memcached服務節點,應用系統端使用magent pool來調用memcache進行存儲。通過magent的連接池放的值會分別存在magent代理的所有memcached服務上去。
3)負載均衡器採用一直性哈希,將數據分散在若干個memcached服務器上
特殊說明:Memcached的調度算法一般用一致性hash,提高緩存命中率,每臺Memcached都是一部分數據
1.程序端實現
程序加載所有的memcached服務器,通過對key進行hash(一致性哈希)存放緩存。
2.負載均衡器實現
通過對key進行hash(一致性哈希)存放緩存
注:一致性hash不但可以保證每個對象只請求對應唯一的memcahced服務器,而且保證單臺緩存服務器宕機,更新的緩存數據最少
1.完全基於內存
2.節點之間相互獨立
3.異步I/O模型,基於libevent模型的事件通知機制
4.緩存數據以key/value鍵值對形式存放
5.C/S模式架構,C語言編寫,總共代碼2000多行
6.數據存放在內存中,斷電會丟失數據
7.緩存空間存放滿之後,採用LRU算法刪除過期緩存數據
1、slab class
在memcached中,對元素的管理是以slab爲單元進行管理的。每個slab class對應一個或多個空間大小相同的chunk。參考下圖一。
2、chunk
存放元素的最小單元。用戶數據item(key、value等)最終會保存在chunk中。memcached會根據元素大小將其放到合適的slab class中。每一個slab class中的chunk空間大小是一樣的,所以元素存放進來後,chunk可能會有部分空間剩餘。參考下圖二、下圖三。
3、page
大小固定爲1MB。當slab class空間不足時,就會申請page,並將page按chunk的大小進行切割。
圖一 slab class邏輯結構圖
圖二 元素存入memcached會尋找最合適的slab class
圖三 元素放入chunk時可能會有空間浪費
memcached使用自己的內存管理機制,可以有效避免系統內存碎片,避免給操作系統帶來負擔。
啓動memcached時,以-m指定大小的內存將會用於數據的存放。默認情況下,這些內存會被分隔成1M的page。每個page在必要時分配給slab class,然後根據slab class裏chunk的大小,將page分隔成chunk。
一個page被賦給一個slab class後,它將不會再被移動。因爲內存空間有限,如果在slab class 3中使用了較多的page,那麼在slab class 4中就只能使用較少的page。可以這麼認爲,memcached是一個有很多更小的相互獨立的緩存系統,每一個更小的緩存系統實際上就是slab class。每個slab class都有它自己的統計信息以及自己的LRU。
在啓動memcached時,指定-vv參數,可以在啓動日誌中查看每個slab class的chunk大小。
[root@server_01 ~]# memcached -vv -u root 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
在slab class 1中,每個chunk大小爲96字節,每個頁面包含10922個chunk(或item)。這兩個數相乘,應該最近接1個page的大小(默認是1MB)。
當存儲元素時,它們將被放到最合適的slab class中。例如,50字節的元素(包含key、value等信息)將被存放到slab class 1中的chunk,根據之前的說明,此chunk中將會有30字節的空間浪費。如果存放數據總共有90字節,將被存放到slab class 2中,此時會有14字節的空間浪費。
Memcached啓動時,通過設置參數-f,可以設置每個slab class下chunk的空間增長率。儘量使每個chunk的size接近具體業務的size,減少內存空間浪費,提高內存利用率
與redis不同的是,memcached不會主動回收內存。memcached會重複使用失效數據的內存。
如果獲取了一個已失效的數據,memcached將會釋放內存。後續再將新的數據存放進來時,將會重用此內存。
根據LRU(最近最少使用)算法,元素將被踢出以讓給新的元素,或發現有過期的元素,它們的內存將被重用。如果元素還沒有失效(失效日期爲0或者將會在將來失效),slab class已經用完了所有空閒的chunk,並且沒有空閒的page可以分配給此slab class,此時將會執行LRU算法,踢出數據。
當存放新的元素時,內存也可能會被回收。如果在相應的slab class裏,既沒有空閒的chunk,也沒有空閒的page,memcached將會使用LRU算法查找應該被回收的元素。它將會查找LRU列表中尾部(最近最少使用)的一些元素,看它們是否已經失效,如果存在失效的元素,則將此元素佔用的空間重用。如果找不到失效的元素,那麼將踢出最尾部還沒有失效的元素。
1)安裝libevent(前提)
yum install libevent libevent-devle -y
也可以通過編譯安裝libevent包
2)安裝Memcached服務端
說明:Memcached是服務端
Memcache是客戶端
[root@server tools]# wget http://memcached.org/files/memcached-1.4.31.tar.gz [root@server_02 tools]# tar xf memcached-1.4.31.tar.gz [root@server_02 tools]# cd memcached-1.4.31 [root@server_02 memcached-1.4.31]# ./configure [root@server_02 memcached-1.4.31]# make && make install
3)啓動memcached服務
[root@server_02 memcached-1.4.31]# memcached -d -m 10m -u root -l 192.168.1.112 -p 11211-c 256 -P /tmp/memcached.pid [root@server_02 memcached-1.4.31]# ss -lntup|grep memcached udp UNCONN 0 0 192.168.1.112:11211 *:* users:(("memcached",833,27),("memcached",833,28),("memcached",833,29),("memcached",833,30)) tcp LISTEN 0 128 192.168.1.112:11211 *:* users:(("memcached",833,26)) [root@server_02 memcached-1.4.31]#
-d選項是以一個守護進程啓動,
-m是分配給Memcache使用的內存數量,單位是MB,我這裏是10MB,
-u是運行Memcache的用戶,我這裏是root,
-l是監聽的服務器IP地址,如果有多個地址的話,我這裏指定了服務器的IP地址192.168.1.112
-p是設置Memcache監聽的端口,最好是1024以上的端口,默認是11211
-c選項是最大運行的併發連接數,默認是1024,我這裏設置了256,按照你服務器的負載量來設定,
-P是設置保存Memcache的pid文件,我這裏是保存在 /tmp/memcached.pid,
注意:可以通過更改端口號,實現啓動多個memcached實例
4)關閉memcached服務
1.pkill memcached
2.kill `cat /tmp/memcached.pid`
5) memcached存儲數據測試(nc/telnet測試)
[root@server_02 memcached-1.4.31]# telnet 192.168.1.112 11211 Trying 192.168.1.112... Connected to 192.168.1.112. Escape character is '^]'. set key key2 0 0 4 CLIENT_ERROR bad command line format set key1 0 60 4 youd STORED get key1 VALUE key1 0 4 youd END delete key1 DELETED get key1 END
命令說明:
<command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n
a) <command name> 可以是”set”, “add”, “replace”。
“set”表示按照相應的<key>存儲該數據,沒有的時候增加,有的覆蓋。
“add”表示按照相應的<key>添加該數據,但是如果該<key>已經存在則會操作失敗。
“replace”表示按照相應的<key>替換數據,但是如果該<key>不存在則操作失敗
b) <key> 客戶端需要保存數據的key。
c) <flags> 是一個16位的無符號的整數(以十進制的方式表示)。
該標誌將和需要存儲的數據一起存儲,並在客戶端get數據時返回。
客戶可以將此標誌用做特殊用途,此標誌對服務器來說是不透明的。
d) <exptime> 過期的時間。
若爲0表示存儲的數據永遠不過時(但可被服務器算法:LRU 等替換)。
如果非0(unix時間或者距離此時的秒數),當過期後,服務器可以保證用戶得不到該數據(以服務器時間爲標準)。
e) <bytes> 需要存儲的字節數(不包含最後的”\r\n”),當用戶希望存儲空數據時,<bytes>可以爲0
f) 最後客戶端需要加上”\r\n”作爲”命令頭”的結束標誌。
<data block>\r\n
緊接着”命令頭”結束之後就要發送數據塊(即希望存儲的數據內容),最後加上”\r\n”作爲此次通訊的結束。
linux nc命令操作memcache方法實例
1)存儲數據:printf “set key 0 10 6\r\nresult\r\n” |nc 192.168.1.112 11211
2)獲取數據:printf “get key\r\n” |nc 192.168.1.112 11211
3)刪除數據:printf “delete key\r\n” |nc 192.168.1.112 11211
4)查看狀態:printf “stats\r\n” |nc 192.168.1.112 11211
5)模擬top命令查看狀態:watch “echo stats” |nc 192.168.1.112 11211
6)清空緩存:printf “flush_all\r\n” |nc 192.168.1.112 11211 (小心操作,清空了緩存就沒了
6)php安裝memcache客戶端(擴展memcache模塊)
參考:http://php.net/manual/zh/memcache.installation.php
tar xf memcache-3.0.6.tgz cd memcache-3.0.6 phpize ./configure --enable-memcache --with-php-config=/usr/bin/php-config --with-zlib-dir make && make install
安裝成功後,修改php.ini文件的一下兩項內容:
[root@server_02 html]# egrep "memcache.so|extension" /etc/php.ini|grep -v ";"
extension_dir = "/usr/lib64/php/modules/" ---擴展模塊的目錄
extension = memcache.so - --擴展的模塊名稱
用phpinfo查看下memcache是否加載成功
7)php程序測試memcached
php測試頁面代碼:
[root@server_02 html]# vim memcache.php <?php $memcache = new Memcache; $memcache->connect('192.168.1.112', 11211); $memcache->set('test', 'successs'); echo $memcache->get('test'); ?>
將以上代碼,放到memcache.php文件中,將memcache.php文件放到web服務目錄下/var/www/html裏
php頁面顯示內容:
wget http://www.junopen.com/memadmin/memadmin-1.0.12.tar.gz tar xf memadmin-1.0.12.tar.gz mv ./memadmin /var/www/html/memadmin --將memadmin目錄移動到web服務器目錄下
memadmin默認賬號密碼都是:admin
memadmin網頁效果圖:
1.如果啓動Memcached服務的時候遇到了
/usr/local/bin/memcached: error while loading shared libraries: libevent-1.2.so.1: cannot open shared object file: No such file or directory;
解決方案:
[root@localhost bin]# LD_DEBUG=libs memcached -v
[root@localhost bin]# ln -s /usr/lib/libevent-1.2.so.1 /usr/lib64/libevent-1.2.so.1
[root@localhost bin]# /usr/local/bin/memcached -d -m 100 -u root -p 11211 -c 1000 -P /tmp/memcached.pid
[root@localhost bin]# ps -aux
可以看到啓動的Memcached服務了.
2.把Memcached服務加載到Linux的啓動項中.萬一機器斷電系統重啓.那麼Memcached就會自動啓動了.
假如啓動Memcache的服務器端的命令爲:
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.1.112 -p 11211 -c 256 -P /tmp/memcached.pid容來自17jquery
想開機自動啓動的話,只需在/etc/rc.d/rc.local中加入一行,下面命令
/usr/local/memcached/bin/memcached -d -m 10 -p 12000 -u apache -c 256
上面有些東西可以參考一下:即,ip不指定時,默認是本機,用戶:最好選擇是:apache 或 deamon