概述
快取已經成了專案中是必不可少的一部分,它是提高性能最好的方式,例如減少網路I/O、減少磁盤I/O 等,使專案加載速度變的更快,
快取可以是CPU快取、記憶體快取、硬碟快取,不同的快取查詢速度也不一樣(CPU快取 優于 記憶體快取 優于 硬碟快取),
接下來,給大家逐一進行介紹,
瀏覽器快取
瀏覽器將請求過的頁面存盤在客戶端快取中,當訪問者再次訪問這個頁面時,瀏覽器就可以直接從客戶端快取中讀取資料,減少了對服務器的訪問,加快了網頁的加載速度,
強快取
用戶發送的請求,直接從客戶端快取中獲取,不請求服務器,
根據 Expires 和 Cache-Control 判斷是否命中強快取,
代碼如下:
header('Expires: '. gmdate('D, d M Y H:i:s', time() + 3600). ' GMT');
header("Cache-Control: max-age=3600"); //有效期3600秒
Cache-Control 還可以設定以下引數:
public:可以被所有的用戶快取(終端用戶的瀏覽器/CDN服務器)
private:只能被終端用戶的瀏覽器快取
no-cache:不使用本地快取
no-store:禁止快取資料
協商快取
用戶發送的請求,發送給服務器,由服務器判定是否使用客戶端快取,
代碼如下:
$last_modify = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if (time() - $last_modify < 3600) {
header('Last-Modified: '. gmdate('D, d M Y H:i:s', $last_modify).' GMT');
header('HTTP/1.1 304'); //Not Modified
exit;
}
header('Last-Modified: '. gmdate('D, d M Y H:i:s').' GMT');
用戶操作行為對快取的影響
操作行為 Expires Last-Modified
地址欄回車 有效 有效
頁面跳轉 有效 有效
新開視窗 有效 有效
前進/后退 有效 有效
F5重繪 無效 有效
Ctrl+F5重繪 無效 無效
檔案快取
資料檔案快取
將更新頻率低,讀取頻率高的資料,快取成檔案,
比如,專案中多個地方用到城市資料做三級聯動,我們就可以將城市資料快取成一個檔案(city_data.json),JS 可以直接讀取這個檔案,無需請求后端服務器,
全站靜態化
CMS(內容管理系統),也許大家都比較熟悉,比如早期的 DEDE、PHPCMS,后臺都可以設定靜態化HTML,用戶在訪問網站的時候讀取的都是靜態HTML,不用請求后端的資料庫,也不用Ajax請求資料介面,加快了網站的加載速度,
靜態化HTML有以下優點:
有利于搜索引擎的收錄(SEO)
頁面打開速度快
減少服務器負擔
CDN快取
CDN(Content Delivery Network)內容分發網路,
用戶訪問網站時,自動選擇就近的CDN節點內容,不需要請求源服務器,加快了網站的打開速度,
快取主要包括 HTML、圖片、CSS、JS、XML 等靜態資源,
NoSQL快取
Memcached 快取
Memcached 是高性能的分布式記憶體快取服務器,
一般的使用目的是,通過快取資料庫查詢結果,減少資料庫訪問次數,以提高動態Web應用的速度、提高可擴展性,
它也能夠用來存盤各種格式的資料,包括影像、視頻、檔案等,
Memcached 僅支持K/V型別的資料,不支持持久化存盤,
Memcache 與 Memcached 的區別
Memcached 從0.2.0開始,要求PHP版本>=5.2.0,Memcache 要求PHP版本>=4.3,
Memcached 最后發布時間為2018-12-24,Memcache 最后發布時間2013-04-07,
Memcached 基于libmemcached,Memcache 基于PECL擴展,
可以將 Memcached 看作是 Memcache 的升級版,
PHP Memcached 使用手冊:
http://www.php.net/manual/zh/book.memcached.php
Memcached 經常拿來與 Redis 做對比,接下來介紹下 Redis 快取,
Redis快取
Redis 是一個高性能的 K/V 資料庫,
Redis 很大程度補償了 Memcached K/V存盤的不足,比如 List(鏈表)、Set(集合)、Zset(有序集合)、Hash(散列),既可以將資料存盤在記憶體中,也可以將資料持久化到磁盤上,支持主從同步,
總的來說,可以將 Redis 看作是 Memcached 的擴展版,更加重量級,功能更強大,
Redis 在日常作業中使用的居多,
Redis 學習網址:http://www.redis.cn/
MongoDB快取
MongoDB 是一個基于分布式檔案存盤的資料庫,由 C++ 語言撰寫,
旨在為 WEB 應用提供可擴展的高性能資料存盤解決方案,
MongoDB 是一個介于關系資料庫和非關系資料庫之間的產品,是非關系資料庫當中功能最豐富,最像關系資料庫的,
MongoDB 學習網址:http://www.mongodb.org.cn
WEB服務器快取
Apache快取
利用 mod_expires ,指定快取的過期時間,可以快取HTML、圖片、JS、CSS 等,
打開 http.conf,開啟模塊:
LoadModule expires_module modules/mod_expires.so
指定快取的過期時間:
<IfModule expires_module>
#打開快取
ExpiresActive on
#css快取(8640000秒=10天)
ExpiresByType text/css A8640000
#js快取
ExpiresByType application/x-javascript A8640000
ExpiresByType application/javascript A8640000
#html快取
ExpiresByType text/html A8640000
#圖片快取
ExpiresByType image/jpeg A8640000
ExpiresByType image/gif A8640000
ExpiresByType image/png A8640000
ExpiresByType image/x-icon A8640000
</IfModule>
這里我還準備了一分學習圖和資料,如下:

鏈接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取碼:x2p5
免費分享,但是X度限制嚴重,如若鏈接失效點擊鏈接或搜索加群 群號518475424,
Nginx快取
利用 expire 引數,指定快取的過期時間,可以快取HTML、圖片、JS、CSS 等,
打開 nginx.conf :
//以圖片為例:
location ~\.(gif|jpg|jepg|png|bmp|ico)$ { #加入新的location
root html;
expires 1d; #指定快取時間
}
大家也可以了解下:proxycachepath 和 proxy_cache,進行快取的設定,
Opcode快取
Opcode(Operate Code)操作碼,
PHP程式運行完后,馬上釋放所有記憶體,所有程式中的變數都銷毀,每次請求都要重新翻譯、執行,導致速度可能會偏慢,
當解釋器完成對腳本代碼的分析后,便將它們生成可以直接運行的中間代碼,也稱為操作碼,
操作碼 的目地是避免重復編譯,減少CPU和記憶體開銷,
APC快取
APC(Alternative PHP Cache)可選 PHP 快取,
APC 的目標是提供一個自由、 開放,和健全的框架,用于快取、優化 PHP 中間代碼,
APC 可以去掉 php 動態決議以及編譯的時間,使php腳本可以執行的更快,
APC 擴展最后的發布時間為 2012-09-03,
感興趣可以了解下,官方介紹:http://php.net/manual/zh/book.apc.php
eAccelerator
eAccelerator:A PHP opcode cache,
感興趣可以了解下,官方介紹:http://eaccelerator.net/
XCache
XCache 是一個又快又穩定的 PHP opcode 快取器,
感興趣可以了解下,官方介紹:http://xcache.lighttpd.net/
小結
文章主要簡單的介紹了 瀏覽器快取、檔案快取、NoSQL快取、WEB服務器快取、Opcode快取,
每一種快取都可以深入研究,從介紹 -> 安裝 -> 使用 -> 總結應用場景,
大家可以思考下,通過上面的介紹,作業中我們使用了哪些快取?
還可以再使用哪些快取,可以對我們的專案有幫助?
關于快取的常見問題
用過快取,大家肯定遇到過比較頭痛的問題,比如資料一致性,雪崩,熱點資料快取,快取監控等等,
給大家列出幾個問題,純屬拋轉引玉,
當專案中使用到快取,我們是選擇 Redis 還是 Memcached ,為什么?
舉一些場景:
一、比如實作一個簡單的日志收集功能或發送大量短信、郵件的功能,實作方式是先將資料收集到佇列中,然后有一個定時任務去消耗佇列,處理該做的事情,
直接使用 Redis 的 lpush,rpop 或 rpush,lpop,
//進佇列
$redis->lpush(key, value);
//出佇列
$redis->rpop(key);
Memcached 沒有這種資料結構,
二、比如我們要存盤用戶資訊,ID、姓名、電話、年齡、身高 ,怎么存盤?
方案一:key => value key = userdata用戶ID value = https://www.cnblogs.com/it-3327/p/json_encode(用戶資料) 查詢時,先取出key,然后進行json_decode決議,
方案二:hash
key = userdata用戶ID hashKey = 姓名,value = https://www.cnblogs.com/it-3327/p/xx hashKey = 電話,value = xx hashKey = 年齡,value = xx hashKey = 身高,value = xx
查詢時,取出key即可,
//新增
$redis->hSet(key, hashKey, value);
$redis->hSet(key, hashKey, value);
$redis->hSet(key, hashKey, value);
//編輯
$redis->hSet(key, hashKey, value);
//查詢
$redis->hGetAll(key); //查詢所有屬性
$redis->hGet(key, hashKey); //查詢某個屬性
方案二 優于 方案一,
三、比如社交專案類似于新浪微博,個人中心的關注串列和粉絲串列,雙向關注串列,還有熱門微博,還有訊息訂閱 等等,
以上都用 Redis 提供的相關資料結構即可,
四、Memcached 只存盤在記憶體中,而 Redis 既可以存盤在記憶體中,也可以持久化到磁盤上,
如果需求中的資料需要持久化,請選擇 Redis ,
個人在作業中沒有用到 Memcached ,通過查詢資料得到 Memcached 記憶體分配時優于 Redis,
Memcached 默認使用 Slab Allocation 機制管理記憶體,按照預先規定的大小,將分配的記憶體分割成特定長度的塊以存盤相應長度的key-value資料記錄,以完全解決記憶體碎片問題,
如何保證,快取與資料庫的資料一致性?
新增資料:先新增到資料庫,再新增到快取,
編輯資料:先洗掉快取資料,再修改資料庫中資料,再新增到快取,
洗掉資料:先洗掉快取資料,再洗掉資料庫中資料,
查詢資料:先查詢快取資料,沒有,再查詢資料庫,再新增到快取,
強一致性是很難保證的,比如事務一致性,時間點一致性,最終一致性等,
具體問題具體分析吧,
快取穿透怎么辦?
用戶請求快取中不存在的資料,導致請求直接落在資料庫上,
一、設定有規則的Key值,先驗證Key是否符合規范,
二、介面限流、降級、熔斷,請研究 istio:https://istio.io/
三、布隆過濾器,
四、為不存在的key值,設定空快取和過期時間,如果存盤層創建了資料,及時更新快取,
雪崩怎么辦?
一、互斥鎖,只允許一個請求去重建索引,其他請求等待快取重建執行完,重新從快取獲取資料,
二、雙快取策略,原始快取和拷貝快取,當原始快取失效請求拷貝快取,原始快取失效時間設定為短期,拷貝快取設定為長期,
已上,純屬拋轉引玉,結合自己的情況,具體問題,具體分析吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/117793.html
標籤:PHP
