圖文並茂超詳細搭建memcache緩存服務器(nginx+php+memcache+mysql)

博主QQ:819594300javascript

博客地址:http://zpf666.blog.51cto.com/php

有什麼疑問的朋友能夠聯繫博主,博主會幫大家解答,謝謝支持!css


1、MemCache簡述html

sessionjava

MemCache是一個自由、源碼開放、高性能、分佈式的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫的負載。它經過在內存中緩存數據和對象來減小讀取數據庫的次數,從而提升了網站訪問的速度。 MemCaChe是一個存儲鍵值對的HashMap,在內存中對任意的數據(好比字符串、對象等)所使用的key-value存儲,數據能夠來自數據庫調用、API調用,或者頁面渲染的結果。MemCache設計理念就是小而強大,它簡單的設計促進了快速部署、易於開發並解決面對大規模的數據緩存的許多難題,而所開放的API使得MemCache能用於Java、C/C++/C#、Perl、Python、PHP、Ruby等大部分流行的程序語言。node

另外,說一下爲何會有Memcache和memcached兩種名稱?其實Memcache是這個項目的名稱,而memcached是它服務器端的主程序文件名mysql

MemCache的官方網站爲http://memcached.org/linux

MemCache訪問模型nginx

爲了加深對memcache的理解,以memcache爲表明的分佈式緩存,訪問模型以下:web

wKioL1kZCmiD8nysAAKDWwegddo172.jpg

特別澄清一個問題,MemCache雖然被稱爲」分佈式緩存」,可是MemCache自己徹底不具有分佈式的功能,MemCache集羣之間不會相互通訊(與之造成對比的,好比JBoss Cache,某臺服務器有緩存數據更新時,會通知集羣中其餘機器更新緩存或清除緩存數據),所謂的」分佈式」,徹底依賴於客戶端程序的實現,就像上面這張圖的流程同樣。

同時基於這張圖,理一下MemCache一次寫緩存的流程:

一、應用程序輸入須要寫緩存的數據

二、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個數據,那麼:

wKiom1kZCmjTqWCdAACxFjWQAJc761.jpg

如今擴容到4臺,加粗標紅的表示命中:

wKioL1kZCmny6EkJAADAZyEXYGk836.jpg

若是擴容到20+的臺數,只有前三個HashCode對應的Key是命中的,也就是15%。固然現實狀況確定比這個複雜得多,不過足以說明,使用餘數Hash的路由算法,在擴容的時候會形成大量的數據沒法正確命中(其實不只僅是沒法命中,那些大量的沒法命中的數據還在原緩存中在被移除前佔據着內存)。在網站業務中,大部分的業務數據度操做請求上事實上是經過緩存獲取的,只有少許讀操做會訪問數據庫,所以數據庫的負載能力是以有緩存爲前提而設計的。當大部分被緩存了的數據由於服務器擴容而不能正確讀取時,這些數據訪問的壓力就落在了數據庫的身上,這將大大超過數據庫的負載能力,嚴重的可能會致使數據庫宕機。

這個問題有解決方案,解決步驟爲:

(1)在網站訪問量低谷,一般是深夜,技術團隊加班,擴容、重啓服務器

(2)經過模擬請求的方式逐漸預熱緩存,使緩存服務器中的數據從新分佈

二、一致性Hash算法

一致性Hash算法經過一個叫作一致性Hash環的數據結構實現Key到緩存服務器的Hash映射。簡單地說,一致性哈希將整個哈希值空間組織成一個虛擬的圓環(這個環被稱爲一致性Hash環),如假設某空間哈希函數H的值空間是0~2^32-1(即哈希值是一個32位無符號×××),整個哈希空間以下:

wKiom1kZCmmSr1coAABtVvs_ySs582.jpg

下一步將各個服務器使用H進行一個哈希計算,具體可使用服務器的IP地址或者主機名做爲關鍵字,這樣每臺機器能肯定其在上面的哈希環上的位置了,而且是按照順時針排列,這裏咱們假設三臺節點memcache經計算後位置以下:

wKioL1kZCmmxRLICAACbdcB-0Q0865.jpg

接下來使用相同算法計算出數據的哈希值h,並由此肯定數據在此哈希環上的位置

假如咱們有數據A、B、C、D、4個對象,通過哈希計算後位置以下:

wKiom1kZCmrglQV4AACYlJn1LaU708.jpg

根據一致性哈希算法,數據A就被綁定到了server01上,D被綁定到了server02上,B、C在server03上,是按照順時針找最近服務節點方法

這樣獲得的哈希環調度方法,有很高的容錯性和可擴展性:

假設server03宕機:

wKiom1kZCmrxtnkfAAChWGHTeN8420.jpg

能夠看到此時C、B會受到影響,將B、C被重定位到Server01。通常的,在一致性哈希算法中,若是一臺服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一臺服務器(即順着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響。

考慮另一種狀況,若是咱們在系統中增長一臺服務器Memcached Server 04:

wKioL1kZCmujrjsmAACzzHKedEg676.jpg

此時A、D、C不受影響,只有B須要重定位到新的Server04。通常的,在一致性哈希算法中,若是增長一臺服務器,則受影響的數據僅僅是新服務器到其環空間中前一臺服務器(即順着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響。

綜上所述,一致性哈希算法對於節點的增減都只需重定位環空間中的一小部分數據,具備較好的容錯性和可擴展性。

一致性哈希的缺點:在服務節點太少時,容易由於節點分部不均勻而形成數據傾斜問題。咱們能夠採用增長虛擬節點的方式解決。

更重要的是,集羣中緩存服務器節點越多,增長/減小節點帶來的影響越小,很好理解。換句話說,隨着集羣規模的增大,繼續命中原有緩存數據的機率會愈來愈大,雖然仍然有小部分數據緩存在服務器中不能被讀到,可是這個比例足夠小,即便訪問數據庫,也不會對數據庫形成致命的負載壓力。

MemCache實現原理

首先要說明一點,MemCache的數據存放在內存中

一、訪問數據的速度比傳統的關係型數據庫要快,由於Oracle、MySQL這些傳統的關係型數據庫爲了保持數據的持久性,數據存放在硬盤中,IO操做速度慢

二、MemCache的數據存放在內存中同時意味着只要MemCache重啓了,數據就會消失

三、既然MemCache的數據存放在內存中,那麼勢必受到機器位數的限制,32位機器最多隻能使用2GB的內存空間,64位機器能夠認爲沒有上限

而後咱們來看一下MemCache的原理,MemCache最重要的是內存如何分配的,MemCache採用的內存分配方式是固定空間分配,以下圖所示:

wKioL1kZCmvBSZasAAGYaCm4DAo414.jpg

這張圖片裏面涉及了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的工做流程:

wKiom1kZCmzworzSAACrA0MKnf8475.jpg

一、檢查客戶端的請求數據是否在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

環境描述:

wKiom1kZCmzxrWG_AAEPbDUo4jE485.jpg

nginx和php:

所需軟件:nginx-1.10.2.tar.gz

php-5.6.27.tar.gz

ip地址:192.168.1.8

mysql:

所需軟件:mysql-5.7.13.tar.gz

ip地址:192.168.1.9

memcache:

所需軟件:memcached-1.4.33.tar.gz

ip地址:192.168.1.10

虛擬機環境以下:

wKiom1kZCmzj_gGjAACEwPrH14w317.jpg

下面開始正式的實驗操做:

1)安裝nginx

①解壓縮zlib

wKioL1kZCm2xHOkgAAENnCfSbf8107.jpg

注意:不須要編譯,只須要解壓就行。

②解壓縮pcre

wKiom1kZCm3SmuQeAAER8L0-qt8789.jpg

注意:不須要編譯,只須要解壓就行。

③yum安裝nginx依賴包

wKioL1kZCm6xiIspAACosMXVtXE651.jpg

④下載安裝nginx源碼包

下載nginx的源碼包:http://nginx.org/download

解壓縮、編譯及安裝nginx源碼包:

wKiom1kZCm-i8XruAAJp-v1Z5no448.jpg

圖中配置、編譯安裝部分以下所示:

./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 && make&& make install

說明:--with-pcre:用來設置pcre的源碼目錄。

         --with-zlib:用來設置zlib的源碼目錄。

         由於編譯nginx須要用到這兩個庫的源碼。

⑤作軟連接

wKioL1kZCm-C4N7kAACw3t5mTmQ652.jpg

⑥nginx配置文件語法檢測

wKiom1kZCnCSzo5kAADY9W3JOGQ400.jpg

⑦啓動nginx

wKiom1kZCnCwv4q5AADCZf2xqA8809.jpg

⑧防火牆開啓80端口例外

wKioL1kZCnCCvjCNAAEngl9noGU668.jpg

⑨在一臺客戶機瀏覽器上瀏覽nginx網頁,測試一下nginx

wKiom1kZCnHRpdFbAAEhEMR50gA395.jpg

2)安裝php

①安裝libmcrypt

wKioL1kZCnHitEr6AAEBWfkQot0381.jpg

②yum安裝php依賴包

wKioL1kZCnKR0peTAACXmGyYR5A532.jpg

③解壓縮、編譯及安裝php源碼包

wKiom1kZCnLTZTNtAAJTjgKlb3E936.jpg

圖中配置、編譯安裝部分以下所示:

./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 && make && make install

④拷貝php.ini樣例文件

wKioL1kZCnSDPdU8AADMBWxYnxc226.jpg

修改/etc/php.ini文件,將short_open_tag修改成on,修改後的內容以下:

wKiom1kZCnTSZh74AAC9TSK1EFg531.jpg

wKioL1kZCnTg63O7AAA5d32Hd0Y539.jpg//支持php短標籤

⑤建立php-fpm服務啓動腳本並啓動服務

wKiom1kZCnWhyhYwAAEX2wN5DSA737.jpg

提供php-fpm配置文件並編輯:

wKioL1kZCnaSR8RvAADmkCHvgWQ814.jpg

wKiom1kZCnbzPT_gAAA_mh4EPI8923.jpg

wKiom1kZCnbBtvTUAABO9f69WzM309.jpg

說明:若是是nginx和php分離部署,這裏須要改爲php真實的ip,而後php服務器還要開始9000端口例外。除此以外都和本博文同樣便可。

wKioL1kZCnfRsG-7AABDWn1BDrM840.jpg

wKiom1kZCq2BgXRvAAA-joxh_Wo041.jpg

wKioL1kZCq3BcrcjAABHa1wvWVE118.jpg

wKiom1kZCq3Rfdp9AABG9gncDLc953.jpg

啓動php-fpm服務:

wKioL1kZCq6xxPuNAADqNZtLKF0919.jpg

3)安裝mysql

(在192.168.1.9主機上操做)

由於centos7.2默認安裝了mariadb-libs,因此先要卸載掉

查看是否安裝mariadb

#rpm-qa | grep mariadb

卸載mariadb

rpm-e --nodeps mariadb-libs

wKioL1kZCq7R3ftXAACy9rMRCIo795.jpg

而後具體的mysql安裝請參考個人mysql5.7.13的安裝,博文地址:

http://zpf666.blog.51cto.com/11248677/1908988

這裏個人mysql是安裝好的,咱們看一下服務是否啓動:

wKiom1kZCq_A1NfDAACeYiWsTKg938.jpg

防火牆開啓3306端口例外:

wKiom1kZCq_Ae_LcAAEauFteYpg255.jpg

四、安裝memcached服務端

(在192.168.1.10主機操做)

memcached是基於libevent的事件處理。libevent是個程序庫,它將Linux的epoll、BSD類操做系統的kqueue等事件處理功能封裝成統一的接口。即便對服務器的鏈接數增長,也能發揮I/O的性能。 memcached使用這個libevent庫,所以能在Linux、BSD、Solaris等操做系統上發揮其高性能。

①安裝memcached依賴庫libevent

wKioL1kZCrDS0JLsAAEPyB1Sbio340.jpg

②安裝memcached

wKiom1kZCrDBqh2sAAEVwR9UXY8626.jpg

③檢測memcache是否安裝成功

wKioL1kZCrHQuwKTAAEB_7-AmRg027.jpg

經過以上操做就很簡單的把memcached服務端編譯好了。這時候就能夠打開服務端進行工做了。

④配置環境變量

進入用戶宿主目錄,編輯.bash_profile,爲系統環境變量LD_LIBRARY_PATH增長新的目錄,須要增長的內容以下:

wKiom1kZCrHhl6o2AAC53gzVZ4Y369.jpg

wKioL1kZCrKwzFC7AACyY3fNhr0648.jpg

圖片中具體內容以下:

MEMCACHED_HOME=/usr/local/memcached

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MEMCACHED_HOME/lib

⑤啓動memcache服務

wKioL1kZCrLSlGK7AADPPMmMbRY026.jpg

注意:-m後面跟的是分配給memcache的內存,不能大於等於本主機內存。個人主機是2048M內存,我給了1024M。

啓動參數說明:

-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     顯示幫助

wKiom1kZCrPRmcQjAACrw50ePk0573.jpg

⑥防火牆開啓11211端口例外

wKioL1kZCrOgk_zvAAEWxYwi0j4395.jpg

⑦刷新用戶環境變量

wKiom1kZCrSRdCzJAACn8s4obgk449.jpg

刷新環境變量的時候報了一個錯誤,讓執行那條命令,你就執行如下便可。

而後再次刷新環境變量:

wKioL1kZCrSTctvdAADwfhuegBM647.jpg

⑧編寫memcached服務啓停腳本

wKiom1kZCrWhsR56AADQpz0z21g897.jpg

腳本內容以下:

#!/bin/sh

#

# pidfile:/usr/local/memcached/memcached.pid

# memcached_home: /usr/local/memcached

# chkconfig: 35 21 79

# description: Start and stop memcachedService

 

# 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.1.10"

#listen port

port=11211

#username for memcached

username="root"

#max memory for memcached,default is 64M

max_memory=1024

#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 | grepmemcached | 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

設置腳本可被執行:

wKioL1kZCrXTtYk3AAHtVWxcJ0E374.jpg

說明:

shell腳本中return的做用

1)終止一個函數.

2)return命令容許帶一個整型參數, 這個整數將做爲函數的"退出狀態

碼"返回給調用這個函數的腳本, 而且這個整數也被賦值給變量$?.

3)命令格式:returnvalue

  

先別急着閃,memcache服務腳本是配置好了,可是有個問題:

wKiom1kZCrWQGcmfAADhv21Qk2E976.jpg

從上圖能夠看出,重啓不了memcache,這是由於當前memcache服務是運行着的,這個服務是開始的時候第⑤步啓動的,因此我們如今用服務腳本是重啓不了的,解決辦法以下:

wKioL1kZCragwLhBAAD4mPlU78s830.jpg

就是殺死正在運行的memcache服務的進程。

而後開始再重啓服務:

wKiom1kZCrbR-zpdAAGNyNMCtpI168.jpg

至此就能夠用服務腳本控制memcache服務了。

五、配置nginx.conf文件(在nginx&&php主機上操做)

①配置成以下的nginx.conf文件

wKiom1kZCrfgwuxKAACcA312wpY873.jpg

把原有的東西所有刪除,配置成以下內容:

說明一下:我這裏nginx&&php主機用的是4核,若是你的不是4核,請修改worker_cpu_affinity,若是是4核,請忽略該問題,所有複製我寫好的內容便可。

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/csstext/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服務

wKioL1kZCrjRXqp0AAFxeAPqshg195.jpg

③編寫一個php測試頁

wKiom1kZCrjzbmMnAACssfO-DBA802.jpg

wKioL1kZCrjThbZ9AACOAwoUXVA426.jpg

④在客戶端使用瀏覽器訪問test1.php測試頁

wKiom1kZCrmAqqszAADdfWYGaHk029.jpg

六、memcache客戶端(在nginx&&php主機上操做)

說明:memcache分爲服務端和客戶端。服務端用來存放緩存,客戶端用來操做緩存。

安裝php擴展庫(phpmemcache)

說明:安裝PHP Memcache擴展:

可使用php自帶的pecl安裝程序

#/usr/local/php5.6/bin/pecl install memcache

也能夠從源碼安裝,他是生成php的擴展庫文件memcache.so。

①安裝memcache擴展庫

wKioL1kZCrryrdscAAINUEZks-s281.jpg

wKioL1kZCrqwcYidAAC7eqSOCBc296.jpg

圖片中內容以下:

./configure --enable-memcache --with-php-config=/usr/local/php5.6/bin/php-config && make && make install

wKiom1kZCruD61hUAACNUqROcDc157.jpg

記住安裝完畢後,最後一行你的這個路徑。

/usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/

②修改php.ini

wKiom1kZCrviQkA7AAC8-OoxwSw026.jpg

添加以下一行內容:

wKioL1kZCrzTau2vAABNt9As1d0398.jpg

圖片中內容以下:

extension=/usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/memcache.so

③重啓php-fpm服務

wKioL1kZCxrTx0OZAAGVcAWOywA271.jpg

④測試

說明:檢查php擴展是否正確安裝。

主要是看查詢結果中是否有memcache項。

wKiom1kZCxuzhX34AAJYLPlMbdA010.jpg

⑤在客戶機瀏覽器上再次訪問test1.php

則看到不到memcache和在session會話裏面看不到memcache。

這是由於,nginx配置文件裏配置了fast-cgi緩存,若是不註釋點這一行,客戶端訪問的test1.php的數據,是fast-cgi緩存的,由於有緩存,memcache就起不到做用了。

解決辦法以下:

wKioL1kZCxvhdNILAAChQ8_Bv8s497.jpg

wKiom1kZCxvQfxDDAABUPqvwClI766.jpg

wKioL1kZCxvBZvZqAAEii425iqw491.jpg

再次刷新test1.php頁面,就能夠看見以下的兩個截圖:

wKiom1kZCxzRc8tPAABa8sQkIzQ457.jpg

wKioL1kZCxywKxzAAABvSmsCweQ991.jpg

⑥編寫test2.php測試頁

說明:這個測試頁測試的是往memcache服務器寫/讀數據測試

wKiom1kZCxzBGI9lAACfUZi_G_g516.jpg

具體內容以下:

<?php

$memcache = new Memcache;

$memcache->connect('192.168.1.10',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 (datawill expire in 10 seconds)<br/>";

$get_result = $memcache->get('key');

echo "Data from thecache:<br/>";

var_dump($get_result);

?>

在客戶機上訪問test2.php

wKioL1kZCx2AusuqAADstILwzkE070.jpg

⑦使用memcache實現session共享

配置php.ini中的Session爲memcache方式。

wKiom1kZCx6Cz4clAAC_4u41qEM623.jpg

wKiom1kZCx6RFcL0AABnpW_WV-4761.jpg

wKioL1kZCx7SQzxaAABrEOzKkkg047.jpg

說明:1394行是修改

          1424行是添加

兩行的文字內容以下:

session.save_handler = memcache

session.save_path = "tcp://192.168.1.10:11211?persistent=1&weight=1&timeout=1&retry_interval=15"

注:

ession.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:

wKioL1kZCx-TaVHIAAGcny4vtVs896.jpg

在nginx&&php

服務器上新建//usr/local/nginx1.10/html/memcache.php文件。內容以下:

wKiom1kZCx_CPVd8AACh8uEMryc198.jpg

<?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 />";

?>

    

這個memcache.php的測試頁面主要測試的是:

當客戶機訪問時,給客戶機生成一個session信息,這個session就是記錄在什麼時間點緩存到memcache的數據。

wKioL1kZCyDSVGw5AADzhyZWOtg461.jpg

刷新一下頁面,再看:

wKiom1kZCyGjn7AbAAEEGEEy8w0520.jpg

每刷一次頁面,now_time的值就一直在漲,而session_time一直不會變的,由於是session會話保持嘛。

訪問網址http://192.168.1.8/memcache.php能夠查看session_time是否都是爲memcache中的Session,同時能夠在不一樣的服務器上修改不一樣的標識查看是否爲不一樣的服務器上的。

能夠直接用sessionid 去 memcached 裏查詢一下:

wKiom1kZCyGR0IsqAADKTNH1AT0904.jpg

wKioL1kZCyPT04sNAAXXncjLnUM006.jpg

說明:獲得session_time|i:1493893966;這樣的結果,說明session 正常工做。

默認memcache會監聽11221端口,若是想清空服務器上memecache的緩存,通常使用的是:

wKiom1kZCyTygSIjAAJkbS1JHnU014.jpg

或者

wKioL1kZCyXg6bJfAADKT6h9QYc645.jpg

說明:使用flush_all 後並非刪除memcache上的key,而是置爲過時。

memcache安全配置:

由於memcache不進行權限控制,所以須要經過iptables將memcache僅開放個web服務器。

七、測試memcache緩存數據庫數據

①先在Mysql服務器上建立測試表

wKioL1kZCyXQbjynAAC4YrzKNAc722.jpg

wKiom1kZCyXglxuCAAEiSSINcMI495.jpg

wKioL1kZCybiuJ0QAAEZ2JurJk0225.jpg

wKiom1kZCyaCu7dQAADXFFVnH14227.jpg

wKioL1kZCyeCNYUMAAGp8xQpxIg086.jpg

②編寫測試腳本

做用:用於測試memcache是否緩存數據成功。

先須要爲這個腳本添加一個只讀的數據庫用戶,命令格式:

wKiom1kZCyfQGqgYAADJw_At5-E631.jpg

在web服務器上建立測試腳本內容以下:

wKioL1kZCyfSG0UuAACk-firJYs465.jpg

<?php

$memcachehost = '192.168.1.10';

$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.1.9","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><fontcolor=#FF0000>$a[id]</font></b>";

echo "<br>";

echo "name is <b><font color=#FF0000>$a[name]</font></b>";

echo "<br>";

}

?>

③訪問頁面測試

wKiom1kZCyjzpnL-AAHBL6UMzg0208.jpg

說明:若是出現mysql表示memcached中沒有內容,須要memcached從數據庫中取得

再刷新頁面,若是有memcache標誌表示此次的數據是從memcached中取得的。

memcached有個緩存時間默認是1分鐘,過了一分鐘後,memcached須要從新從數據庫中取得數據。

wKiom1kZCyjR5l8uAAHJfnEsaTA599.jpg

④查看 Memcached 緩存狀況

咱們須要使用 telnet 命令查看。

wKioL1kZCymgrKbMAAGtyMdttKo619.jpg

wKioL1kZCyuwbhSTAAUGccE_acY006.jpg

wKiom1kZCy2BTgPiAAPFGUgS6oE045.jpg

wKiom1kZC27hLVbGAAQJzTC84BE474.jpg

本文出自 「IT技術助手」 博客,請務必保留此出處http://zpf666.blog.51cto.com/11248677/1925729

相關文章
相關標籤/搜索