緩存,顧名思義,就是臨時存儲信息以提高訪問性能。PHP的緩存技術大體可分為三大類:
1. 緩存內容(Caching content)
2. 內存緩存(Memory Cache)
3. 數據庫緩存(Database Cache)
1. 緩存內容
將某個腳本的最終輸出作為靜態文件存放在文件系統中,比如??信息,商品顯示頁,當數據庫內容被修改或文件過期時,重新執行原始腳本以更新緩存內容。簡單示例如下:
內容緩存是最為常見的,比如輸出緩存ob_start,頁面部分緩存ob_get_contents,甚至數據庫某些查詢結果的緩存。
2. 內存緩存
顧名思義,通過內存進行緩存,顯然會比緩存在文件系統中快出許多,常見的技術如下:
Opcode Cache
簡要介紹下PHP的運行機制:a)子進程解釋器解析php腳本,比如Zend Complier; b)zend_language_scanner會首先對代碼進行掃描,將PHP代碼進行詞法分析,轉化為一系列的token array;c)zend_language_parse將上一步產生的一系列token處理空格等無用的代碼后轉化成一系列表達式;d)這些表達式經過complier階段生成opcode【即Operation code,是一個四元組(opcode,op1,op2,result)】并返回zend_op_array指針;e)zend_vm_execute根據傳入的zend_op_array指針,執行opcode并將結果返回輸出;
對opcode進行緩存的軟件很多,比如apc,eAcclerator,Xcache,Zend Platform,這里主要介紹下apc;
APC提供了兩種緩存功能:緩存Opcode(目標文件),即apc_complier_cache,緩存用戶數據即apc_user_cache. 下圖為使用了apc_complier_cache后的php解析過程:
由于apc并未內置到PHP解釋器內核中,你需要單獨安裝并在php.ini中添加apc配置:
apc的使用是比較簡單的,主要比較常用的有三個方法:
apc_add/apc_store–?store a variable in the cache. The only difference betweenapc_addandapc_storeis thatapc_storeoverwrites the data if it already exists andapc_adddoes not。
apc_fetch– fetch a variable from the cache
apc_delete– delete a variable from the cache.
http://www.360doc.com/content/16/0204/17/22355405_532718314.shtml
據說apc使用了spinlocks(自旋)鎖機制,能夠達到最佳性能,但這也可能會死鎖,進而影響到php-fpm進程(https://yq.aliyun.com/articles/1699);
一方面apc_store對于系統設置等PHP變量的緩存是比較好的選擇,但apc不合適通過apc_store頻繁變更用戶數據,會出現一些奇異現象;
Memcache
分布式對象緩存系統,通過在內存中以鍵值對的形式緩存數據和對象以減少讀取數據庫的次數,進而提高驅動網站的速度。它可以應對任意多個連接,使用非阻塞的網絡IO。
Memcache與memcached區別:Memcache是項目名稱,而memcached是項目在服務器段的主程序文件名;
所謂的分布式對象緩存體現,單個服務器就算了,比如現memcache客戶端要添加“shanghai”,客戶端根據查詢算法(比如Consistent hashing)根據“鍵”來決定保存數據的memcached服務器。至于memcache服務器端,它會在內存中開辟一塊空間,然后建立一個HashTable, 并復制管理維護?!皊hanghai”到了選定的服務器后,將“shanghai”維護到HashTable,并在內存中保存其值。
同樣在獲取保存的數據時,比如鍵值“hangzhou”,memcache客戶端會通過相同的方式,根據鍵值選擇服務器,然后發送get命令取得value,當然若不幸該鍵值尚不存在或已失效,那就從元數據取之并reset。這樣鍵值對通過HashTable存儲到不同的服務器上,就實現了memcached的分布式。
注意:查詢算法因節點分布不均而造成的數據傾斜問題,memcache服務器增多是否會影響鍵值的重新分布以及增減服務器是否會導致緩存的大范圍丟失。
Memcache區分為memcache服務器端的安裝和memcache客戶端安裝,默認端口號11211。簡單示例如下:
既然是緩存,定是有過期時間的,比如上述圖片中set('things',$things,false,86400),對memcache而言,它不會在過期監視上耗費CPU時間,當某個值過期后,其內存并沒有被刪除,而是當再次在get時查看記錄的時間戳,檢查記錄是否過期,如果已過期,則返回空并且清空,這種技術被稱為lazy(惰性)expiration。
另外,memcache會優先使用已超時記錄的空間,但即使如此,也會發生追加新紀錄時空間不足的情況,此時就要使用Least Recently Used(LRU)機制來分配空間【即使某個key設置的是永久有效期】。
對于分布式的對象緩存系統memcache,其須以root權限運行,且訪問是無用戶狀態的,考慮到安全性,一般通過放在內網,并通過防火墻限制外網訪問memcache端口達到安全。
數據庫緩存
上述的緩存技術都是在應用層討論的,database server本身也可以cache,典型的就是SQL第一次查詢時解析,后續查詢則直接從database server cache中獲取結果。簡單config MySQL my.cnf如下:
query_cache_type =1
query_cache_limit = 1M
query_cache_size =16M