轉載請註明原文地址:http://www.javashuo.com/article/p-zqgsncbe-eq.htmlhtml
MemCache是一個高性能、「分佈式」的內存緩存系統,它經過在內存中緩存數據和對象來減小讀取數據庫的次數,從而提升了網站訪問的速度,減輕數據庫的負載。linux
MemCaChe是一個存儲鍵值對的HashMap,在內存中對任意的數據(好比字符串、對象等)使用key-value形式進行存儲。redis
數據能夠來自數據庫查詢、API調用結果返回,或者網頁傳輸過來的數據(session信息、request信息或者所攜帶的參數)。算法
一、在本機或者集羣服務器上安裝Memcache數據庫
(Ubuntu/Debian) sudo apt-get install libevent ibevent-dev sudo apt-get install memcached (Redhat/Fedora/Centos) yum install libevent libevent-devel yum install memcached
二、啓動memcache:使用 memcached命令api
cd到memcached目錄/bin下,經過 memcached [-options][value] 來啓動memcache。緩存
啓動選項:安全
三、memcache服務器運維服務器
咱們還能夠在終端窗口使用telnet指令,經過IP和端口鏈接到memcache服務器進行操做。session
telnet HOST PORT
四、memcache操做指令
1)存儲指令
2)查找與操做指令
3)運維指令
一、添加依賴
二、鏈接memcache服務器
// 鏈接 Memcached 服務,建立memcache客戶端對象 MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("ip", port));
三、經過memcache對象調用api進行存儲、查找操做,api的參數同上面第二點中的指令參數
// 存儲數據 Future fo = mcc.set(key, 有效期, 值); //查找數據 mcc.get(key)
四、操做完成後關閉鏈接,以避免佔用memcache服務器資源
// 關閉鏈接 mcc.shutdown();
一、memcache與redis的區別和聯繫
1)存儲數據類型區別
redis:支持較多的數據類型(String/list/set/sortset/hash)做爲值;每一個value最大數據存儲量爲1G;支持持久化;目前只支持在linux下運行。
memcache:各類框架(tp/yii等等)都支持使用;session的信息能夠很是方便的保存到memcache中,每一個key保存的數據量最大爲1M;不支持持久化,斷電重啓就沒有了。
2)分佈式模式區別
redis:主從模式,一個redis負責數據寫入,其餘多個redis負責數據讀取。
memcache:平均分攤模式,每一個子服務器之間都是平級的,每一個服務器都要執行數據的寫入、讀取操做。
3)聯繫
二者都是把數據保存在內存中,優化數據存取速度。
二、memcache的數據類型存儲
1)基本數據類型——轉化爲String字符串格式來存儲
2)引用類型對象——原型存儲
因爲原型存儲對資源的消耗比較大,爲了節省資源,能夠把引用類型信息都變爲字符串形式進行存儲,這時須要進行 序列化 操做。
三、memcache的分佈式
memcache的分佈式 不是經過架構手段去實現的,咱們只須要部署多臺memcache服務器,而後在代碼中爲memcache對象添加多個server便可。
其分佈式特性是內置好了的,無需咱們再經過架構手段實現一遍。
memcache自己有算法,能夠保證數據「平均」地存儲在不一樣的服務器裏邊。【注意:是平均,而不是複製,各臺memcache中存儲的內容是不一樣的。】
四、Memcache的訪問模型(參考:http://www.javashuo.com/article/p-ngxgekwb-cr.html)
MemCache雖然被稱爲"分佈式緩存",可是MemCache自己徹底不具有分佈式的功能,MemCache集羣之間不會相互通訊(與之造成對比的,好比JBoss Cache,某臺服務器有緩存數據更新時,會通知集羣中其餘機器更新緩存或清除緩存數據),所謂的"分佈式",徹底依賴於客戶端程序的實現[經過代碼]。
MemCache一次寫緩存的流程:
1)應用程序輸入須要寫緩存的數據
2)API將Key輸入路由算法模塊,路由算法根據Key和MemCache集羣服務器列表獲得一臺服務器編號
3)由服務器編號獲得MemCache及其的ip地址和端口號
4)API調用通訊模塊和指定編號的服務器通訊,將數據寫入該服務器,完成一次分佈式緩存的寫操做
讀緩存和寫緩存同樣,只要使用相同的路由算法和服務器列表,只要應用程序查詢的是相同的Key,MemCache客戶端老是訪問相同的客戶端去讀取數據,只要服務器中還緩存着該數據,就能保證緩存命中。
五、memcache路由算法(參考:http://www.javashuo.com/article/p-ngxgekwb-cr.html)
1)餘數Hash策略
例如,key的HashCode爲50,memcache服務器有3臺,則key.hashcode % 3 == 2,路由算法將key路由到第二臺服務器上進行存儲。
原理:因爲hashcode的隨機性,能夠保證數據「較爲平均」地分佈在memcache服務器集羣中。
缺點:服務器集羣伸縮性差。當memcache服務器集羣橫向擴展時,服務器數量變化,會致使一樣的key路由到新的服務器上,而舊路由器上的值不會被清除。
解決方案:
(1)在網站訪問量低谷時段,一般是深夜,技術團隊加班,擴容、重啓服務器;
(2)而後經過模擬請求的方式,對緩存內容從新讀寫一遍,逐漸預熱緩存,使緩存服務器中的數據從新分佈;
2)一致性Hash算法
一致性Hash算法經過一個叫作一致性Hash環的數據結構實現Key到緩存服務器的Hash映射。
咱們將服務器節點分佈在Hash環上,每一個key路由時,指向該key沿着hash環順時針最近的服務器節點上。
例如:服務器擴展前的Hash環
當咱們新增了一臺服務器時,環上新增了一個節點:
這樣會致使上圖中加粗部分緩存內容被從新分佈,但相比第一種策略,這樣已經優化了好多倍了。而且,集羣中緩存服務器節點越多,增長節點帶來的影響越小。
六、memcache的存儲原理(參考:http://www.javashuo.com/article/p-ngxgekwb-cr.html)
MemCache採用的內存分配方式是 固定空間分配:
1)MemCache將內存空間分爲一組slab
2)每一個slab下又有若干個page,每一個page默認是1M,若是一個slab佔用100M內存的話,那麼這個slab下應該有100個page
3)每一個page裏面包含一組chunk,chunk是真正存放數據的地方,同一個slab裏面的chunk的大小是固定的
4)有相同大小chunk的slab被組織在一塊兒,稱爲slab_class
若是slab中沒有chunk能夠分配了怎麼辦:若是MemCache啓動沒有追加-M(禁止LRU,這種狀況下內存不夠會報Out Of Memory錯誤),那麼MemCache會把這個slab中最近最少使用的chunk中的數據清理掉,而後放上最新的數據。
爲何MemCache存放的value大小是限制的:由於一個新數據過來,slab會先以page爲單位申請一塊內存,申請的內存最多就只有1M,因此value大小天然不能大於1M了。
七、memcache的特性與限制
1)MemCache中能夠保存的item數據量是沒有限制的,只要內存足夠
2)MemCache單進程在32位機中最大使用內存爲2G,64位機則沒有限制
3)Key最大爲250個字節,超過該長度沒法存儲
4)單個item最大數據是1MB,超過1MB的數據不予存儲
5)MemCache服務端是不安全的,好比已知某個MemCache節點的ip和port,能夠直接telnet過去,並經過flush_all讓已經存在的鍵值對當即失效
6)不可以遍歷MemCache中全部的item,由於這個操做的速度相對緩慢且會阻塞其餘的操做
7)MemCache的高性能源自於兩階段哈希結構:第一階段在客戶端,經過Hash算法根據Key值算出一個節點;第二階段在服務端,經過一個內部的Hash算法,查找真正的item並返回給客戶端。
8)MemCache設置添加某一個Key值的時候,傳入expiry爲0表示這個Key值永久有效,然而這個Key值也會在30天以後失效,這是在源碼中寫死了的。
一、session共享
一個大型網站或系統,每每部署在多臺服務器上。多臺服務器彼此之間須要共享session信息,這時能夠把session緩存在memcache中,而各服務器均可以從memcache中提取session進行分佈式處理的同時又能保持一致性。
二、網頁內容緩存
網站有一個頁面須要得到許多數據信息,而且這些數據信息在短期內不會發生變化時。能夠把這些數據得到出來存入到memacache中過去,供後續訪問。