防偽碼:萬(wàn)丈紅塵三杯酒,千秋大業(yè)一壺茶。
一、MemCache簡(jiǎn)
session
MemCache是一個(gè)自由、源碼開(kāi)放、高性能、分布式的分布式內(nèi)存對(duì)象緩存系統(tǒng),用于動(dòng)態(tài)Web應(yīng)用以減輕數(shù)據(jù)庫(kù)的負(fù)載。它通過(guò)在內(nèi)存中緩存數(shù)據(jù)和對(duì)象來(lái)減少讀取數(shù)據(jù)庫(kù)的次數(shù),從而提高了網(wǎng)站訪問(wèn)的速度。 MemCaChe是一個(gè)存儲(chǔ)鍵值對(duì)的HashMap,在內(nèi)存中對(duì)任意的數(shù)據(jù)(比如字符串、對(duì)象等)所使用的key-value存儲(chǔ),數(shù)據(jù)可以來(lái)自數(shù)據(jù)庫(kù)調(diào)用、API調(diào)用,或者頁(yè)面渲染的結(jié)果。MemCache設(shè)計(jì)理念就是小而強(qiáng)大,它簡(jiǎn)單的設(shè)計(jì)促進(jìn)了快速部署、易于開(kāi)發(fā)并解決面對(duì)大規(guī)模的數(shù)據(jù)緩存的許多難題,而所開(kāi)放的API使得MemCache能用于Java、C/C++/C#、Perl、Python、PHP、Ruby等大部分流行的程序語(yǔ)言。
另外,說(shuō)一下為什么會(huì)有Memcache和memcached兩種名稱(chēng)?其實(shí)Memcache是這個(gè)項(xiàng)目的名稱(chēng),而memcached是它服務(wù)器端的主程序文件名
MemCache的官方網(wǎng)站為 http://memcached.org/
MemCache訪問(wèn)模型
為了加深對(duì)memcache的理解,以memcache為代表的分布式緩存,訪問(wèn)模型如下:
特別澄清一個(gè)問(wèn)題,MemCache雖然被稱(chēng)為”分布式緩存”,但是MemCache本身完全不具備分布式的功能,MemCache集群之間不會(huì)相互通信(與之形成對(duì)比的,比如JBoss Cache,某臺(tái)服務(wù)器有緩存數(shù)據(jù)更新時(shí),會(huì)通知集群中其他機(jī)器更新緩存或清除緩存數(shù)據(jù)),所謂的”分布式”,完全依賴(lài)于客戶(hù)端程序的實(shí)現(xiàn),就像上面這張圖的流程一樣。
同時(shí)基于這張圖,理一下MemCache一次寫(xiě)緩存的流程:
1、應(yīng)用程序輸入需要寫(xiě)緩存的數(shù)據(jù)
2、API將Key輸入路由算法模塊,路由算法根據(jù)Key和MemCache集群服務(wù)器列表得到一臺(tái)服務(wù)器編號(hào)
3、由服務(wù)器編號(hào)得到MemCache及其的ip地址和端口號(hào)
4、API調(diào)用通信模塊和指定編號(hào)的服務(wù)器通信,將數(shù)據(jù)寫(xiě)入該服務(wù)器,完成一次分布式緩存的寫(xiě)操作
讀緩存和寫(xiě)緩存一樣,只要使用相同的路由算法和服務(wù)器列表,只要應(yīng)用程序查詢(xún)的是相同的Key,MemCache客戶(hù)端總是訪問(wèn)相同的客戶(hù)端去讀取數(shù)據(jù),只要服務(wù)器中還緩存著該數(shù)據(jù),就能保證緩存命中。
這種MemCache集群的方式也是從分區(qū)容錯(cuò)性的方面考慮的,假如Node2宕機(jī)了,那么Node2上面存儲(chǔ)的數(shù)據(jù)都不可用了,此時(shí)由于集群中Node0和Node1還存在,下一次請(qǐng)求Node2中存儲(chǔ)的Key值的時(shí)候,肯定是沒(méi)有命中的,這時(shí)先從數(shù)據(jù)庫(kù)中拿到要緩存的數(shù)據(jù),然后路由算法模塊根據(jù)Key值在Node0和Node1中選取一個(gè)節(jié)點(diǎn),把對(duì)應(yīng)的數(shù)據(jù)放進(jìn)去,這樣下一次就又可以走緩存了,這種集群的做法很好,但是缺點(diǎn)是成本比較大。
一致性Hash算法
從上面的圖中,可以看出一個(gè)很重要的問(wèn)題,就是對(duì)服務(wù)器集群的管理,路由算法至關(guān)重要,就和負(fù)載均衡算法一樣,路由算法決定著究竟該訪問(wèn)集群中的哪臺(tái)服務(wù)器,先看一個(gè)簡(jiǎn)單的路由算法。
1、余數(shù)Hash
簡(jiǎn)單的路由算法可以使用余數(shù)Hash:用服務(wù)器數(shù)目和緩存數(shù)據(jù)KEY的hash值相除,余數(shù)為服務(wù)器列表下標(biāo)編號(hào),假如某個(gè)str對(duì)應(yīng)的HashCode是52、服務(wù)器的數(shù)目是3,取余數(shù)得到1,str對(duì)應(yīng)節(jié)點(diǎn)Node1,所以路由算法把str路由到Node1服務(wù)器上。由于HashCode隨機(jī)性比較強(qiáng),所以使用余數(shù)Hash路由算法就可以保證緩存數(shù)據(jù)在整個(gè)MemCache服務(wù)器集群中有比較均衡的分布。
如果不考慮服務(wù)器集群的伸縮性,那么余數(shù)Hash算法幾乎可以滿(mǎn)足絕大多數(shù)的緩存路由需求,但是當(dāng)分布式緩存集群需要擴(kuò)容的時(shí)候,就難辦了。
就假設(shè)MemCache服務(wù)器集群由3臺(tái)變?yōu)?臺(tái)吧,更改服務(wù)器列表,仍然使用余數(shù)Hash,52對(duì)4的余數(shù)是0,對(duì)應(yīng)Node0,但是str原來(lái)是存在Node1上的,這就導(dǎo)致了緩存沒(méi)有命中。再舉個(gè)例子,原來(lái)有HashCode為0~19的20個(gè)數(shù)據(jù),那么:
那么不妨舉個(gè)例子,原來(lái)有HashCode為0~19的20個(gè)數(shù)據(jù),那么:
現(xiàn)在擴(kuò)容到4臺(tái),加粗標(biāo)紅的表示命中:
如果擴(kuò)容到20+的臺(tái)數(shù),只有前三個(gè)HashCode對(duì)應(yīng)的Key是命中的,也就是15%。當(dāng)然現(xiàn)實(shí)情況肯定比這個(gè)復(fù)雜得多,不過(guò)足以說(shuō)明,使用余數(shù)Hash的路由算法,在擴(kuò)容的時(shí)候會(huì)造成大量的數(shù)據(jù)無(wú)法正確命中(其實(shí)不僅僅是無(wú)法命中,那些大量的無(wú)法命中的數(shù)據(jù)還在原緩存中在被移除前占據(jù)著內(nèi)存)。在網(wǎng)站業(yè)務(wù)中,大部分的業(yè)務(wù)數(shù)據(jù)度操作請(qǐng)求上事實(shí)上是通過(guò)緩存獲取的,只有少量讀操作會(huì)訪問(wèn)數(shù)據(jù)庫(kù),因此數(shù)據(jù)庫(kù)的負(fù)載能力是以有緩存為前提而設(shè)計(jì)的。當(dāng)大部分被緩存了的數(shù)據(jù)因?yàn)榉?wù)器擴(kuò)容而不能正確讀取時(shí),這些數(shù)據(jù)訪問(wèn)的壓力就落在了數(shù)據(jù)庫(kù)的身上,這將大大超過(guò)數(shù)據(jù)庫(kù)的負(fù)載能力,嚴(yán)重的可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)宕機(jī)。
這個(gè)問(wèn)題有解決方案,解決步驟為:
(1)在網(wǎng)站訪問(wèn)量低谷,通常是深夜,技術(shù)團(tuán)隊(duì)加班,擴(kuò)容、重啟服務(wù)器
(2)通過(guò)模擬請(qǐng)求的方式逐漸預(yù)熱緩存,使緩存服務(wù)器中的數(shù)據(jù)重新分布
2、一致性Hash算法
一致性Hash算法通過(guò)一個(gè)叫做一致性Hash環(huán)的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)Key到緩存服務(wù)器的Hash映射。簡(jiǎn)單地說(shuō),一致性哈希將整個(gè)哈希值空間組織成一個(gè)虛擬的圓環(huán)(這個(gè)環(huán)被稱(chēng)為一致性Hash環(huán)),如假設(shè)某空間哈希函數(shù)H的值空間是0~2^32-1(即哈希值是一個(gè)32位無(wú)符號(hào)整形),整個(gè)哈??臻g如下:
下一步將各個(gè)服務(wù)器使用H進(jìn)行一個(gè)哈希計(jì)算,具體可以使用服務(wù)器的IP地址或者主機(jī)名作為關(guān)鍵字,這樣每臺(tái)機(jī)器能確定其在上面的哈希環(huán)上的位置了,并且是按照順時(shí)針排列,這里我們假設(shè)三臺(tái)節(jié)點(diǎn)memcache經(jīng)計(jì)算后位置如下
接下來(lái)使用相同算法計(jì)算出數(shù)據(jù)的哈希值h,并由此確定數(shù)據(jù)在此哈希環(huán)上的位置
假如我們有數(shù)據(jù)A、B、C、D、4個(gè)對(duì)象,經(jīng)過(guò)哈希計(jì)算后位置如下:
根據(jù)一致性哈希算法,數(shù)據(jù)A就被綁定到了server01上,D被綁定到了server02上,B、C在server03上,是按照順時(shí)針找最近服務(wù)節(jié)點(diǎn)方法
這樣得到的哈希環(huán)調(diào)度方法,有很高的容錯(cuò)性和可擴(kuò)展性:
假設(shè)server03宕機(jī)
可以看到此時(shí)C、B會(huì)受到影響,將B、C被重定位到Server01。一般的,在一致性哈希算法中,如果一臺(tái)服務(wù)器不可用,則受影響的數(shù)據(jù)僅僅是此服務(wù)器到其環(huán)空間中前一臺(tái)服務(wù)器(即順著逆時(shí)針?lè)较蛐凶哂龅降牡谝慌_(tái)服務(wù)器)之間數(shù)據(jù),其它不會(huì)受到影響。
考慮另外一種情況,如果我們?cè)谙到y(tǒng)中增加一臺(tái)服務(wù)器Memcached Server 04:
此時(shí)A、D、C不受影響,只有B需要重定位到新的Server04。一般的,在一致性哈希算法中,如果增加一臺(tái)服務(wù)器,則受影響的數(shù)據(jù)僅僅是新服務(wù)器到其環(huán)空間中前一臺(tái)服務(wù)器(即順著逆時(shí)針?lè)较蛐凶哂龅降牡谝慌_(tái)服務(wù)器)之間數(shù)據(jù),其它不會(huì)受到影響。
綜上所述,一致性哈希算法對(duì)于節(jié)點(diǎn)的增減都只需重定位環(huán)空間中的一小部分?jǐn)?shù)據(jù),具有較好的容錯(cuò)性和可擴(kuò)展性。
一致性哈希的缺點(diǎn):在服務(wù)節(jié)點(diǎn)太少時(shí),容易因?yàn)楣?jié)點(diǎn)分部不均勻而造成數(shù)據(jù)傾斜問(wèn)題。我們可以采用增加虛擬節(jié)點(diǎn)的方式解決。
更重要的是,集群中緩存服務(wù)器節(jié)點(diǎn)越多,增加/減少節(jié)點(diǎn)帶來(lái)的影響越小,很好理解。換句話(huà)說(shuō),隨著集群規(guī)模的增大,繼續(xù)命中原有緩存數(shù)據(jù)的概率會(huì)越來(lái)越大,雖然仍然有小部分?jǐn)?shù)據(jù)緩存在服務(wù)器中不能被讀到,但是這個(gè)比例足夠小,即使訪問(wèn)數(shù)據(jù)庫(kù),也不會(huì)對(duì)數(shù)據(jù)庫(kù)造成致命的負(fù)載壓力。
MemCache實(shí)現(xiàn)原理
首先要說(shuō)明一點(diǎn),MemCache的數(shù)據(jù)存放在內(nèi)存中
1、訪問(wèn)數(shù)據(jù)的速度比傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)要快,因?yàn)镺racle、MySQL這些傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)為了保持?jǐn)?shù)據(jù)的持久性,數(shù)據(jù)存放在硬盤(pán)中,IO操作速度慢
2、MemCache的數(shù)據(jù)存放在內(nèi)存中同時(shí)意味著只要MemCache重啟了,數(shù)據(jù)就會(huì)消失
3、既然MemCache的數(shù)據(jù)存放在內(nèi)存中,那么勢(shì)必受到機(jī)器位數(shù)的限制,32位機(jī)器最多只能使用2GB的內(nèi)存空間,64位機(jī)器可以認(rèn)為沒(méi)有上限
然后我們來(lái)看一下MemCache的原理,MemCache最重要的是內(nèi)存如何分配的,MemCache采用的內(nèi)存分配方式是固定空間分配,如下圖所示:
這張圖片里面涉及了slab_class、slab、page、chunk四個(gè)概念,它們之間的關(guān)系是:
1、MemCache將內(nèi)存空間分為一組slab
2、每個(gè)slab下又有若干個(gè)page,每個(gè)page默認(rèn)是1M,如果一個(gè)slab占用100M內(nèi)存的話(huà),那么這個(gè)slab下應(yīng)該有100個(gè)page
3、每個(gè)page里面包含一組chunk,chunk是真正存放數(shù)據(jù)的地方,同一個(gè)slab里面的chunk的大小是固定的
4、有相同大小chunk的slab被組織在一起,稱(chēng)為slab_class
MemCache內(nèi)存分配的方式稱(chēng)為allocator(分配運(yùn)算),slab的數(shù)量是有限的,幾個(gè)、十幾個(gè)或者幾十個(gè),這個(gè)和啟動(dòng)參數(shù)的配置相關(guān)。
MemCache中的value存放的地方是由value的大小決定的,value總是會(huì)被存放到與chunk大小最接近的一個(gè)slab中,比如slab[1]的chunk大小為80字節(jié)、slab[2]的chunk大小為100字節(jié)、slab[3]的chunk大小為125字節(jié)(相鄰slab內(nèi)的chunk基本以1.25為比例進(jìn)行增長(zhǎng),MemCache啟動(dòng)時(shí)可以用-f指定這個(gè)比例),那么過(guò)來(lái)一個(gè)88字節(jié)的value,這個(gè)value將被放到2號(hào)slab中。放slab的時(shí)候,首先slab要申請(qǐng)內(nèi)存,申請(qǐng)內(nèi)存是以page為單位的,所以在放入第一個(gè)數(shù)據(jù)的時(shí)候,無(wú)論大小為多少,都會(huì)有1M大小的page被分配給該slab。申請(qǐng)到page后,slab會(huì)將這個(gè)page的內(nèi)存按chunk的大小進(jìn)行切分,這樣就變成了一個(gè)chunk數(shù)組,最后從這個(gè)chunk數(shù)組中選擇一個(gè)用于存儲(chǔ)數(shù)據(jù)。
如果這個(gè)slab中沒(méi)有chunk可以分配了怎么辦,如果MemCache啟動(dòng)沒(méi)有追加-M(禁止LRU,這種情況下內(nèi)存不夠會(huì)報(bào)Out Of Memory錯(cuò)誤),那么MemCache會(huì)把這個(gè)slab中最近最少使用的chunk中的數(shù)據(jù)清理掉,然后放上最新的數(shù)據(jù)。
Memcache的工作流程:
1、檢查客戶(hù)端的請(qǐng)求數(shù)據(jù)是否在memcached中,如果有,直接把請(qǐng)求數(shù)據(jù)返回,不再對(duì)數(shù)據(jù)庫(kù)進(jìn)行任何操作,路徑操作為①②③⑦。
2、如果請(qǐng)求的數(shù)據(jù)不在memcached中,就去查數(shù)據(jù)庫(kù),把從數(shù)據(jù)庫(kù)中獲取的數(shù)據(jù)返回給客戶(hù)端,同時(shí)把數(shù)據(jù)緩存一份到memcached中(memcached客戶(hù)端不負(fù)責(zé),需要程序明確實(shí)現(xiàn)),路徑操作為①②④⑤⑦⑥。
3、每次更新數(shù)據(jù)庫(kù)的同時(shí)更新memcached中的數(shù)據(jù),保證一致性。
4、當(dāng)分配給memcached內(nèi)存空間用完之后,會(huì)使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效數(shù)據(jù)首先被替換,然后再替換掉最近未使用的數(shù)據(jù)。
Memcached特征:
協(xié)議簡(jiǎn)單:
它是基于文本行的協(xié)議,直接通過(guò)telnet在memcached服務(wù)器上可進(jìn)行存取數(shù)據(jù)操作
注:文本行的協(xié)議:指的是信息以文本傳送,一個(gè)信息單元傳遞完畢后要傳送換行。比如對(duì)于HTTP的GET請(qǐng)求來(lái)說(shuō),GET /index.html HTTP/1.1是一行,接下去每個(gè)頭部信息各占一行。一個(gè)空行表示整個(gè)請(qǐng)求結(jié)束
基于libevent事件處理:
Libevent是一套利用C開(kāi)發(fā)的程序庫(kù),它將BSD系統(tǒng)的kqueue,Linux系統(tǒng)的epoll等事件處理功能封裝成一個(gè)接口,與傳統(tǒng)的select相比,提高了性能。
內(nèi)置的內(nèi)存管理方式:
所有數(shù)據(jù)都保存在內(nèi)存中,存取數(shù)據(jù)比硬盤(pán)快,當(dāng)內(nèi)存滿(mǎn)后,通過(guò)LRU算法自動(dòng)刪除不使用的緩存,但沒(méi)有考慮數(shù)據(jù)的容災(zāi)問(wèn)題,重啟服務(wù),所有數(shù)據(jù)會(huì)丟失。
分布式
各個(gè)memcached服務(wù)器之間互不通信,各自獨(dú)立存取數(shù)據(jù),不共享任何信息。服務(wù)器并不具有分布式功能,分布式部署取決于memcache客戶(hù)端。
Memcache的安裝
分為兩個(gè)過(guò)程:memcache服務(wù)器端的安裝和memcached客戶(hù)端的安裝。
所謂服務(wù)器端的安裝就是在服務(wù)器(一般都是linux系統(tǒng))上安裝Memcache實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)。
所謂客戶(hù)端的安裝就是指php(或者其他程序,Memcache還有其他不錯(cuò)的api接口提供)去使用服務(wù)器端的Memcache提供的數(shù)據(jù),需要php添加擴(kuò)展。
PHP的Memcache
二、centos7.2+nginx+php+memcache+mysql
環(huán)境描述:
OS:
1 2 | [root@www ~] # cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) |
1 2 3 4 5 6 7 8 9 10 | 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 |
1、安裝nginx(在192.168.31.141主機(jī)操作)
解壓zlib
1 | [root@www ~] # tar zxf zlib-1.2.8.tar.gz |
說(shuō)明:不需要編譯,只需要解壓就行。
解壓pcre
1 | [root@www ~] # tar zxf pcre-8.39.tar.gz |
說(shuō)明:不需要編譯,只需要解壓就行。
1 | [root@www ~] # yum -y install gcc gcc-c++ make libtool openssl openssl-devel |
下載nginx的源碼包:
1 | http: //nginx .org /download |
解壓源碼包:
1 2 3 4 | [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 #創(chuàng)建nginx運(yùn)行賬戶(hù)www并加入到www組,不允許www用戶(hù)直接登錄系統(tǒng) |
1 2 | [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:用來(lái)設(shè)置pcre的源碼目錄。
--with-zlib:用來(lái)設(shè)置zlib的源碼目錄。
因?yàn)榫幾gnginx需要用到這兩個(gè)庫(kù)的源碼。
1 2 | [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 |
啟動(dòng)nginx
1 2 3 4 5 6 7 | [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 |
啟動(dòng)后可以再瀏覽器中打開(kāi)頁(yè)面,會(huì)顯示nginx默認(rèn)頁(yè)面。
2、安裝php
安裝libmcrypt
1 2 3 4 5 6 7 8 9 | [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,修改后的內(nèi)容如下:
1 | short_open_tag = On // 支持php短標(biāo)簽 |
創(chuàng)建php-fpm服務(wù)啟動(dòng)腳本:
1 2 3 4 | [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配置文件并編輯:
1 2 | #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 |
修改內(nèi)容如下:
1 2 3 4 5 6 7 8 9 10 11 | 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 啟動(dòng)php-fpm服務(wù): [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 |
3、安裝mysql(在192.168.31.225主機(jī)操作)
因?yàn)閏entos7.2默認(rèn)安裝了mariadb-libs,所以先要卸載掉
查看是否安裝mariadb
1 | #rpm -qa | grep mariadb |
卸載mariadb
1 | rpm -e --nodeps mariadb-libs |
2、安裝依賴(lài)包
注: 相關(guān)依賴(lài)包的作用
cmake:由于從MySQL5.5版本開(kāi)始棄用了常規(guī)的configure編譯方法,所以需要CMake編譯器,用于設(shè)置mysql的編譯參數(shù)。如:安裝目錄、數(shù)據(jù)存放目錄、字符編碼、排序規(guī)則等。
Boost #從MySQL 5.7.5開(kāi)始Boost庫(kù)是必需的,mysql源碼中用到了C++的Boost庫(kù),要求必須安裝boost1.59.0或以上版本
GCC是Linux下的C語(yǔ)言編譯工具,mysql源碼編譯完全由C和C++編寫(xiě),要求必須安裝GCC
bison:Linux下C/C++語(yǔ)法分析器
ncurses:字符終端處理庫(kù)
1)安裝文件準(zhǔn)備
1 2 3 4 5 6 7 | 下載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
1 2 | tar zxf boost_1_59_0. tar .gz mv boost_1_59_0 /usr/local/boost |
3)創(chuàng)建mysql用戶(hù)和用戶(hù)組及目錄
1 2 3 | # groupadd -r mysql && useradd -r -g mysql -s /bin/false -M mysql---新建msyql組和msyql用戶(hù)禁止登錄shell #mkdir /usr/local/mysql ---創(chuàng)建目錄 #mkdir /usr/local/mysql/data ---數(shù)據(jù)庫(kù)目錄 |
3、編譯安裝mysql
解壓mysql源碼包:
執(zhí)行cmake命令進(jìn)行編譯前的配置:
開(kāi)始編譯、編譯安裝:
注1:配置解釋?zhuān)?/span>
1 2 3 4 5 6 7 8 9 10 11 12 | -DCMAKE_INSTALL_PREFIX= /usr/local/mysql [MySQL安裝的根目錄](méi)-DMYSQL_DATADIR= /usr/local/mysql /data [MySQL數(shù)據(jù)庫(kù)文件存放目錄](méi) -DSYSCONFDIR= /etc [MySQL配置文件所在目錄](méi) -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[安裝支持?jǐn)?shù)據(jù)庫(kù)分區(qū)] -DEXTRA_CHARSETS=all [使MySQL支持所有的擴(kuò)展字符] -DDEFAULT_CHARSET=utf8[設(shè)置MySQL的默認(rèn)字符集為utf8]-DDEFAULT_COLLATION=utf8_general_ci [設(shè)置默認(rèn)字符集校對(duì)規(guī)則] -DWITH-SYSTEMD=1 [可以使用systemd控制mysql服務(wù)] -DWITH_BOOST= /usr/local/boost [指向boost庫(kù)所在目錄](méi) 更多參數(shù)執(zhí)行[root@localhost mysql-5.7.13] # cmake . –LH |
注2:為了加快編譯速度可以按下面的方式編譯安裝
make -j $(grep processor /proc/cpuinfo | wc –l)
-j參數(shù)表示根據(jù)CPU核數(shù)指定編譯時(shí)的線(xiàn)程數(shù),可以加快編譯速度。默認(rèn)為1個(gè)線(xiàn)程編譯。
注3:若要重新運(yùn)行cmake配置,需要?jiǎng)h除CMakeCache.txt文件
# make clean
#rm -f CMakeCache.txt
優(yōu)化Mysql的執(zhí)行路徑
4、設(shè)置權(quán)限并初始化MySQL系統(tǒng)授權(quán)表
1 2 3 | # 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初始化操作時(shí)要加--user=mysql參數(shù),生成一個(gè)隨機(jī)密碼(注意保存登錄時(shí)用)
注2:MySQL 5.7.6之前的版本執(zhí)行這個(gè)腳本初始化系統(tǒng)數(shù)據(jù)庫(kù)
1 2 3 | /usr/local/mysql/bin/mysql_install_db --user=mysql --basedir= /usr/local/mysql --datadir= /usr/local/mysql/data # 5.7.6之后版本初始系統(tǒng)數(shù)據(jù)庫(kù)腳本(本文使用此方式初始化) #/usr/local/mysql/bin/mysqld --initialize-insecure--user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data |
注意:如果使用–initialize參數(shù)初始化系統(tǒng)數(shù)據(jù)庫(kù)之后,會(huì)生成root用戶(hù)的一個(gè)臨時(shí)密碼,如上圖高亮中所示。
1 | # chown -Rmysql:mysql . ---改所有者,注意是root . |
5、創(chuàng)建配置文件
1 2 | # cd/usr/local/mysql/support-files ---進(jìn)入MySQL安裝目錄支持文件目錄 # cp my-default.cnf /etc/my.cnf ---復(fù)制模板為新的配置文件, |
修改文件中配置選項(xiàng),如下圖所示,添加如下配置項(xiàng)
#vi /etc/my.cnf
6、配置mysql自動(dòng)啟動(dòng)
服務(wù)啟動(dòng)失敗,查看錯(cuò)誤日志文件
在mysqld.service,把默認(rèn)的pid文件指定到了/var/run/mysqld/目錄,而并沒(méi)有事先建立該目錄,因此要手動(dòng)建立該目錄并把權(quán)限賦給mysql用戶(hù)。
或者修改/usr/lib/system/system/mysqld.service,修改內(nèi)容如下:
#systemctl daemon-reload
再次啟動(dòng)mysql服務(wù)
查看端口號(hào)
服務(wù)啟動(dòng)成功
訪問(wèn)MySQL數(shù)據(jù)庫(kù)
# mysql -u root -h 127.0.0.1 -p ---連接mysql,輸入初始化時(shí)生成的隨機(jī)密碼
設(shè)置數(shù)據(jù)庫(kù)管理員用戶(hù)root的密碼
4、安裝memcached服務(wù)端(在192.168.31.250主機(jī)操作)
memcached是基于libevent的事件處理。libevent是個(gè)程序庫(kù),它將Linux的epoll、BSD類(lèi)操作系統(tǒng)的kqueue等事件處理功能封裝成統(tǒng)一的接口。即使對(duì)服務(wù)器的連接數(shù)增加,也能發(fā)揮I/O的性能。 memcached使用這個(gè)libevent庫(kù),因此能在Linux、BSD、Solaris等操作系統(tǒng)上發(fā)揮其高性能。
首先先安裝memcached依賴(lài)庫(kù)libevent
1 2 3 4 | [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
1 2 3 4 | [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 |
檢測(cè)是否成功安裝
1 2 | [root@memcache ~] # ls /usr/local/memcached/bin/memcached /usr/local/memcached/bin/memcached |
通過(guò)以上操作就很簡(jiǎn)單的把memcached服務(wù)端編譯好了。這時(shí)候就可以打開(kāi)服務(wù)端進(jìn)行工作了。
配置環(huán)境變量:
進(jìn)入用戶(hù)宿主目錄,編輯.bash_profile,為系統(tǒng)環(huán)境變量LD_LIBRARY_PATH增加新的目錄,需要增加的內(nèi)容如下:
1 2 3 4 | [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òng)參數(shù)說(shuō)明:
1 2 3 4 5 6 7 8 9 10 11 | -d 選項(xiàng)是啟動(dòng)一個(gè)守護(hù)進(jìn)程。 -m 分配給Memcache使用的內(nèi)存數(shù)量,單位是MB,默認(rèn)64MB。 -l 監(jiān)聽(tīng)的IP地址。(默認(rèn):INADDR_ANY,所有地址) -p 設(shè)置Memcache的TCP監(jiān)聽(tīng)的端口,最好是1024以上的端口。 -u 運(yùn)行Memcache的用戶(hù),如果當(dāng)前為root的話(huà),需要使用此參數(shù)指定用戶(hù)。 -c 選項(xiàng)是最大運(yùn)行的并發(fā)連接數(shù),默認(rèn)是1024。 -P 設(shè)置保存Memcache的pid文件。 -M 內(nèi)存耗盡時(shí)返回錯(cuò)誤,而不是刪除項(xiàng) -f 塊大小增長(zhǎng)因子,默認(rèn)是1.25 -n 最小分配空間,key+value+flags默認(rèn)是48 -h 顯示幫助 |
1 2 3 4 5 6 7 | [root@memcache ~] # netstat -anpt |grep memcached tcp 0 0 192.168.31.250:11211 0.0.0.0:* LISTEN 12840 /memcached 設(shè)置防火墻: [root@memcache ~] # firewall-cmd --permanent --add-port=11211/tcp success [root@memcache ~] # firewall-cmd --reload success |
刷新用戶(hù)環(huán)境變量:
1 | [root@memcache ~] # source ~/.bash_profile |
編寫(xiě)memcached服務(wù)啟停腳本
1 | [root@memcache ~] # vi /etc/init.d/memcached |
腳本內(nèi)容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | [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 |
設(shè)置腳本可被執(zhí)行:
1 2 3 | [root@memcache ~] # chmod +x /etc/init.d/memcached [root@memcache ~] # chkconfig --add memcached [root@memcache ~] # chkconfig memcached on |
說(shuō)明:
shell腳本中return的作用
1)終止一個(gè)函數(shù).
2)return命令允許帶一個(gè)整型參數(shù), 這個(gè)整數(shù)將作為函數(shù)的"退出狀態(tài)
碼"返回給調(diào)用這個(gè)函數(shù)的腳本, 并且這個(gè)整數(shù)也被賦值給變量$?.
3)命令格式:return value
5、配置nginx.conf文件(在nginx主機(jī)操作)
配置內(nèi)容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 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服務(wù)
生成一個(gè)php測(cè)試頁(yè)
1 2 3 4 | [root@www memcache-3.0.8] # cat /usr/local/nginx1.10/html/test1.php <?php phpinfo(); ?> |
使用瀏覽器訪問(wèn)test1.php測(cè)試頁(yè)
6、memcache客戶(hù)端(在php服務(wù)器操作):
memcache分為服務(wù)端和客戶(hù)端。服務(wù)端用來(lái)存放緩存,客戶(hù)端用來(lái)操作緩存。
安裝php擴(kuò)展庫(kù)(phpmemcache)。
安裝PHP Memcache擴(kuò)展:
可以使用php自帶的pecl安裝程序
1 | # /usr/local/php5.6/bin/pecl install memcache |
也可以從源碼安裝,他是生成php的擴(kuò)展庫(kù)文件memcache.so。
安裝memcache擴(kuò)展庫(kù)
1 2 3 4 5 | [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 |
安裝完后會(huì)有類(lèi)似這樣的提示:
1 | Installing shared extensions: /usr/local/php5 .6 /lib/php/extensions/no-debug-zts-20131226/ |
把這個(gè)記住,然后修改php.ini
添加一行
1 | extension= /usr/local/php5 .6 /lib/php/extensions/no-debug-zts-20131226/memcache .so |
重啟php-fpm服務(wù)
1 2 3 | [root@www memcache-3.0.8] # service php-fpm restart Gracefully shutting down php-fpm . done Starting php-fpm done |
測(cè)試:
檢查php擴(kuò)展是否正確安裝
1、[root@www html]# /usr/local/php5.6/bin/php -m
命令行執(zhí)行php -m 查詢(xún)結(jié)果中是否有memcache項(xiàng)
2、創(chuàng)建phpinfo()頁(yè)面,查詢(xún)session項(xiàng)下面的Registered save handlers值中是否有memcache項(xiàng)
瀏覽器訪問(wèn)test1.php
測(cè)試代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [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); ?> |
瀏覽器訪問(wèn)test2.php
使用memcache實(shí)現(xiàn)session共享
配置php.ini中的Session為memcache方式。
1 2 | 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:設(shè)置session的儲(chǔ)存方式為memcache 。默認(rèn)以文件方式存取session數(shù)據(jù),如果想要使用自定義的處理來(lái)存取session數(shù)據(jù),比如memcache方式則修為session.save_handler = memcache
session.save_path:設(shè)置session儲(chǔ)存的位置,多臺(tái)memcache用逗號(hào)隔開(kāi)
使用多個(gè) memcached server 時(shí)用逗號(hào)”,”隔開(kāi),可以帶額外的參數(shù)”persistent”、”weight”、”timeout”、”retry_interval”等等,
類(lèi)似這樣的:"tcp://host:port?persistent=1&weight=2,tcp://host2:port2"。
memcache實(shí)現(xiàn)session共享也可以在某個(gè)一個(gè)應(yīng)用中設(shè)置:
ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://192.168.0.9:11211");
ini_set()只對(duì)當(dāng)前php頁(yè)面有效,并且不會(huì)去修改php.ini文件本身,也不會(huì)影響其他php頁(yè)面。
測(cè)試memcache可用性
重啟php-fpm
在web服務(wù)器上新建//usr/local/nginx1.10/html/memcache.php文件。內(nèi)容如
1 2 3 4 5 6 7 8 9 10 | <?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 />" ; ?> |
訪問(wèn)網(wǎng)址http://192.168.31.141/memcache.php可以查看session_time是否都是為memcache中的Session,同時(shí)可以在不同的服務(wù)器上修改不同的標(biāo)識(shí)查看是否為不同的服務(wù)器上的。
可以直接用sessionid 去 memcached 里查詢(xún)一下:
1 2 3 4 5 6 7 | [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;這樣的結(jié)果,說(shuō)明session 正常工作
默認(rèn)memcache會(huì)監(jiān)聽(tīng)11221端口,如果想清空服務(wù)器上memecache的緩存,一般使用的是:
1 2 3 4 5 6 | [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 |
同樣也可以使用:
1 2 | [root@memcache ~] # echo "flush_all" | nc 192.168.31.250 11211 OK |
使用flush_all 后并不是刪除memcache上的key,而是置為過(guò)期
memcache安全配置
因?yàn)閙emcache不進(jìn)行權(quán)限控制,因此需要通過(guò)iptables將memcache僅開(kāi)放個(gè)web服務(wù)器。
7、測(cè)試memcache緩存數(shù)據(jù)庫(kù)數(shù)據(jù)
在Mysql服務(wù)器上創(chuàng)建測(cè)試表
1 2 | mysql> create database testdb1; Query OK, 1 row affected (0.00 sec) |
1 2 3 4 | 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) |
1 2 3 | 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 |
1 2 3 4 5 6 7 8 9 10 11 | mysql> select * from test1; +----+------+ | id | name | +----+------+ | 1 | tom1 | | 2 | tom2 | | 3 | tom3 | | 4 | tom4 | | 5 | tom5 | +----+------+ 5 rows in set (0.00 sec) |
測(cè)試
下面就是測(cè)試的工作了,這里有個(gè)php腳本,用于測(cè)試memcache是否緩存數(shù)據(jù)成功
需要為這個(gè)腳本添加一個(gè)只讀的數(shù)據(jù)庫(kù)用戶(hù),命令格式
1 2 | mysql> grant select on testdb1.* to user@ '%' identified by '123456' ; Query OK, 0 rows affected, 1 warning (0.00 sec) |
在web服務(wù)器上創(chuàng)建測(cè)試腳本內(nèi)容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | [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>" ; } ?> |
訪問(wèn)頁(yè)面測(cè)試
如果出現(xiàn)mysql表示memcached中沒(méi)有內(nèi)容,需要memcached從數(shù)據(jù)庫(kù)中取得
再刷新頁(yè)面,如果有memcache標(biāo)志表示這次的數(shù)據(jù)是從memcached中取得的。
memcached有個(gè)緩存時(shí)間默認(rèn)是1分鐘,過(guò)了一分鐘后,memcached需要重新從數(shù)據(jù)庫(kù)中取得數(shù)據(jù)
查看 Memcached 緩存情況
我們需要使用 telnet 命令查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | [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 進(jìn)程的ID STAT uptime 8429 // 進(jìn)程運(yùn)行時(shí)間 STAT time 1479142306 // 當(dāng)前時(shí)間 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 // 總共獲取數(shù)據(jù)的次數(shù)(等于 get_hits + get_misses ) STAT cmd_set 19 // 總共設(shè)置數(shù)據(jù)的次數(shù) STAT cmd_flush 4 STAT cmd_touch 0 STAT get_hits 15 // 命中了多少次數(shù)據(jù),也就是從 Memcached 緩存中成功獲取數(shù)據(jù)的次數(shù) STAT get_misses 10 // 沒(méi)有命中的次數(shù) 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 // 總的存儲(chǔ)大小,默認(rèn)為 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 // 當(dāng)前所用存儲(chǔ)大小 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 |
本文出自 “一盞燭光” 博客,謝絕轉(zhuǎn)載!
更多建議: