系統的講解 - PHP 緩存技術

概述



緩存已經成了項目中是必不可少的一部分,它是提升性能最好的方式,例如減小網絡I/O、減小磁盤I/O 等,使項目加載速度變的更快。

緩存能夠是CPU緩存、內存緩存、硬盤緩存,不一樣的緩存查詢速度也不同(CPU緩存 優於 內存緩存 優於 硬盤緩存)。

接下來,給你們逐一進行介紹。
瀏覽器緩存

瀏覽器將請求過的頁面存儲在客戶端緩存中,當訪問者再次訪問這個頁面時,瀏覽器就能夠直接從客戶端緩存中讀取數據,減小了對服務器的訪問,加快了網頁的加載速度。
強緩存

用戶發送的請求,直接從客戶端緩存中獲取,不請求服務器。

根據 Expires 和 Cache-Control 判斷是否命中強緩存。

代碼以下:

 javascript

   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:禁止緩存數據

 



協商緩存

用戶發送的請求,發送給服務器,由服務器斷定是否使用客戶端緩存。

代碼以下:

  php

 $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

指定緩存的過時時間:

css

    <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 等。

html

打開 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 ,爲何?

舉一些場景:

1、好比實現一個簡單的日誌收集功能或發送大量短信、郵件的功能,實現方式是先將數據收集到隊列中,而後有一個定時任務去消耗隊列,處理該作的事情。

直接使用 Redis 的 lpush,rpop 或 rpush,lpop。java

    //進隊列    
    $redis->lpush(key, value);    
    //出隊列    
    $redis->rpop(key);

Memcached 沒有這種數據結構。

 



2、好比咱們要存儲用戶信息,ID、姓名、電話、年齡、身高 ,怎麼存儲?

nginx

方案一: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); //查詢某個屬性

 



方案二 優於 方案一。

3、好比社交項目相似於新浪微博,我的中心的關注列表和粉絲列表,雙向關注列表,還有熱門微博,還有消息訂閱 等等。

以上都用 Redis 提供的相關數據結構便可。

4、Memcached 只存儲在內存中,而 Redis 既能夠存儲在內存中,也能夠持久化到磁盤上。

若是需求中的數據須要持久化,請選擇 Redis 。

我的在工做中沒有用到 Memcached ,經過查詢資料獲得 Memcached 內存分配時優於 Redis。

Memcached 默認使用 Slab Allocation 機制管理內存,按照預先規定的大小,將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以徹底解決內存碎片問題。
如何保證,緩存與數據庫的數據一致性?

新增數據:先新增到數據庫,再新增到緩存。

編輯數據:先刪除緩存數據,再修改數據庫中數據,再新增到緩存。

刪除數據:先刪除緩存數據,再刪除數據庫中數據。

查詢數據:先查詢緩存數據,沒有,再查詢數據庫,再新增到緩存。

強一致性是很難保證的,好比事務一致性,時間點一致性,最終一致性等。

具體問題具體分析吧。
緩存穿透怎麼辦?

用戶請求緩存中不存在的數據,致使請求直接落在數據庫上。

1、設置有規則的Key值,先驗證Key是否符合規範。

2、接口限流、降級、熔斷,請研究 istio:https://istio.io/

3、布隆過濾器。

4、爲不存在的key值,設置空緩存和過時時間,若是存儲層建立了數據,及時更新緩存。
雪崩怎麼辦?

1、互斥鎖,只容許一個請求去重建索引,其餘請求等待緩存重建執行完,從新從緩存獲取數據。


2、雙緩存策略,原始緩存和拷貝緩存,當原始緩存失效請求拷貝緩存,原始緩存失效時間設置爲短時間,拷貝緩存設置爲長期。

已上,純屬拋轉引玉,結合本身的狀況,具體問題,具體分析吧。

redis

相關文章
相關標籤/搜索