memcached是一個分佈式,開源的數據存儲引擎。php
memcached是一款高性能的分佈式內存緩存服務器,經過減小查詢次數來抵消沉重緩慢的數據集或API調用、提升應用響應速度、提升可擴展性。ios
在高併發的場景下, 大量的讀/寫請求涌向數據庫, 此時磁盤IO將成爲瓶頸, 從而致使太高的響應延遲, 所以緩存應運而生.git
Memcached的工做方式是將關鍵詞和他們對應的值(最大能達到1MB)保存在一個關聯矩陣中(好比哈希表),延展和分佈在大量的虛擬服務器中。github
固然不管是單機緩存仍是分佈式緩存都有其適用場景和優缺點, 最多見的有redis和memcached. 本文主要是介紹memcached.redis
硬盤 --> 內存 --> 三級緩存 --> 二級緩存 --> 一級緩存算法
首先訪問較快的存儲介質, 若是命中且未生效則返回內容. 若是命中或失效則訪問較慢的存儲介質將內容返回同時更新緩存.docker
特色 | 描述 |
---|---|
協議簡單 | 它是基於文本行的協議,直接經過telnet在memcached服務器上可進行存取數據操做 |
基於libevent事件處理 | 異步I/O, 基於事件的單進程和單線程, 使用libevent做爲事件處理機制; |
內置內存存儲方式, 非持久性存儲 | 全部數據都保存在內存中,存取數據比硬盤快,當內存滿後,經過LRU算法自動刪除不使用的緩存,但沒有考慮數據的容災問題,重啓服務,全部數據會丟失。 |
分佈式 | 各個memcached服務器之間互不通訊,各自獨立存取數據,不共享任何信息。服務器並不具備分佈式功能,分佈式部署取決於memcache客戶端。 |
# 安裝依賴包
apt-get install libevent-dev
#安裝Memcached
wget http://memcached.org/latest
tar -zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure && make && make test && sudo make install
#啓動memcached
memcached -p 11211 -d -u root -P /tmp/memcached.pid
複製代碼
-P是表示使用TCP,默認端口爲11211 -d表示後臺啓動一個守護進程(daemon) -u表示指定root用戶啓動,默認不能用root用戶啓動 -P表示進程的pid存放地點,此處「p」爲大寫「P」 -l,後面跟IP地址,手工指定監聽IP地址,默認全部IP都在監聽 -m後面跟分配內存大小,以MB爲單位,默認爲64M -c最大運行併發鏈接數,默認爲1024 -f 塊大小增加因子,默認是1.25 -M 內存耗盡時返回錯誤,而不是刪除項,即不用LRU算法 在64位系統中,會報libevent-1.4.so.2文件沒法找到,解決辦法是把32位目錄裏的同名文件連接至64位目錄中,即像windows那樣創建快捷方式。 Shell > /usr/local/lib/libevent-1.4.so.2 /usr/lib64/libevent-1.4.so.2 啓動後若是發現沒有端口在監聽,是由於命動命令時帶pid參數的「p」是大寫「P」,你可能寫成小寫了。數據庫
// 運行一個內存限制爲1024MB的容器:
sudo docker run -name csphere-memcached -m 1024m -d -p 11211:11211 memcached:alpine
複製代碼
能夠查看Memcached:latest
使用的 Dockerfile, 來獲取 memcached在debian下的安裝方法windows
分類 | 方法 | 描述 |
---|---|---|
存 | set | 添加一個新條目到memcached或是用新的數據替換替換掉已存在的條目 |
存 | add | 當KEY不存在的狀況下,它向memcached存數據,不然,返回NOT_STORED響應 |
存 | replace | 當KEY存在的狀況下,它纔會向memcached存數據,不然返回NOT_STORED響應 |
存 | cas | 改變一個存在的KEY值 ,但它還帶了檢查的功能 |
存 | append | 在這個值後面插入新值 |
存 | prepend | 在這個值前面插入新值 |
取 | get | 取單個值 ,從緩存中返回數據時,將在第一行獲得KEY的名字,flag的值和返回的value長度,真正的數據在第二行,最後返回END,如KEY不存在,第一行就直接返回END |
取 | get_multi | 一次性取多個值 |
刪 | delete |
# 清空memcache數據
telnet 10.27.5.71 11211
flush_all
quit //退出telnet
複製代碼
yum -y install libmemcached.x86_64 libmemcached-devel.x86_64
cd /usr/src
git clone https://github.com/php-memcached-dev/php-memcached.git
cd php-memcached/
git checkout php7
/alidata/server/php/bin/phpize
./configure --with-php-config=/alidata/server/php/bin/php-config
make
make install
複製代碼
能夠經過命令行直接管理與監控也可經過nagios等監控軟件進行監控 命令行:緩存
// 若是在啓動時指定了IP及端口號,這裏要做相應改動,鏈接成功後命令
telnet 127.0.0.1 11211
複製代碼
命令 | 描述 |
---|---|
stats | 統計memcached的各類信息 |
stats reset | 從新統計數據 |
stats slabs | 顯示slabs信息,能夠詳細看到數據的分段存儲狀況 |
stats items | 顯示slab中的item數目 |
stats cachedump 1 0 | 列出slabs第一段裏存的KEY值 |
set/get | 保存/獲取數據 |
STAT evictions 0 | 表示要騰出新空間給新的item而移動的合法item數目 |
Memcached利用slab allocation機制來分配和管理內存,它按照預先規定的大小,將分配的內存分割成特定長度的內存塊,再把尺寸相同的內存塊分紅組,數據在存放時,根據鍵值 大小去匹配slab大小,找就近的slab存放,因此存在空間浪費現象。
傳統的內存管理方式是,使用完經過malloc分配的內存後經過free來回收內存,這種方式容易產生內存碎片並下降操做系統對內存的管理效率。
Memcached的內存管理制效率高,並且不會形成內存碎片,可是它最大的缺點就是會致使空間浪費。由於每一個 Chunk都分配了特定長度的內存空間,因此變長數據沒法充分利用這些空間。如圖二所示,將100個字節的數據緩存到128個字節的Chunk中,剩餘的28個字節就浪費掉了。
如何避免內存浪費
Memcached的緩存策略是**LRU(最近最少使用)**加上到期失效策略。當你在memcached內存儲數據項時,你有可能會指定它在緩存的失效時間,默認爲永久。當memcached服務器用完分配的內時,失效的數據被首先替換,而後也是最近未使用的數據。在LRU中,memcached使用的是一種Lazy Expiration策略,本身不會監控存入的key/vlue對是否過時,而是在獲取key值時查看記錄的時間戳,檢查key/value對空間是否過時,這樣可減輕服務器的負載。
當空間佔滿時
memcached不相互通訊,那麼memcached是如何實現分佈式的呢?
memcached的分佈式實現主要依賴客戶端的實現.
當數據到達客戶端, 客戶端實現的算法會根據」鍵」來決定保存的memcached服務器. 服務器選定後, 命令他保存數據. 取的時候也同樣, 客戶端根據」鍵」選擇服務器, 使用保存時候的相同算法就能保存選中和存的時候相同的服務器.
也就是說,存取數據分二步走,第一步,選擇服務器,第二步存取數據。
使用什麼算法選擇服務器呢?
client 使用Hash算法來完成數據分散存儲.
複製代碼
當向memcached集羣存入/取出key/value時,memcached客戶端程序根據必定的算法計算存入哪臺服務器,而後再把key/value值存到此服務器中。也就是說,存取數據分二步走,第一步,選擇服務器,第二步存取數據。
經常使用的算法有兩種: 餘數計算分散法 和 一致性Hash算法.
CRC($key)%N
複製代碼
客戶端首先根據key來計算CPC, 而後結果對服務器取模獲得memcached服務器節點
將server的hash值分配至0~2^32的圓環上, 用一樣的方法求出存儲數值鍵的hash值並映射到圓上. 而後從數據映射到的位置開始順時針查找, 將數據存放至找到的第一臺服務器上. 若是超過0~2^32還找不到, 則將數據存放至第一臺服務器.
若是新添/刪除一臺server, 在一致性hash算法下會有什麼影響?
如圖, 新添/刪除server時, 只在圓上增長服務器的逆時針方向的第一臺服務器上的鍵會受到影響。
優化一致性hash算法
優化後: 在物理機不多的狀況下, 只要虛擬節點足夠多, 也能使的key分佈相對均勻. 提高了算法的平衡性.
單調性是指若是已經有一些內容經過哈希分派到了相應的緩衝中,又有新的緩衝加入到系統中。哈希的結果應可以保證原有已分配的內容能夠被映射到新的緩衝中去,而不會被映射到舊的緩衝集合中的其餘緩衝區。
複製代碼
平衡性是指哈希的結果可以儘量分佈到全部的緩衝中去,這樣可使得全部的緩衝空間都獲得利用。
複製代碼
hash 算法並非保證絕對的平衡
對比點 | memcached | redis |
---|---|---|
數據結構 | 單一(存儲數據的類型都是String字符串類型) | 豐富(String、List、Set、Sortedset、Hash) |
內存使用率 | 使用簡單的key-value存儲,Memcached的內存利用率更高 | Redis採用hash結構來作key-value存儲,因爲其組合式的壓縮,其內存利用率會高於Memcached |
持久化 | 不能夠 | 能夠(能夠把數據隨時存儲在磁盤上) |
數據同步 | 不能夠 | 能夠 |
多核 | 可使用多核(多線程) | 單核 |
數據大小 | 單個key(變量)存放的數據有1M的限制 | 單個key(變量)存放的數據有1GB的限制 |
計算能力 | 無 | 自己有必定的計算功能 |
memcached和redis對過時數據的處理
Redis是懶處理,對有有效期的數據會作有效期的標識,在指定時間會對有過時時間的數據作處理。隨機取出一部分數據,檢查是否有過時數據,若是過時數據超過25/100,則反覆此過程
它使用libevent,能夠應付任意數量打開的鏈接(使用epoll,而非poll),使用非阻塞網絡IO,分佈式散列對象到不一樣的服務器,查詢複雜度是O(1)。
緩存命中率 = get_hits/cmd_get * 100%
一致性Hash
a. 在軟件工程的項目實戰中, 常常會遇到時間/空間的權衡, 緩存是權衡中被研究出的一種典型的技術, 而memcached又是此類技術中的佼佼者.
b. 在高併發環境下,大量的讀、寫請求涌向數據庫,此時磁盤IO將成爲瓶頸,從而致使太高的響應延遲,所以緩存應運而生。
c. 本文在理解緩存基本概念的狀況下介紹了memcached的分佈式算法實現原理