Memcached高性能內存對象緩存系統
- Memcached 是一個高性能的分布式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信。
- 傳統數據都保存在關系型數據庫管理系統中(RDBMS關系型數據庫管理系統),客戶端請求時會從RDBMS中讀取數據並在瀏覽器中顯示,這樣當訪問量過大時或集中時,導致RSBMS負擔過重,數據庫響應惡化,瀏覽器中顯示延遲等嚴重問題
- Memcached 是一套分布式內存對象緩存系統,主要通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態 Web 應用的響應速度、提高可擴展性
二、Memcached緩存方式
- 與APC等本地緩存方式不同,Memcached是分布式的,也就是說它不是本地的;它基於網絡連接(當然它也可以使用localhost)方式完成服務,本身它是一個獨立於應用的程序或守護進程(Daemon方式)
- Memcached使用libevent庫(程序庫,封裝了linux的epoll、BSD類操作系統的kqueue等事件處理功能)實現網絡連接服務,理論上可以處理無限多的連接,但是它和Apache不同,它更多的時候是面向穩定的持續連接的,所以它實際的並發能力是有限制的;在保守情況下memcached的最大同時連接數為200,這和Linux線程能力有關系,當然這個數值是可以調整的
- Memcached內存使用方式也和APC不同。APC是基於共享內存和MMAP(將一個文件或者其它對象映射進內存)的,memcachd有自己的內存分配算法和管理方式,它和共享內存沒有關系,也沒有共享內存的限制,通常情況下,每個memcached進程可以管理2GB的內存空間,如果需要更多的空間,可以增加進程數
1.Memcached內存算法
- Memcached使用[slab allocation][1]機制分配和管理內存,按照預先規定的大小,將分配的內存分割成特定長度的內存塊,再把尺寸相同的內存塊分成組,數據在存放時,根據鍵值大小去匹配slab大小,找就近的slab存放
2.Memcached緩存策略
- LRU(最近最少使用)加上到期失效策略,當在memcached內存儲數據項時,可指定它在緩存的失效時間,默認為永久;當memcached服務器用完分配的內存時,失效的數據被首先替換,然後是最近未使用的數據
- LRU中,memcached使用的是一種Lazy Expiration策略(為給定key設置生存時間,當key過期時(生存時間為 0),它會被自動刪除),自己不會監控存入的key/vlue對是否過期,而是在獲取key值時查看記錄的時間戳,檢查key/value對空間是否過期,這樣可減輕服務器的負載
3.Memcached失效策略
Lazy expiration + LRU
- Lazy expiration作用:假如所存儲的數據項相當多的時候,在這時候進行監控的話,花費的代價是相當大的,所以memcached不會在過期監視上耗費過多的CPU時間,從而在性能方面也起到一定的優化作用
- LRU:memcached會優先使用已超時的空間,但是還是會有追加信息時空間不足的狀態,這時候會使用Least Recently Used(LRU)機制來分配空間,就從最近未被使用的記錄中搜索,並將其空間分配給新的記錄
4.Memcached分布式算法
當向memcached集群存入/取出key/value時,memcache客戶端會根據一定算法計算存入那臺服務器(第一步:選擇服務器,第二步:存取數據)
- 余數算法:先求得鍵的整數散列值,再除以服務器數量,根據余數存儲那臺服務器(特點:簡單、高效;但是擴展性差,服務器數量變更時,幾乎所有的緩存都會失效)
- 散列算法:先計算memcached的散列值,並將其分布在0—2^32的圓上,然後用同樣的方法算出存儲數據鍵的散列值並映射至圓上,最後從數據映射到的位置開始順順時針查找,將數據保存在查找到的第一臺服務器,如果超過2^32還是找不到,則將數據保存在第一臺memcached服務器上;如果添加一臺memcached服務器,則只在圓上添加的逆時針方向的第一臺服務器上的鍵會受到影響
一次性哈系原理
添加一臺服務器後
三、Memcached使用場景
- Memcached應使用在需要"分布式"場合,不需要"共享"的或服務器規模小都不適用;如果將Memcached用於向本地緩存方式使用,速度比PHP的APC慢幾十倍
- 一般Memcached都用於作為數據庫前端Cache(減少磁盤開銷、SQL解析),並且Memcached是使用內存緩存數據的,比用戶直接訪問數據庫擁有更高的性能,那麽在大型系統中,如訪問數據頻繁的,Memcached可大大降低數據庫壓力、提高效率
- 並且Memcached不光用於數據庫緩存,除了php中的資源不能存,其它的數據都能存儲(字符串、數值、數組、對象、布爾值、null、二進制(圖片、視頻))
註:但註意,由於Memcached使用內存緩存,而內存擁有易失性(斷電數據丟失),因此Memcached不能持久保存數據 - 那麽Memcached瓶頸在哪裏呢?Memcached瓶頸在於網絡,由於Memcached采用"分布式",需要大量數據交換,所以網絡帶寬會經常滿負荷
- Memcached不適用於PV不大的網站
- Memcached不適用於數據改動頻繁,但數據一改動就需要入庫的情況
- Memcached適用於數據改動頻繁、查詢頻繁的情況
- Memcached適用於數據庫改動不頻率、查詢頻繁的情況
四、Memcached原理
1.Memcached無緩存
- 客戶端訪問Web服務器
- Web服務器調用Memcache客戶端程序庫接口,連接Memcached服務器
- 如果Memcached沒有緩存客戶端所請求數據,則Memcache客戶端程序將請求轉發到數據庫服務器
- 數據庫服務器將數據返回給Memcache客戶端程序
- Memcache客戶端程序收到數據後會通過分布式算法決定將數據緩存到指定Memcached服務器,以供下次使用
- Memcached緩存完畢後,Memcache客戶端程序將數據返回給Web客戶端,Web客戶端再將數據返回給客戶端
2.Memcached有緩存
- 客戶端訪問Web服務器
- Web服務器調用Memcache客戶端程序庫接口,連接Memcached服務器
- 當Memcached中緩存客戶端所需數據,則Memcached將數據庫返回給Memcache客戶端程序
- Memcache客戶端再將數據交給Web服務器
- Web服務器將數據返回給客戶端
Memcached會在內存裏維護一張巨大的hash表,存儲經常被讀寫的一些數組與文件,在Server端啟動服務進程,在啟動時可以指定監聽的ip,自己的端口號,所使用的內存大小等幾個關鍵參數(采用了單進程,單線程,異步I/O,基於事件 (event_based) 的服務方式)使用libevent作為事件通知實現;每個Server只是對自己的數據進行管理Client端通過指定Server端的ip地址;數據以key -->value形式,key的值通過hash進行轉換,然後通過分布式算法確定對哪臺Sever存儲/獲取數據
五、案例:LAMP+Memcached
主機 | 系統 | IP | 網卡 | 軟件 |
---|---|---|---|---|
LAMP+Memcache(Client) | Centos 6.7 64Bit | 192.168.1.10 | vmnet1 | LAMP、memcache |
Memcached(Server) | Centos 6.7 64Bit | 192.168.1.100 | vmnet1 | libevent memcached |
Memcached(Server)
1.環境準備(Memcached)
vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 //網卡名稱
TYPE=Ethernet //網卡類型為以太網
ONBOOT=yes //開機自啟該網卡
NM_CONTROLLED=no //關閉NetworkManager
BOOTPROTO=static //網卡設置為靜態方式
IPADDR=192.168.1.100 //IP地址配置
NETMASK=255.255.255.0 //子網掩碼配置
/etc/init.d/network restart //重啟網絡服務
2.安裝memcached(Memcached)
安裝libevent
libevent是memcached 所依賴的異步時間通知庫,作為Memcached的依賴需要先完成安裝
tar -zxvf libevent-1.4.9-stable.tar.gz -C /usr/src/
cd /usr/src/libevent-1.4.9-stable/
./configure --prefix=/usr/local/libevent
make && make install
安裝Memcached
tar -zxvf memcached-1.2.6.tar.gz -C /usr/src/
cd /usr/src/memcached-1.2.6/
./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
選項:
--with-libevent:指定libevent事件庫位置
make && make install
echo "PATH=$PATH:/usr/local/memcached/bin">>/etc/profile
source /etc/profile
memcached -d -m 32m -p 11211 -u root //啟動Memcached服務
參數說明:
-d:啟動為守護進程
-m <num>:分配給Memcached使用的內存數量,單位是MB,默認為64MB
-u <username>:運行Memcached的用戶,僅當作為root運行時
-l <ip_addr>:(小寫L)監聽的服務器IP地址,默認為環境變量INDRR_ANY的值
-p <num>:設置Memcached監聽的端口,最好是1024以上的端口
-c <num>:設置最大並發連接數,默認為1024
-P <file>:設置保存Memcached的pid文件,與-d選擇同時使用
註:啟動過程中會出現"memcached : error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory"錯誤,這是由於Memcached沒有尋找到libevent庫,需在系統中增加libevent庫文件位置
解決方案:
vim /etc/ld.so.conf //打開系統額外加載庫定義文件
/usr/local/libevent/lib //增加libevent事件庫文件夾路徑
ldconfig //重新讀取/etc/ld.so.conf文件內容
memcached -d -m 32m -p 11211 -u root //無報錯
netstat -utpln | grep 11211 //查看Memcahced監聽端口
註:停止Memcached,可使用"pkill memcahced"及"killall memcached"等其它相關方式
LAMP+Memcache(Client)
1.環境準備(LAMP+Memcache)
vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 //網卡名稱
TYPE=Ethernet //網卡類型為以太網
ONBOOT=yes //開機自啟該網卡
NM_CONTROLLED=no //關閉NetworkManager
BOOTPROTO=static //網卡設置為靜態方式
IPADDR=192.168.1.10 //IP地址配置
NETMASK=255.255.255.0 //子網掩碼配置
/etc/init.d/network restart //重啟網絡服務
yum -y install zlib-devel libxml2-devel libtool-ltdl-devel //安裝依賴包
2.安裝LAMP(LAMP+Memcache)
安裝httpd
rpm -e httpd httpd-manual webalizer subversion mod_python mod_ssl mod_perl system-config-httpd php php-cli php-ldap php-common mysql dovecot --nodeps
//忽略依賴關系卸載系統已安裝的RPM包軟件(如果有的話,最好輸入確認下)
tar -zxvf httpd-2.2.17.tar.gz -C /usr/src/
cd /usr/src/httpd-2.2.17/
./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi
選項:
--enable-so:啟動動態加載模塊支持
--enable-rewrite:啟動網頁地址重寫功能
--enable-charset-lite:啟用字符集支持,以支持使用各種字符集編碼的網頁
--enable-cgi:啟用CGI腳本程序支持
make && make install
echo "PATH=$PATH:/usr/local/httpd/bin">>/etc/profile
source /etc/profile
cp /usr/local/httpd/bin/apachectl /etc/init.d/httpd
vim /etc/init.d/httpd
\# chkconfig:35 67 55
\# description: Apache Service
chkconfig --add httpd
安裝MySQL
rpm -e mysql-server mysql /卸載使用RPM方式安裝MySQL軟件包
yum -y install ncurses-devel cmake //安裝依賴軟件包
useradd -M -s /sbin/nologin mysql //新建程序用戶並加入mysql組,不允許登陸系統
tar -zxvf mysql-5.5.22.tar.gz -C /usr/src/
cd /usr/src/mysql-5.5.22/
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all -DSYSCONFDIR=/etc
選項:
-DCMAKE_INSTALL_PREFIX:指定MySQL安裝位置
-DDEFAULT_CHARSET:指定默認字符集編碼
-DDEFAULT_COLLATION:指定默認使用字符集校對規則
-DWITH-EXTRA-CHARSETS:指定額外支持的其他字符集編碼
-DSYSCONFDIR:配置文件存儲位置
make && make install
chown -R mysql:mysql /usr/local/mysql/
cp support-files/my-medium.cnf /etc/my.cnf
/usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ //執行初始化腳本
選項:
--user:指定運行用戶
--basedir:指定MySQL數據庫位置
--datadir:指定MySQL數據存儲位置
echo "PATH=$PATH:/usr/local/mysql/bin">>/etc/profile
//添加MySQL到搜索路徑,方便執行命令
source /etc/profile //立即讓profile文件內容生效
cp support-files/mysql.server /etc/init.d/mysqld
//拷貝服務腳本文件到/etc/rc.d/init.d位置
chmod +x /etc/init.d/mysqld
chkconfig --level 35 mysqld on
/etc/init.d/mysqld start 或 service mysqld start
netstat -utpln | grep mysqld
安裝PHP加密工具
rpm -e php php-cli php-ldap php-common php-mysql --nodeps
//忽略依賴關系卸載系統已安裝的RPM包軟件(如果有的話,最好輸入確認下)
tar -zxvf libmcrypt-2.5.8.tar.gz -C /usr/src/
cd /usr/src/libmcrypt-2.5.8/
./configure && make && make install
ln -s /usr/local/lib/libmcrypt.* /usr/lib/
tar -zxvf mhash-0.9.9.9.tar.gz -C /usr/src/
cd /usr/src/mhash-0.9.9.9/
./configure && make && make install
ln -s /usr/local/lib/libmhash.* /usr/lib/
tar -zxvf mcrypt-2.6.8.tar.gz -C /usr/src/
cd /usr/src/mcrypt-2.6.8/
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
./configure && make && make install
安裝PHP
tar -zxvf php-5.3.28.tar.gz -C /usr/src/
cd /usr/src/php-5.3.28/
./configure --prefix=/usr/local/php --with-mcrypt --with-apxs2=/usr/local/httpd/bin/apxs --with-config-file-path=/usr/local/php --enable-mbstring --with-mysql=/usr/local/mysql/
選項:
--with-mcrypt:加載數據加密等擴展工具支持
--with-apxs2:設置Apache HTTP Server提供的apxs模塊支持程序的文件位置
--with-config-file-path:設置PHP的配置文件php.ini將要存放的位置
--enable-mbstring:啟動多字節字符串功能,以便支持中文等代碼
--with-mysql:設置MySQL數據庫服務程序的安裝位置
make && make install
PHP配置(LAMP+Memcache)
cp /usr/src/php-5.3.28/php.ini-development /usr/local/php/php.ini
//拷貝PHP模板文件到PHP工作目錄
vim /usr/local/php/php.ini
226 short_open_tag = On //允許識別PHP短語法標記,即<?...?>
784 default_charset = "utf-8" //設置默認字符集為utf-8,註意刪除前面";"
tar -zxvf ZendGuardLoader-php-5.3-linux-glibc23-x86_64.tar.gz -C /usr/src/
cd /usr/src/ZendGuardLoader-php-5.3-linux-glibc23-x86_64/
cp php-5.3.x/ZendGuardLoader.so /usr/local/php/lib/php/
vim /usr/local/php/php.ini
zend_extension=/usr/local/php/lib/php/ZendGuardLoader.so
zend_loader.enable=1
vim /usr/local/httpd/conf/httpd.conf
310 AddType application/x-httpd-php .php
167 DirectoryIndex index.php index.html
httpd -t
/etc/init.d/httpd start
vim /usr/local/httpd/htdocs/test1.php //測試PHP網頁能否正確顯示
<?php
phpinfo();
?>
vim /usr/local/httpd/htdocs/test3.php
<?php
$link=mysql_connect(‘localhost‘,‘root‘,‘‘);
if($link) echo "恭喜你,數據庫連接成功啦!";
mysql_close();
?>
3.安裝Memcache(LAMP+Memcache)
tar -zxvf memcache-2.2.7.tgz -C /usr/src/
cd /usr/src/memcache-2.2.7/
/usr/local/php/bin/phpize //根據系統信息生成對應的configure文件
若出現報錯:
……
Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment variable. Then, rerun this script.
解決方法:
yum -y install autoconf
註:以上為解決方案,只當執行"/usr/local/php/bin/phpize"報錯時使用
./configure --enable-memcache --with-php-config=/usr/local/php/bin/php-config
make && make install
Build complete.
Don‘t forget to run ‘make test‘.
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/ //復制擴展目錄
vim /usr/local/php/php.ini
819 extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/" //指定目錄
820 extension = memcache.so //啟動擴展模塊
/etc/init.d/httpd restart
vim /usr/local/httpd/htdocs/test2.php
<?php
$memcache = new Memcache();
$memcache->connect(‘192.168.1.100‘,11211);
$memcache->set(‘key‘,‘Memcache test successful!‘,0,60);
$result = $memcache->get(‘key‘);
unset($memecache);
echo $result;
?>
//測試調用memcache程序接口來測試memcached服務器與客戶端系統工作是否正常
六、Memcached的使用
Memcached每個被存取的對象都有唯一的標識符key,存取操作均通過key進行,例如可以把後端數據庫中的select操作提取出來,然後對相應的SQL進行hash計算得出key,然後以這個key在memcached中查找數據,如果數據不存在,說明其尚未被寫入緩存中,緩存不存在時將key存儲在緩存中,並設置一個失效時間(比如1小時),在失效時間內的數據都是從緩存中提取,這樣就有效地減少了數據庫的壓力
數據存取命令:
- set:保存一個數據到服務器上,如已存在則覆蓋
- add:添加一個數據到服務器,但是服務器必須這個key是不存在的,能夠保證數據不會被覆蓋
- replace:替換一個已經存在的數據,如果數據不存在,就是類似set功能
- get:格式是:get <鍵>key;一個不為空的字符串組合,發送這個指令以後,等待服務器的返回;如果服務器端沒有任何數據,則返回"END",證明沒有不存在這個key,沒有任何數據,如果存在數據,則返回指定格式:VALUE <鍵><標記><數據長度>
- delete:刪除指令;delete <鍵><超時時間><超時時間> - timeout
- flush_all:這個指令執行後,服務器上所有緩存的數據都被刪除,並且返回
- stats:顯示當前所有 Memcache 服務器運行的狀態信息
如果只是想獲取部分項目的信息,可以指定參數,格式:stats <參數>:這個指令將只返回指定參數的項目狀態信息
參數:
stats
Pid:memcache 服務器的進程 ID
uptime:服務器已經運行的秒數
Time:服務器當前的 unix 時間戳
version:memcache 版本
pointer_size:當前操作系統的指針大小(32 位系統一般是 32bit)
rusage_user:進程的累計用戶時間
rusage_system:進程的累計系統時間
curr_items:服務器當前存儲的 items 數量
Total_items:從服務器啟動以後存儲的 items 總數量
Bytes:當前服務器存儲 items 占用的字節數
curr_connections:當前打開著的連接數
Total_connections:從服務器啟動以後曾經打開過的連接數
connection_structures:服務器分配的連接構造數
cmd_get:get 命令(獲取)總請求次數
cmd_set:set 命令(保存)總請求次數
get_hits:總命中次數
get_misses:總未命中次數
evictions:為獲取空閑內存而刪除的items數(分配給memcache的空間用滿後需要刪除舊的items來得到空間分配給新的items)
Bytes_read:總讀取字節數(請求字節數)
Bytes_written:總發送字節數(結果字節數)
Limit_maxbytes:分配給 memcache 的內存大小(字節)
threads:當前線程數
quit:退出
1.案例(Memcached)
yum -y install telnet
telnet 192.168.1.100 11211 //連接Memcached的11211端口
Trying 192.168.1.100...
Connected to 192.168.1.100.
Escape character is ‘^]‘.
set key 0 60 2
he //設置保存key的值
STORED //服務器返回結果,該處代表保存成功
get key //獲取key對應的鍵值
VALUE key 0 2
he
END
stats //顯示當前所有 Memcache 服務器運行的狀態信息
STAT pid 12863 //memcached 啟動的進程 ID
STAT uptime 4008 //到目前為止啟動了多少秒
STAT time 1464713917 //Unix時間(從1970年1月1日開始統計的秒數)
STAT version 1.2.6 //memcached 的版本信息
STAT pointer_size 64 //當前操作系統的指針大小
STAT rusage_user 0.278957 //進程的累計用戶時間
STAT rusage_system 0.371943 //進程的累計系統時間
STAT curr_items 1 //服務器當前存儲的items數量
STAT total_items 2 //從服務器啟動以後存儲的items總數量
STAT bytes 79 //當前服務器存儲items占用的字節數
STAT curr_connections 2 //當前的並發連接數
STAT total_connections 4 //總的連接數
STAT connection_structures 3 //服務器分配的連接構造數
STAT cmd_get 2 //執行 get 命令的次數
STAT cmd_set 2 //執行 set 命令的次數
STAT get_hits 2 //get 的命中次數
STAT get_misses 0 //get 的非命中數
STAT evictions 0 //為獲取空閑內存而刪除的 items 數
STAT bytes_read 98 //總讀取字節數(請求字節數)
STAT bytes_written 97 //總發送字節數(結果字節數)
STAT limit_maxbytes 33554432 //允許使用的最大內存容量
STAT threads 1 //當前線程數
END
quit //退出
Connection closed by foreign host.
2.總結
錯誤
Memcache 的協議的錯誤部分主要是三個錯誤提示之提示指令
- 普通錯誤信息:ERROR
- 客戶端錯誤:CLIENT_ERROR <錯誤信息>
- 服務器端錯誤:SERVER_ERROR <錯誤信息>
數據保存指令
- 數據保存是基本的功能,就是客戶端通過命令把數據返回過來,服務器端接收後進行處理
指令格式
<命令><鍵><標記><有效期><數據長度>
set key 0 60 10
服務器端的返回
- 數據保存成功(STORED)
- 數據保存失敗(NOT_STORED),一般是因為服務器端這個數據key已經存在了
- set後如無任何返回,一般為設置的數據長度未使用完,服務器等待使用完畢
Memcached高性能內存對象緩存系統