Memcached存儲單個item最大數據是在1MB內,如果數據超過1M,存取set和get是都是返回false,而且引起性能的問題。
我們之前對排行榜的數據進行緩存,由于排行榜在我們所有sql select查詢里面占了30%,而且我們排行榜每小時更新一次,所以必須對數據做緩存。為了清除緩存方便,把所有的用戶的數據放在同一key中,由于memcached:set的時候沒有壓縮數據。在測試服測試的時候,沒發現問題,當上線的時候,結果發現,在線人數剛剛490人的時候,服務器load average飄到7.9。然后我們去掉緩存,一下子就下降到0.59。
所以Memcahce不適合緩存大數據,超過1MB的數據,可以考慮在客戶端壓縮或拆分到多個key中。大的數據在進行load和uppack到內存的時候需要花很長時間,從而降低服務器的性能。
Memcached支持最大的存儲對象為1M。這個值由其內存分配機制決定的。
memcached默認情況下采用了名為Slab Allocator的機制分配、管理內存。在該機制出現以前,內存的分配是通過對所有記錄簡單地進行malloc和free來進行的。但是,這種方式會導致內存碎片,加重操作系統內存管理器的負擔,最壞的情況下,會導致操作系統比memcached進程本身還慢。Slab Allocator就是為解決該問題而誕生的。Slab Allocator的基本原理是按照預先規定的大小,將分配的內存分割成特定長度的塊,以完全解決內存碎片問題.
今天(2012-03-16)我們重新測試了memcached ::set的數據大小??赡苁俏覀冇胮hp的memcached擴展是最新版,set數據的時候是默認壓縮的。set 數據:
$ac = new memcahed(); $data = str_repeat('a', 1024* 1024); //1M的數據 $r = $ac->set('key', $data, 9999); //或者 $data = str_repeat('a', 1024* 1024*100);//100M的數據 $r = $ac->set('key', $data, 9999);
不論是1M的數據還是100M的數據,都能set成功。后來我發現,memcachedset數據的時候是默認壓縮的。由于這個這個是重復的字符串,壓縮率高達1000倍。因此100M的數據壓縮后實際也就100k而已。
當我設置:
$ac->setOption(memcahed::OPT_COMPRESSION,0); //不壓縮存儲數據。 $data = str_repeat('a', 1024* 1024); //1M數據 $r = $ac->set('key', $data, 9999);//1M的數據set不成功。
也就是說memcached server不能存儲超過1M的數據,但是經過客戶端壓縮數據后,只要小于1M的數據都能存儲成功。
memcached相關知識:
1、memcached的基本設置
1)啟動Memcache的服務器端
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.0.200 -p 12000 -c 256 -P /tmp/memcached.pid
-d選項是啟動一個守護進程,
-m是分配給Memcache使用的內存數量,單位是MB,我這里是10MB,
-u是運行Memcache的用戶,我這里是root,
-l是監聽的服務器IP地址,如果有多個地址的話,我這里指定了服務器的IP地址192.168.0.200,
-p是設置Memcache監聽的端口,我這里設置了12000,最好是1024以上的端口,
-c選項是最大運行的并發連接數,默認是1024,我這里設置了256,按照你服務器的負載量來設定,
-P是設置保存Memcache的pid文件,我這里是保存在 /tmp/memcached.pid,
2)如果要結束Memcache進程,執行:
# kill `cat /tmp/memcached.pid`
哈希算法將任意長度的二進制值映射為固定長度的較小二進制值,這個小的二進制值稱為哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式。如果散列一段明文而且哪怕只更改該
段落的一個字母,隨后的哈希都將產生不同的值。要找到散列為同一個值的兩個不同的輸入,在計算上是不可能的。
2、適用memcached的業務場景?
1)如果網站包含了訪問量很大的動態網頁,因而數據庫的負載將會很高。由于大部分數據庫請求都是讀操作,那么memcached可以顯著地減小數據庫負載。
2)如果數據庫服務器的負載比較低但CPU使用率很高,這時可以緩存計算好的結果( computed objects )和渲染后的網頁模板(enderred templates)。
3)利用memcached可以緩存session數據、臨時數據以減少對他們的數據庫寫操作。
4)緩存一些很小但是被頻繁訪問的文件。
5)緩存Web 'services'(非IBM宣揚的Web Services,譯者注)或RSS feeds的結果.。
3、不適用memcached的業務場景?
1)緩存對象的大小大于1MB
Memcached本身就不是為了處理龐大的多媒體(large media)和巨大的二進制塊(streaming huge blobs)而設計的。
2)key的長度大于250字符
3)虛擬主機不讓運行memcached服務
如果應用本身托管在低端的虛擬私有服務器上,像vmware, xen這類虛擬化技術并不適合運行memcached。Memcached需要接管和控制大塊的內存,如果memcached管理 的內存被OS或 hypervisor交換出去,memcached的性能將大打折扣。
4)應用運行在不安全的環境中
Memcached為提供任何安全策略,僅僅通過telnet就可以訪問到memcached。如果應用運行在共享的系統上,需要著重考慮安全問題。
5)業務本身需要的是持久化數據或者說需要的應該是database
4、 不能能夠遍歷memcached中所有的item
這個操作的速度相對緩慢且阻塞其他的操作(這里的緩慢時相比memcached其他的命令)。memcached所有非調試(non-debug)命令,例如add, set, get, fulsh等無論
memcached中存儲了多少數據,它們的執行都只消耗常量時間。任何遍歷所有item的命令執行所消耗的時間,將隨著memcached中數據量的增加而增加。當其他命令因為等待(遍歷所有item的命令執行完畢)而不能得到執行,因而阻塞將發生。
5、 memcached能接受的key的最大長度是250個字符
memcached能接受的key的最大長度是250個字符。需要注意的是,250是memcached服務器端內部的限制。如果使用的Memcached客戶端支持"key的前綴"或類似特性,那么key(前綴+原始key)的最大長度是可以超過250個字符的。推薦使用較短的key,這樣可以節省內存和帶寬。
6、 單個item的大小被限制在1M byte之內
因為內存分配器的算法就是這樣的。
詳細的回答:
1)Memcached的內存存儲引擎,使用slabs來管理內存。內存被分成大小不等的slabs chunks(先分成大小相等的slabs,然后每個slab被分成大小相等chunks,不同slab的chunk大小是不相等的)。chunk的大小依次從一個最小數開始,按某個因子增長,直到達到最大的可能值。如果最小值為400B,最大值是1MB,因子是1.20,各個slab的chunk的大小依次是:
slab1 – 400B;slab2 – 480B;slab3 – 576B …slab中chunk越大,它和前面的slab之間的間隙就越大。因此,最大值越大,內存利用率越低。Memcached必須為每個slab預先分配內存,因此如果設置了較小的因子和較大的最大值,會需要為Memcached提供更多的內存。
2)不要嘗試向memcached中存取很大的數據,例如把巨大的網頁放到mencached中。因為將大數據load和unpack到內存中需要花費很長的時間,從而導致系統的性能反而不好。如果確實需要存儲大于1MB的數據,可以修改slabs.c:POWER_BLOCK的值,然后重新編譯memcached;或者使用低效的malloc/free。另外,可以使用數據庫、MogileFS等方案代替Memcached系統。
7、 memcached的內存分配器是如何工作的?為什么不適用malloc/free???為何要使用slabs?
實際上,這是一個編譯時選項。默認會使用內部的slab分配器,而且確實應該使用內建的slab分配器。最早的時候,memcached只使用malloc/free來管理內存。然而,這種方式不能與OS的內存管理以前很好地工作。反復地malloc/free造成了內存碎片,OS最終花費大量的時間去查找連續的內存塊來滿足malloc的請求,而不是運行memcached進程。slab分配器就是為了解決這個問題而生的。內存被分配并劃分成chunks,一直被重復使用。因為內存被劃分成大小不等的slabs,如果item的大小與被選擇存放它的slab不是很合適的話,就會浪費一些內存。
8、memcached對item的過期時間有什么限制?
item對象的過期時間最長可以達到30天。memcached把傳入的過期時間(時間段)解釋成時間點后,一旦到了這個時間點,memcached就把item置為失效狀態,這是一個簡單但obscure的機制。
9、什么是二進制協議,是否需要關注?
二進制協議嘗試為端提供一個更有效的、可靠的協議,減少客戶端/服務器端因處理協議而產生的CPU時間。根據Facebook的測試,解析ASCII協議是memcached中消耗CPU時間最多的
環節。
10、 memcached的內存分配器是如何工作的?為什么不適用malloc/free???為何要使用slabs?
實際上,這是一個編譯時選項。默認會使用內部的slab分配器,而且確實應該使用內建的slab分配器。最早的時候,memcached只使用malloc/free來管理內存。然而,這種方式不能與OS的內存管理以前很好地工作。反復地malloc/free造成了內存碎片,OS最終花費大量的時間去查找連續的內存塊來滿足malloc的請求,而不是運行memcached進程。slab分配器就是為了解決這個問題而生的。內存被分配并劃分成chunks,一直被重復使用。因為內存被劃分成大小不等的slabs,如果item的大小與被選擇存放它的slab不是很合適的話,就會浪費一些內存。
11、memcached是原子的嗎?
所有的被發送到memcached的單個命令是完全原子的。如果您針對同一份數據同時發送了一個set命令和一個get命令,它們不會影響對方。它們將被串行化、先后執行。即使在多線程模式,所有的命令都是原子的。然是,命令序列不是原子的。如果首先通過get命令獲取了一個item,修改了它,然后再把它set回memcached,系統不保證這個item沒有被其他進程(process,未必是操作系統中的進程)操作過。memcached 1.2.5以及更高版本,提供了gets和cas命令,它們可以解決上面的問題。如果使用gets命令查詢某個key的item,memcached會返回該item當前值的唯一標識。如果客戶端程序覆寫了這個item并想把它寫回到memcached中,可以通過cas命令把那個唯一標識一起發送給memcached。如果該item存放在memcached中的唯一標識與您提供的一致,寫操作將會成功。如果另一個進程在這期間也修改了這個item,那么該item存放在memcached中的唯一標識將會改變,寫操作就會
失敗。
轉自:http://blog.csdn.net/hguisu/article/details/6163621
原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/3121