近幾天,瀏覽了大量的memcached相關文章,又自己動手實踐了一番
至此,對memcached有了更加深入的了解
在繼續編寫memcached操作類(基於java_memcached-release)的同時
留下一些自認為比較重要的知識,算是總結一下吧
如果其中有理解不當的,請高手給予指點,萬分感謝!
也歡迎正在或即將使用memcached的朋友一起分享學習心得,有意者請email:inetwild@gmail.com
一、常用命令
- 將memcached.exe安裝為Windows服務:memcached.exe -d install
- 啟動memcached服務:memcached.exe -d start
- 啟動memcached服務(windows命令):net start "memcached Server"
- 停止memcached服務(windows命令):net stop "memcached Server"
- 連接到memcached控制台:telnet ServerIP 11211
- 打印當前memcached服務器狀態:stats
- 打印當前memcached服務器Items(記錄)的統計信息:stats items
- 打印當前memcached服務器Slab(分區)及Chunk(塊)的統計信息:stats slabs
- 打印指定Slab中的KEY列表(可用於遍歷items,但效率較低,慎用!):stats cachedump SlabId Limit_num。顯示結果:ITEM KeyName [ValueByteLength b; LastAccessTime s]。值得注意的是,經過測試確認:那個LastAccessTime並不是記錄到期時間,而是最后一次的get時間,並且get之后,也不會自動延長expiry(到期時間)。
- 添加新記錄:add KeyName 0 0 ValueByteLength [回車] ValueContent
- 刪除記錄 : delete KeyName
- 添加或更新記錄 : set KeyName 0 0 ValueByteLength [回車] ValueContent
- 更新記錄 : replace KeyName 0 0 ValueByteLength [回車] ValueContent
二、Think in memcached
- memcached預先將可支配的內存空間進行分區(Slab),每個分區里再分成多個塊(Chunk),但同一個分區里:塊的長度(bytes)是固定的。
- 可以將memcached的這種內存管理方式理解為Table,分區(Slab)就是列(Col),而塊(Chunk)就是這列下面相同寬度的單元格(Td)
- 雖然各個Slab的長度不同,但容量卻是相同的。例如:Slab Class1的Chunk長度:128,個數:8192,Slab Class1的內存容量:128 * 8192 = 1M;Slab Class2的Chunk長度:256,個數:4096,Slab Class2的內存容量:256 * 4096 = 1M。
- 有新的記錄要存入memcached時,首先根據記錄的長度查找剛好能夠容納下它的Slab,再找到這個分區里閑置的Chunk,存入即可。
- 內存浪費的一個小場景:要存入一個100bytes的記錄,但最合適的Slab卻是128bytes,那么每存入一個這樣的記錄,就會產生28bytes的閑置內存
- 將記錄從memcached刪除后,已經分配的內存(即Chunk),也不會被釋放,而是會重復利用,這樣就徹底解決了內存碎片的問題
- memcached采用“惰性”方式來應對記錄的超期問題,就是它不會主動去監視記錄是否超期,而是在每次get時查看記錄的時間戳,如果已超期就會扔掉。這樣的好處就是不會占用寶貴的CPU資源。比如,在使用flushAll命令清除全部items后,使用stats命令查看items統計數是不變的,除非get一個不存在的記錄之后,stats的統計結果才會減少1個,不過使用delete命令刪除記錄,stats的統計結果卻會馬上表現出來。
- 有新記錄入住時,memcached為它推薦房間(Slab)的優先級是:閑置的 > 該退房的(超期的) > 已有人卻很少過來住的(get命中數最少的)。這種方式簡稱:LRU
- memcached最大的特點就是“分布式”,可以為一個應用部署多個memcached服務器,根據其負載權重(weight),自動進行簡單而又有效的任務均衡。
- 當memcached向多個Server保存一條記錄時,會根據特定算法生成一個“鍵”,這個“鍵”決定了這條記錄會被打發到哪台服務器;同樣,當提取這條記錄時,也會根據同樣的算法得到這個“鍵”,那么也會清楚當初是哪台服務器接收的這條記錄,返回就沒問題了。
- 在將memcached用於生產環境時,最好根據存儲記錄的平均長度對memcached的Slab分區規則進行設置,來盡量減少內存浪費及最大化利用好內存資源。(具體方式不詳)
- 更多待補充
三、在Java項目中使用memcached
- 面向Java的memcached客戶端,目前為止我知道的有兩種:
- 阿里軟件:memcache-client-forjava
- gwhalin:Memcached-Java-Client
- 阿里的客戶端用的人蠻多的,據說效率也很不錯,以后有時間會好好學習一下,但我現在主要使用的還是第二種:java_memcached-release
- 剛開始使用的是java_memcached-release_1.6,算是比較老的版本了,提供的API較少,僅包含最常用的幾個命令。優點是支持壓縮功能,在add或set時,如果value大於指定bytes,會自動對其進行壓縮,個人覺得這個功能還是很實用的。
- 后來嘗試performance分支下的java_memcached-release_2.6.6,二進制包下載地址:https://github.com/gwhalin/Memcached-Java-Client/downloads
- 該分支由Schooner中國團隊開發完成,向你們致敬!
- 使用上與1.6的基本兼容,重載或新增了很多常用的函數,更方便了,主要是性能上有300%左右的提升,並且重新實現的連接池,修復了之前連接數太多所導致的OutOfMemory異常問題。但可惜的是,從2.6.1開始,不再支持壓縮功能,據說這樣可以減少CPU負擔。所以,需要將以前用1.6寫的JAVA初始化客戶端部分關於壓縮的兩個參數注釋掉:
- setCompressEnable
- setCompressThreshold
過幾天將發布本人基於java_memcached-release_2.6.6封裝的memcached操作類,支持服務器配置文件,對於沒有使用spring的項目還是很合適的。