防僞碼:萬丈紅塵三杯酒,千秋大業一壺茶。
javascript
1、MemCache簡php
sessioncss
MemCache是一個自由、源碼開放、高性能、分佈式的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫的負載。它經過在內存中緩存數據和對象來減小讀取數據庫的次數,從而提升了網站訪問的速度。 MemCaChe是一個存儲鍵值對的HashMap,在內存中對任意的數據(好比字符串、對象等)所使用的key-value存儲,數據能夠來自數據庫調用、API調用,或者頁面渲染的結果。MemCache設計理念就是小而強大,它簡單的設計促進了快速部署、易於開發並解決面對大規模的數據緩存的許多難題,而所開放的API使得MemCache能用於Java、C/C++/C#、Perl、Python、PHP、Ruby等大部分流行的程序語言。html
另外,說一下爲何會有Memcache和memcached兩種名稱?其實Memcache是這個項目的名稱,而memcached是它服務器端的主程序文件名java
MemCache的官方網站爲 http://memcached.org/node
MemCache訪問模型mysql
爲了加深對memcache的理解,以memcache爲表明的分佈式緩存,訪問模型以下:linux
特別澄清一個問題,MemCache雖然被稱爲」分佈式緩存」,可是MemCache自己徹底不具有分佈式的功能,MemCache集羣之間不會相互通訊(與之造成對比的,好比JBoss Cache,某臺服務器有緩存數據更新時,會通知集羣中其餘機器更新緩存或清除緩存數據),所謂的」分佈式」,徹底依賴於客戶端程序的實現,就像上面這張圖的流程同樣。nginx
同時基於這張圖,理一下MemCache一次寫緩存的流程:c++
一、應用程序輸入須要寫緩存的數據
二、API將Key輸入路由算法模塊,路由算法根據Key和MemCache集羣服務器列表獲得一臺服務器編號
三、由服務器編號獲得MemCache及其的ip地址和端口號
四、API調用通訊模塊和指定編號的服務器通訊,將數據寫入該服務器,完成一次分佈式緩存的寫操做
讀緩存和寫緩存同樣,只要使用相同的路由算法和服務器列表,只要應用程序查詢的是相同的Key,MemCache客戶端老是訪問相同的客戶端去讀取數據,只要服務器中還緩存着該數據,就能保證緩存命中。
這種MemCache集羣的方式也是從分區容錯性的方面考慮的,假如Node2宕機了,那麼Node2上面存儲的數據都不可用了,此時因爲集羣中Node0和Node1還存在,下一次請求Node2中存儲的Key值的時候,確定是沒有命中的,這時先從數據庫中拿到要緩存的數據,而後路由算法模塊根據Key值在Node0和Node1中選取一個節點,把對應的數據放進去,這樣下一次就又能夠走緩存了,這種集羣的作法很好,可是缺點是成本比較大。
一致性Hash算法
從上面的圖中,能夠看出一個很重要的問題,就是對服務器集羣的管理,路由算法相當重要,就和負載均衡算法同樣,路由算法決定着究竟該訪問集羣中的哪臺服務器,先看一個簡單的路由算法。
一、餘數Hash
簡單的路由算法可使用餘數Hash:用服務器數目和緩存數據KEY的hash值相除,餘數爲服務器列表下標編號,假如某個str對應的HashCode是5二、服務器的數目是3,取餘數獲得1,str對應節點Node1,因此路由算法把str路由到Node1服務器上。因爲HashCode隨機性比較強,因此使用餘數Hash路由算法就能夠保證緩存數據在整個MemCache服務器集羣中有比較均衡的分佈。
若是不考慮服務器集羣的伸縮性,那麼餘數Hash算法幾乎能夠知足絕大多數的緩存路由需求,可是當分佈式緩存集羣須要擴容的時候,就難辦了。
就假設MemCache服務器集羣由3臺變爲4臺吧,更改服務器列表,仍然使用餘數Hash,52對4的餘數是0,對應Node0,可是str原來是存在Node1上的,這就致使了緩存沒有命中。再舉個例子,原來有HashCode爲0~19的20個數據,那麼:
那麼不妨舉個例子,原來有HashCode爲0~19的20個數據,那麼:
如今擴容到4臺,加粗標紅的表示命中:
若是擴容到20+的臺數,只有前三個HashCode對應的Key是命中的,也就是15%。固然現實狀況確定比這個複雜得多,不過足以說明,使用餘數Hash的路由算法,在擴容的時候會形成大量的數據沒法正確命中(其實不只僅是沒法命中,那些大量的沒法命中的數據還在原緩存中在被移除前佔據着內存)。在網站業務中,大部分的業務數據度操做請求上事實上是經過緩存獲取的,只有少許讀操做會訪問數據庫,所以數據庫的負載能力是以有緩存爲前提而設計的。當大部分被緩存了的數據由於服務器擴容而不能正確讀取時,這些數據訪問的壓力就落在了數據庫的身上,這將大大超過數據庫的負載能力,嚴重的可能會致使數據庫宕機。
這個問題有解決方案,解決步驟爲:
(1)在網站訪問量低谷,一般是深夜,技術團隊加班,擴容、重啓服務器
(2)經過模擬請求的方式逐漸預熱緩存,使緩存服務器中的數據從新分佈
二、一致性Hash算法
一致性Hash算法經過一個叫作一致性Hash環的數據結構實現Key到緩存服務器的Hash映射。簡單地說,一致性哈希將整個哈希值空間組織成一個虛擬的圓環(這個環被稱爲一致性Hash環),如假設某空間哈希函數H的值空間是0~2^32-1(即哈希值是一個32位無符號×××),整個哈希空間以下:
下一步將各個服務器使用H進行一個哈希計算,具體可使用服務器的IP地址或者主機名做爲關鍵字,這樣每臺機器能肯定其在上面的哈希環上的位置了,而且是按照順時針排列,這裏咱們假設三臺節點memcache經計算後位置以下
接下來使用相同算法計算出數據的哈希值h,並由此肯定數據在此哈希環上的位置
假如咱們有數據A、B、C、D、4個對象,通過哈希計算後位置以下:
根據一致性哈希算法,數據A就被綁定到了server01上,D被綁定到了server02上,B、C在server03上,是按照順時針找最近服務節點方法
這樣獲得的哈希環調度方法,有很高的容錯性和可擴展性:
假設server03宕機
能夠看到此時C、B會受到影響,將B、C被重定位到Server01。通常的,在一致性哈希算法中,若是一臺服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一臺服務器(即順着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響。
考慮另一種狀況,若是咱們在系統中增長一臺服務器Memcached Server 04:
此時A、D、C不受影響,只有B須要重定位到新的Server04。通常的,在一致性哈希算法中,若是增長一臺服務器,則受影響的數據僅僅是新服務器到其環空間中前一臺服務器(即順着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響。
綜上所述,一致性哈希算法對於節點的增減都只需重定位環空間中的一小部分數據,具備較好的容錯性和可擴展性。
一致性哈希的缺點:在服務節點太少時,容易由於節點分部不均勻而形成數據傾斜問題。咱們能夠採用增長虛擬節點的方式解決。
更重要的是,集羣中緩存服務器節點越多,增長/減小節點帶來的影響越小,很好理解。換句話說,隨着集羣規模的增大,繼續命中原有緩存數據的機率會愈來愈大,雖然仍然有小部分數據緩存在服務器中不能被讀到,可是這個比例足夠小,即便訪問數據庫,也不會對數據庫形成致命的負載壓力。
MemCache實現原理
首先要說明一點,MemCache的數據存放在內存中
一、訪問數據的速度比傳統的關係型數據庫要快,由於Oracle、MySQL這些傳統的關係型數據庫爲了保持數據的持久性,數據存放在硬盤中,IO操做速度慢
二、MemCache的數據存放在內存中同時意味着只要MemCache重啓了,數據就會消失
三、既然MemCache的數據存放在內存中,那麼勢必受到機器位數的限制,32位機器最多隻能使用2GB的內存空間,64位機器能夠認爲沒有上限
而後咱們來看一下MemCache的原理,MemCache最重要的是內存如何分配的,MemCache採用的內存分配方式是固定空間分配,以下圖所示:
這張圖片裏面涉及了slab_class、slab、page、chunk四個概念,它們之間的關係是:
一、MemCache將內存空間分爲一組slab
二、每一個slab下又有若干個page,每一個page默認是1M,若是一個slab佔用100M內存的話,那麼這個slab下應該有100個page
三、每一個page裏面包含一組chunk,chunk是真正存放數據的地方,同一個slab裏面的chunk的大小是固定的
四、有相同大小chunk的slab被組織在一塊兒,稱爲slab_class
MemCache內存分配的方式稱爲allocator(分配運算),slab的數量是有限的,幾個、十幾個或者幾十個,這個和啓動參數的配置相關。
MemCache中的value存放的地方是由value的大小決定的,value老是會被存放到與chunk大小最接近的一個slab中,好比slab[1]的chunk大小爲80字節、slab[2]的chunk大小爲100字節、slab[3]的chunk大小爲125字節(相鄰slab內的chunk基本以1.25爲比例進行增加,MemCache啓動時能夠用-f指定這個比例),那麼過來一個88字節的value,這個value將被放到2號slab中。放slab的時候,首先slab要申請內存,申請內存是以page爲單位的,因此在放入第一個數據的時候,不管大小爲多少,都會有1M大小的page被分配給該slab。申請到page後,slab會將這個page的內存按chunk的大小進行切分,這樣就變成了一個chunk數組,最後從這個chunk數組中選擇一個用於存儲數據。
若是這個slab中沒有chunk能夠分配了怎麼辦,若是MemCache啓動沒有追加-M(禁止LRU,這種狀況下內存不夠會報Out Of Memory錯誤),那麼MemCache會把這個slab中最近最少使用的chunk中的數據清理掉,而後放上最新的數據。
Memcache的工做流程:
一、檢查客戶端的請求數據是否在memcached中,若是有,直接把請求數據返回,再也不對數據庫進行任何操做,路徑操做爲①②③⑦。
二、若是請求的數據不在memcached中,就去查數據庫,把從數據庫中獲取的數據返回給客戶端,同時把數據緩存一份到memcached中(memcached客戶端不負責,須要程序明確實現),路徑操做爲①②④⑤⑦⑥。
三、每次更新數據庫的同時更新memcached中的數據,保證一致性。
四、當分配給memcached內存空間用完以後,會使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效數據首先被替換,而後再替換掉最近未使用的數據。
Memcached特徵:
協議簡單:
它是基於文本行的協議,直接經過telnet在memcached服務器上可進行存取數據操做
注:文本行的協議:指的是信息以文本傳送,一個信息單元傳遞完畢後要傳送換行。好比對於HTTP的GET請求來講,GET /index.html HTTP/1.1是一行,接下去每一個頭部信息各佔一行。一個空行表示整個請求結束
基於libevent事件處理:
Libevent是一套利用C開發的程序庫,它將BSD系統的kqueue,Linux系統的epoll等事件處理功能封裝成一個接口,與傳統的select相比,提升了性能。
內置的內存管理方式:
全部數據都保存在內存中,存取數據比硬盤快,當內存滿後,經過LRU算法自動刪除不使用的緩存,但沒有考慮數據的容災問題,重啓服務,全部數據會丟失。
分佈式
各個memcached服務器之間互不通訊,各自獨立存取數據,不共享任何信息。服務器並不具備分佈式功能,分佈式部署取決於memcache客戶端。
Memcache的安裝
分爲兩個過程:memcache服務器端的安裝和memcached客戶端的安裝。
所謂服務器端的安裝就是在服務器(通常都是linux系統)上安裝Memcache實現數據的存儲。
所謂客戶端的安裝就是指php(或者其餘程序,Memcache還有其餘不錯的api接口提供)去使用服務器端的Memcache提供的數據,須要php添加擴展。
PHP的Memcache
2、centos7.2+nginx+php+memcache+mysql
環境描述:
OS:
[root@www ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core)
nginx和php: nginx-1.10.2.tar.gz php-5.6.27.tar.gz ip地址:192.168.31.141/24 memcache: memcached-1.4.33.tar.gz ip地址:192.168.31.250/24 mysql: mysql-5.7.13.tar.gz ip地址:192.168.31.225/24
一、安裝nginx(在192.168.31.141主機操做)
解壓zlib
[root@www ~]# tar zxf zlib-1.2.8.tar.gz
說明:不須要編譯,只須要解壓就行。
解壓pcre
[root@www ~]# tar zxf pcre-8.39.tar.gz
說明:不須要編譯,只須要解壓就行。
[root@www ~]# yum -y install gcc gcc-c++ make libtool openssl openssl-devel
下載nginx的源碼包:
http://nginx.org/download
解壓源碼包:
[root@www ~]# tar zxf nginx-1.10.2.tar.gz [root@www ~]# cd nginx-1.10.2/ [root@www ~]# groupadd www #添加www組 [root@www ~]# useradd -g www www -s /sbin/nologin #建立nginx運行帳戶www並加入到www組,不容許www用戶直接登陸系統
[root@www nginx-1.10.2]# ./configure --prefix=/usr/local/nginx1.10 --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre=/root/pcre-8.39 --with-zlib=/root/zlib-1.2.8 --with-http_ssl_module --with-http_gzip_static_module --user=www --group=www [root@www nginx-1.10.2]# make&& make install
注:
--with-pcre:用來設置pcre的源碼目錄。
--with-zlib:用來設置zlib的源碼目錄。
由於編譯nginx須要用到這兩個庫的源碼。
[root@www nginx-1.10.2]# ln -s /usr/local/nginx1.10/sbin/nginx /usr/local/sbin/ [root@www nginx-1.10.2]# nginx -t
啓動nginx
[root@www nginx-1.10.2]# nginx [root@www nginx-1.10.2]# netstat -anpt | grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9834/nginx: master [root@www nginx-1.10.2]# firewall-cmd --permanent --add-port=80/tcp success [root@www nginx-1.10.2]# firewall-cmd --reload success
啓動後能夠再瀏覽器中打開頁面,會顯示nginx默認頁面。
二、安裝php
安裝libmcrypt
[root@www ~]# tar zxf libmcrypt-2.5.7.tar.gz [root@www ~]# cd libmcrypt-2.5.7/ [root@www libmcrypt-2.5.7]# ./configure --prefix=/usr/local/libmcrypt && make && make install [root@www ~]# yum -y install libxml2-devel libcurl-devel openssl-devel bzip2-devel [root@www ~]# tar zxf php-5.6.27.tar.gz [root@www ~]# cd php-5.6.27/ [root@www php-5.6.27]#./configure --prefix=/usr/local/php5.6 --with-mysql=mysqlnd --with-pdo-mysql=mysqlnd --with-mysqli=mysqlnd --with-openssl --enable-fpm --enable-sockets --enable-sysvshm --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --with-mhash --with-mcrypt=/usr/local/libmcrypt --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-bz2 --enable-maintainer-zts [root@www php-5.6.27]# make&& make install [root@www php-5.6.27]# cp php.ini-production /etc/php.ini
修改/etc/php.ini文件,將short_open_tag修改成on,修改後的內容以下:
short_open_tag = On //支持php短標籤
建立php-fpm服務啓動腳本:
[root@www php-5.6.27]# cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm [root@www php-5.6.27]# chmod +x /etc/init.d/php-fpm [root@www php-5.6.27]# chkconfig --add php-fpm [root@www php-5.6.27]# chkconfig php-fpm on
提供php-fpm配置文件並編輯:
#cp /usr/local/php5.6/etc/php-fpm.conf.default /usr/local/php5.6/etc/php-fpm.conf [root@www php-5.6.27]# vi /usr/local/php5.6/etc/php-fpm.conf
修改內容以下:
pid = run/php-fpm.pid listen =127.0.0.1:9000 pm.max_children = 300 pm.start_servers = 10 pm.min_spare_servers = 10 pm.max_spare_servers =50 啓動php-fpm服務: [root@phpserver ~]# service php-fpm start Starting php-fpm done [root@www php-5.6.27]# netstat -anpt | grep php-fpm tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 10937/php-fpm: mast
三、安裝mysql(在192.168.31.225主機操做)
由於centos7.2默認安裝了mariadb-libs,因此先要卸載掉
查看是否安裝mariadb
#rpm -qa | grep mariadb
卸載mariadb
rpm -e --nodeps mariadb-libs
二、安裝依賴包
注: 相關依賴包的做用
cmake:因爲從MySQL5.5版本開始棄用了常規的configure編譯方法,因此須要CMake編譯器,用於設置mysql的編譯參數。如:安裝目錄、數據存放目錄、字符編碼、排序規則等。
Boost #從MySQL 5.7.5開始Boost庫是必需的,mysql源碼中用到了C++的Boost庫,要求必須安裝boost1.59.0或以上版本
GCC是Linux下的C語言編譯工具,mysql源碼編譯徹底由C和C++編寫,要求必須安裝GCC
bison:Linux下C/C++語法分析器
ncurses:字符終端處理庫
1)安裝文件準備
下載cmake-3.5.tar.gz http://www.cmake.org/download/ 下載ncurses-5.9.tar.gzftp://ftp.gnu.org/gnu/ncurses/ 下載bison-3.0.4.tar.gzhttp://ftp.gnu.org/gnu/bison/ 下載mysql-5.7.13.tar.gz wget http://cdn.mysql.com/Downloads/MySQL-5.7/mysql-5.7.13.tar.gz 下載Boost_1_59_0.tar.gz wget http://nchc.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz
2)安裝CMAKE及必要的軟件
安裝cmake
cmake –version ---查看cmake版本
安裝ncurses
安裝bison
安裝bootst
tar zxf boost_1_59_0.tar.gz mv boost_1_59_0 /usr/local/boost
3)建立mysql用戶和用戶組及目錄
# groupadd -r mysql && useradd -r -g mysql -s /bin/false -M mysql---新建msyql組和msyql用戶禁止登陸shell #mkdir /usr/local/mysql ---建立目錄 #mkdir /usr/local/mysql/data ---數據庫目錄
三、編譯安裝mysql
解壓mysql源碼包:
執行cmake命令進行編譯前的配置:
開始編譯、編譯安裝:
注1:配置解釋:
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql[MySQL安裝的根目錄]-DMYSQL_DATADIR=/usr/local/mysql /data[MySQL數據庫文件存放目錄] -DSYSCONFDIR=/etc [MySQL配置文件所在目錄] -DWITH_MYISAM_STORAGE_ENGINE=1 [添加MYISAM引擎支持] -DWITH_INNOBASE_STORAGE_ENGINE=1[添加InnoDB引擎支持] -DWITH_ARCHIVE_STORAGE_ENGINE=1 [添加ARCHIVE引擎支持] -DMYSQL_UNIX_ADDR=/usr/local/mysql /mysql.sock[指定mysql.sock位置] -DWITH_PARTITION_STORAGE_ENGINE=1[安裝支持數據庫分區] -DEXTRA_CHARSETS=all [使MySQL支持全部的擴展字符] -DDEFAULT_CHARSET=utf8[設置MySQL的默認字符集爲utf8]-DDEFAULT_COLLATION=utf8_general_ci [設置默認字符集校對規則] -DWITH-SYSTEMD=1 [可使用systemd控制mysql服務] -DWITH_BOOST=/usr/local/boost [指向boost庫所在目錄] 更多參數執行[root@localhost mysql-5.7.13]# cmake . –LH
注2:爲了加快編譯速度能夠按下面的方式編譯安裝
make -j $(grep processor /proc/cpuinfo | wc –l)
-j參數表示根據CPU核數指定編譯時的線程數,能夠加快編譯速度。默認爲1個線程編譯。
注3:若要從新運行cmake配置,須要刪除CMakeCache.txt文件
# make clean
#rm -f CMakeCache.txt
優化Mysql的執行路徑
四、設置權限並初始化MySQL系統受權表
# cd/usr/local/mysql # chown -R mysql:mysql . ---更改全部者,屬組,注意是mysql . #bin/mysqld --initialize--user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
注1:以root初始化操做時要加--user=mysql參數,生成一個隨機密碼(注意保存登陸時用)
注2:MySQL 5.7.6以前的版本執行這個腳本初始化系統數據庫
/usr/local/mysql/bin/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data # 5.7.6以後版本初始系統數據庫腳本(本文使用此方式初始化) #/usr/local/mysql/bin/mysqld --initialize-insecure--user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
注意:若是使用–initialize參數初始化系統數據庫以後,會生成root用戶的一個臨時密碼,如上圖高亮中所示。
# chown -Rmysql:mysql . ---改全部者,注意是root .
五、建立配置文件
# cd/usr/local/mysql/support-files ---進入MySQL安裝目錄支持文件目錄 # cp my-default.cnf /etc/my.cnf ---複製模板爲新的配置文件,
修改文件中配置選項,以下圖所示,添加以下配置項
#vi /etc/my.cnf
六、配置mysql自動啓動
服務啓動失敗,查看錯誤日誌文件
在mysqld.service,把默認的pid文件指定到了/var/run/mysqld/目錄,而並無事先創建該目錄,所以要手動創建該目錄並把權限賦給mysql用戶。
或者修改/usr/lib/system/system/mysqld.service,修改內容以下:
#systemctl daemon-reload
再次啓動mysql服務
查看端口號
服務啓動成功
訪問MySQL數據庫
# mysql -u root -h 127.0.0.1 -p ---鏈接mysql,輸入初始化時生成的隨機密碼
設置數據庫管理員用戶root的密碼
四、安裝memcached服務端(在192.168.31.250主機操做)
memcached是基於libevent的事件處理。libevent是個程序庫,它將Linux的epoll、BSD類操做系統的kqueue等事件處理功能封裝成統一的接口。即便對服務器的鏈接數增長,也能發揮I/O的性能。 memcached使用這個libevent庫,所以能在Linux、BSD、Solaris等操做系統上發揮其高性能。
首先先安裝memcached依賴庫libevent
[root@memcache ~]# tar zxf libevent-2.0.22-stable.tar.gz [root@memcache ~]# cd libevent-2.0.22-stable/ [root@memcache libevent-2.0.22-stable]# ./configure [root@memcache libevent-2.0.22-stable]# make&& make install
安裝memcached
[root@memcache ~]# tar zxf memcached-1.4.33.tar.gz [root@memcache ~]# cd memcached-1.4.33/ [root@memcache memcached-1.4.33]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local [root@memcache memcached-1.4.33]# make&& make install
檢測是否成功安裝
[root@memcache ~]# ls /usr/local/memcached/bin/memcached /usr/local/memcached/bin/memcached
經過以上操做就很簡單的把memcached服務端編譯好了。這時候就能夠打開服務端進行工做了。
配置環境變量:
進入用戶宿主目錄,編輯.bash_profile,爲系統環境變量LD_LIBRARY_PATH增長新的目錄,須要增長的內容以下:
[root@memcache ~]# vi ~/.bash_profile MEMCACHED_HOME=/usr/local/memcached LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MEMCACHED_HOME/lib [root@memcache ~]# /usr/local/memcached/bin/memcached -d -m 2048 -l 192.168.31.250 -p 11211 -u root -c 10240 -P /usr/local/memcached/memcached.pid
啓動參數說明:
-d 選項是啓動一個守護進程。 -m 分配給Memcache使用的內存數量,單位是MB,默認64MB。 -l 監聽的IP地址。(默認:INADDR_ANY,全部地址) -p 設置Memcache的TCP監聽的端口,最好是1024以上的端口。 -u 運行Memcache的用戶,若是當前爲root的話,須要使用此參數指定用戶。 -c 選項是最大運行的併發鏈接數,默認是1024。 -P 設置保存Memcache的pid文件。 -M 內存耗盡時返回錯誤,而不是刪除項 -f 塊大小增加因子,默認是1.25 -n 最小分配空間,key+value+flags默認是48 -h 顯示幫助
[root@memcache ~]# netstat -anpt |grep memcached tcp 0 0 192.168.31.250:11211 0.0.0.0:* LISTEN 12840/memcached 設置防火牆: [root@memcache ~]# firewall-cmd --permanent --add-port=11211/tcp success [root@memcache ~]# firewall-cmd --reload success
刷新用戶環境變量:
[root@memcache ~]# source ~/.bash_profile
編寫memcached服務啓停腳本
[root@memcache ~]# vi /etc/init.d/memcached
腳本內容以下:
[root@memcache ~]# cat /etc/init.d/memcached #!/bin/sh # # pidfile: /usr/local/memcached/memcached.pid # memcached_home: /usr/local/memcached # chkconfig: 35 21 79 # description: Start and stop memcached Service # Source function library . /etc/rc.d/init.d/functions RETVAL=0 prog="memcached" basedir=/usr/local/memcached cmd=${basedir}/bin/memcached pidfile="$basedir/${prog}.pid" #interface to listen on (default: INADDR_ANY, all addresses) ipaddr="192.168.31.250" #listen port port=11211 #username for memcached username="root" #max memory for memcached,default is 64M max_memory=2048 #max connections for memcached max_simul_conn=10240 start() { echo -n $"Starting service: $prog" $cmd -d -m $max_memory -u $username -l $ipaddr -p $port -c $max_simul_conn -P $pidfile RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog } stop() { echo -n $"Stopping service: $prog " run_user=$(whoami) pidlist=$(ps -ef | grep $run_user | grep memcached | grep -v grep | awk '{print($2)}') for pid in $pidlist do kill -9 $pid if [ $? -ne 0 ]; then return 1 fi done RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 esac exit $RETVAL
設置腳本可被執行:
[root@memcache ~]# chmod +x /etc/init.d/memcached [root@memcache ~]# chkconfig --add memcached [root@memcache ~]# chkconfig memcached on
說明:
shell腳本中return的做用
1)終止一個函數.
2)return命令容許帶一個整型參數, 這個整數將做爲函數的"退出狀態
碼"返回給調用這個函數的腳本, 而且這個整數也被賦值給變量$?.
3)命令格式:return value
五、配置nginx.conf文件(在nginx主機操做)
配置內容以下:
user www www; worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; pid logs/nginx.pid; events { use epoll; worker_connections 65535; multi_accept on; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; tcp_nodelay on; client_header_buffer_size 4k; open_file_cache max=102400 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 1; client_header_timeout 15; client_body_timeout 15; reset_timedout_connection on; send_timeout 15; server_tokens off; client_max_body_size 10m; fastcgi_connect_timeout 600; fastcgi_send_timeout 600; fastcgi_read_timeout 600; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; fastcgi_temp_path /usr/local/nginx1.10/nginx_tmp; fastcgi_intercept_errors on; fastcgi_cache_path /usr/local/nginx1.10/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:128m inactive=1d max_size=10g; gzip on; gzip_min_length 2k; gzip_buffers 4 32k; gzip_http_version 1.1; gzip_comp_level 6; gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; gzip_vary on; gzip_proxied any; server { listen 80; server_name www.benet.com; #charset koi8-r; #access_log logs/host.access.log main; location ~* ^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ { valid_referers none blocked www.benet.com benet.com; if ($invalid_referer) { #return 302 http://www.benet.com/img/nolink.jpg; return 404; break; } access_log off; } location / { root html; index index.php index.html index.htm; } location ~* \.(ico|jpe?g|gif|png|bmp|swf|flv)$ { expires 30d; #log_not_found off; access_log off; } location ~* \.(js|css)$ { expires 7d; log_not_found off; access_log off; } location = /(favicon.ico|roboots.txt) { access_log off; log_not_found off; } location /status { stub_status on; } location ~ .*\.(php|php5)?$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; fastcgi_cache cache_fastcgi; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_cache_key http://$host$request_uri; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
重啓nginx服務
生成一個php測試頁
[root@www memcache-3.0.8]# cat /usr/local/nginx1.10/html/test1.php <?php phpinfo(); ?>
使用瀏覽器訪問test1.php測試頁
六、memcache客戶端(在php服務器操做):
memcache分爲服務端和客戶端。服務端用來存放緩存,客戶端用來操做緩存。
安裝php擴展庫(phpmemcache)。
安裝PHP Memcache擴展:
可使用php自帶的pecl安裝程序
# /usr/local/php5.6/bin/pecl install memcache
也能夠從源碼安裝,他是生成php的擴展庫文件memcache.so。
安裝memcache擴展庫
[root@www ~]# tar zxf memcache-3.0.8.tgz [root@www ~]# cd memcache-3.0.8/ [root@www memcache-3.0.8]# /usr/local/php5.6/bin/phpize [root@wwwmemcache-3.0.8]#./configure --enable-memcache --with-php-config=/usr/local/php5.6/bin/php-config [root@www memcache-3.0.8]# make&& make install
安裝完後會有相似這樣的提示:
Installing shared extensions: /usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/
把這個記住,而後修改php.ini
添加一行
extension=/usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/memcache.so
重啓php-fpm服務
[root@www memcache-3.0.8]# service php-fpm restart Gracefully shutting down php-fpm .done Starting php-fpm done
測試:
檢查php擴展是否正確安裝
一、[root@www html]# /usr/local/php5.6/bin/php -m
命令行執行php -m 查詢結果中是否有memcache項
二、建立phpinfo()頁面,查詢session項下面的Registered save handlers值中是否有memcache項
瀏覽器訪問test1.php
測試代碼:
[root@www ~]# cat /usr/local/nginx1.10/html/test2.php <?php $memcache = new Memcache; $memcache->connect('192.168.31.250', 11211) or die ("Could not connect"); $version = $memcache->getVersion(); echo "Server's version: ".$version."<br/>"; $tmp_object = new stdClass; $tmp_object->str_attr = 'test'; $tmp_object->int_attr = 123; $memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server"); echo "Store data in the cache (data will expire in 10 seconds)<br/>"; $get_result = $memcache->get('key'); echo "Data from the cache:<br/>"; var_dump($get_result); ?>
瀏覽器訪問test2.php
使用memcache實現session共享
配置php.ini中的Session爲memcache方式。
session.save_handler = memcache session.save_path = "tcp://192.168.31.250:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
注:
session.save_handler:設置session的儲存方式爲memcache 。默認以文件方式存取session數據,若是想要使用自定義的處理來存取session數據,好比memcache方式則修爲session.save_handler = memcache
session.save_path:設置session儲存的位置,多臺memcache用逗號隔開
使用多個 memcached server 時用逗號」,」隔開,能夠帶額外的參數」persistent」、」weight」、」timeout」、」retry_interval」等等,
相似這樣的:"tcp://host:port?persistent=1&weight=2,tcp://host2:port2"。
memcache實現session共享也能夠在某個一個應用中設置:
ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://192.168.0.9:11211");
ini_set()只對當前php頁面有效,而且不會去修改php.ini文件自己,也不會影響其餘php頁面。
測試memcache可用性
重啓php-fpm
在web服務器上新建//usr/local/nginx1.10/html/memcache.php文件。內容如
<?php session_start(); if (!isset($_SESSION['session_time'])) { $_SESSION['session_time'] = time(); } echo "session_time:".$_SESSION['session_time']."<br />"; echo "now_time:".time()."<br />"; echo "session_id:".session_id()."<br />"; ?>
訪問網址http://192.168.31.141/memcache.php能夠查看session_time是否都是爲memcache中的Session,同時能夠在不一樣的服務器上修改不一樣的標識查看是否爲不一樣的服務器上的。
能夠直接用sessionid 去 memcached 裏查詢一下:
[root@www html]# telnet 192.168.31.250 11211 Trying 192.168.31.250... Connected to 192.168.31.250. Escape character is '^]'. get ffaqe5b1oar311n3cn5q9co5g6 VALUE ffaqe5b1oar311n3cn5q9co5g6 0 26 session_time|i:1479134997;
獲得session_time|i:1479134997;這樣的結果,說明session 正常工做
默認memcache會監聽11221端口,若是想清空服務器上memecache的緩存,通常使用的是:
[root@memcache ~]# telnet 192.168.31.250 11211 Trying 192.168.31.250... Connected to 192.168.31.250. Escape character is '^]'. flush_all OK
一樣也可使用:
[root@memcache ~]# echo "flush_all" | nc 192.168.31.250 11211 OK
使用flush_all 後並非刪除memcache上的key,而是置爲過時
memcache安全配置
由於memcache不進行權限控制,所以須要經過iptables將memcache僅開放個web服務器。
七、測試memcache緩存數據庫數據
在Mysql服務器上建立測試表
mysql> create database testdb1; Query OK, 1 row affected (0.00 sec)
mysql> use testdb1; Database changed mysql> create table test1(id int not null auto_increment,name varchar(20) default null,primary key (id)) engine=innodb auto_increment=1 default charset=utf8; Query OK, 0 rows affected (0.03 sec)
mysql> insert into test1(name) values ('tom1'),('tom2'),('tom3'),('tom4'),('tom5'); Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from test1; +----+------+ | id | name | +----+------+ | 1 | tom1 | | 2 | tom2 | | 3 | tom3 | | 4 | tom4 | | 5 | tom5 | +----+------+ 5 rows in set (0.00 sec)
測試
下面就是測試的工做了,這裏有個php腳本,用於測試memcache是否緩存數據成功
須要爲這個腳本添加一個只讀的數據庫用戶,命令格式
mysql> grant select on testdb1.* to user@'%' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.00 sec)
在web服務器上建立測試腳本內容以下:
[root@www html]# cat /usr/local/nginx1.10/html/test_db.php <?php $memcachehost = '192.168.31.250'; $memcacheport = 11211; $memcachelife = 60; $memcache = new Memcache; $memcache->connect($memcachehost,$memcacheport) or die ("Could not connect"); $query="select * from test1 limit 10"; $key=md5($query); if(!$memcache->get($key)) { $conn=mysql_connect("192.168.31.225","user","123456"); mysql_select_db(testdb1); $result=mysql_query($query); while ($row=mysql_fetch_assoc($result)) { $arr[]=$row; } $f = 'mysql'; $memcache->add($key,serialize($arr),0,30); $data = $arr ; } else{ $f = 'memcache'; $data_mem=$memcache->get($key); $data = unserialize($data_mem); } echo $f; echo "<br>"; echo "$key"; echo "<br>"; //print_r($data); foreach($data as $a) { echo "number is <b><font color=#FF0000>$a[id]</font></b>"; echo "<br>"; echo "name is <b><font color=#FF0000>$a[name]</font></b>"; echo "<br>"; } ?>
訪問頁面測試
若是出現mysql表示memcached中沒有內容,須要memcached從數據庫中取得
再刷新頁面,若是有memcache標誌表示此次的數據是從memcached中取得的。
memcached有個緩存時間默認是1分鐘,過了一分鐘後,memcached須要從新從數據庫中取得數據
查看 Memcached 緩存狀況
咱們須要使用 telnet 命令查看
[root@memcache ~]# telnet 192.168.31.250 11211 Trying 192.168.31.250... Connected to 192.168.31.250. Escape character is '^]'. stats STAT pid 1681 //Memcached 進程的ID STAT uptime 8429 //進程運行時間 STAT time 1479142306 //當前時間 STAT version 1.4.33 // Memcached 版本 STAT libevent 2.0.22-stable STAT pointer_size 64 STAT rusage_user 1.218430 STAT rusage_system 1.449512 STAT curr_connections 5 STAT total_connections 32 STAT connection_structures 10 STAT reserved_fds 20 STAT cmd_get 25//總共獲取數據的次數(等於 get_hits + get_misses ) STAT cmd_set 19 //總共設置數據的次數 STAT cmd_flush 4 STAT cmd_touch 0 STAT get_hits 15//命中了多少次數據,也就是從 Memcached 緩存中成功獲取數據的次數 STAT get_misses 10//沒有命中的次數 STAT get_expired 3 STAT get_flushed 1 STAT delete_misses 0 STAT delete_hits 0 STAT incr_misses 2 STAT incr_hits 2 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT touch_hits 0 STAT touch_misses 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 3370 STAT bytes_written 15710 STAT limit_maxbytes 2147483648//總的存儲大小,默認爲 64M STAT accepting_conns 1 STAT listen_disabled_num 0 STAT time_in_listen_disabled_us 0 STAT threads 4 STAT conn_yields 0 STAT hash_power_level 16 STAT hash_bytes 524288 STAT hash_is_expanding 0 STAT malloc_fails 0 STAT log_worker_dropped 0 STAT log_worker_written 0 STAT log_watcher_skipped 0 STAT log_watcher_sent 0 STAT bytes 584//當前所用存儲大小 STAT curr_items 3 STAT total_items 17 STAT expired_unfetched 2 STAT evicted_unfetched 0 STAT evictions 0 STAT reclaimed 4 STAT crawler_reclaimed 0 STAT crawler_items_checked 0 STAT lrutail_reflocked 0 END 命中率= get_hits/ cmd_get