系統講解PHP快取技術

2022-12-29 18:00:51
本篇文章給大家帶來了關於的相關知識,其中主要介紹了快取技術的相關內容,快取已經成了專案中必不可少的一部分,是提高效能最好的方式,下面一起來看一下,希望對大家有幫助。

概述

36.png

快取已經成了專案中是必不可少的一部分,它是提高效能最好的方式,例如減少網路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');
登入後複製

使用者操作行為對快取的影響

37.png

檔案快取

資料檔案快取

將更新頻率低,讀取頻率高的資料,快取成檔案。

比如,專案中多個地方用到城市資料做三級聯動,我們就可以將城市資料快取成一個檔案(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>
登入後複製

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 = json_encode(使用者資料)

查詢時,先取出key,然後進行json_decode解析。

方案二:hash

key = userdata使用者ID

hashKey = 姓名,value = 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值,設定空快取和過期時間,如果儲存層建立了資料,及時更新快取。

雪崩怎麼辦?

一、互斥鎖,只允許一個請求去重建索引,其他請求等待快取重建執行完,重新從快取獲取資料。

1.jpg

二、雙快取策略,原始快取和拷貝快取,當原始快取失效請求拷貝快取,原始快取失效時間設定為短期,拷貝快取設定為長期。

推薦學習:《》

以上就是系統講解PHP快取技術的詳細內容,更多請關注TW511.COM其它相關文章!