首頁 > php框架 > ThinkPHP > 主體

ThinkPHP快取原始碼深度解析

咔咔
發布: 2021-02-19 09:08:06
原創
1837 人瀏覽過

快取在專案的運行了一段時間都會使用的一個功能,本文將會對框架中的快取做一個深度的解析

前言

#在專案中快取是不可或缺的功能,當使用者量大的時候是必須上快取的,如何都直接查資料庫那麼對於使用者體驗來說就太差了。

那麼什麼情況下應該要使用快取呢!

  • 熱點事件,例如微博熱搜
  • #不經常更新的數據,例如配置項目
  • 部落格平台的排行榜單
  • 社群平台的追蹤清單粉絲清單等等

以上說的這些應用程式場景並不說是框架的緩存,一般在使用緩存的層面是不太使用框架的緩存的。

常用的為redis,memcache等NoSQL。

但是今天主要討論的是框架中緩存,所以千萬不要認為框架的緩存是無所不能的,還是要看項目的實際情況。

一、快取cache設定的執行流程以及原始碼解析

首先需要實作以下的案例,並且引入cache類別

ThinkPHP快取原始碼深度解析
示範案例

cache怎麼運作的?

就程式碼Cache::set這個現在知道是怎麼運行的嗎?如果不知道咔咔帶你在來深入的學習一次。

我們都知道框架的入口檔案是index.php,在入口檔案中引入了一個檔案為base.php。

ThinkPHP快取原始碼深度解析
入口檔案

來到base.php這個檔案裡邊可以看到關於註冊類別庫別名,至於是怎麼註冊的,這個在框架執行流程的那一節有過深度的講​​解,可以回過頭在去了解一下。

ThinkPHP快取原始碼深度解析
註冊類別庫別名

所以說程式碼將會執行到框架核心的facade這個類別裡邊,在這個類別裡邊存在一個方法__callStatic,當呼叫不存在的靜態方法時此方法會進行執行。

ThinkPHP快取原始碼深度解析
門面的核心類別

那麼怎麼來做這個驗證呢!不能喀喀這樣說就是這樣的對吧!

那麼程式碼將會接著來到創建Facade實例這個方法,我們做的測試就是將這個class印出來得到的值都有什麼。

ThinkPHP快取原始碼深度解析
建立Facade實例

暫時先不管這個cache執行了幾次,是可以明顯的看到列印結果是存在這個值的,所以說從另一個笨拙的方面驗證了咔咔的說辭。

ThinkPHP快取原始碼深度解析
列印的測試值

這裡有一個特別小的細節我想大家應該要了解一下,那就是關於static的使用

關於static的小技巧

首先可以看到cache類別是繼承這Facade門面類別

ThinkPHP快取原始碼深度解析
類別的繼承

然後static是在門面類別中做的使用,那麼最後回傳​​的類別就是繼承門面類別的那個類別也就是cache類別

ThinkPHP快取原始碼深度解析
門面類別示範

總結為一句話就為

static 如果有被繼承的話預設呼叫子類,否則呼叫的是自身

##所以說下邊接著的

static::getFacadeClass()這裡也是執行的子類別中的方法。

好了,進入了一段小插曲,接下來會到正題。

所以說程式碼將會執行到thinkphp/library/think/Cache.php這個文件,也就是核心類別庫的位置。

在這個方法你是找不到set方法的,所以程式碼將會執行到__call方法,這個方法當呼叫不存在的方法時則會觸發的方法。

ThinkPHP快取原始碼深度解析
快取的類別

自動初始化快取

根據執行流程我們將會看到init這個方法自動初始化快取(這裡要注意,第一次不是在這裡進行執行的,而是ThinkPHP快取原始碼深度解析,當ThinkPHP快取原始碼深度解析執行完後會把值存放在handler這個屬性,第二次透過call方法進來之後就直接返回了,而不會在進行一次執行,這裡一定要注意)

ThinkPHP快取原始碼深度解析
自動初始化快取

在這裡我們進行一次列印$options 這個的值。

ThinkPHP快取原始碼深度解析
列印結果

探討為什麼$options這個參數會有值

這裡就是關於容器方面的知識了,來喀喀帶你看一下。

ThinkPHP快取原始碼深度解析
ThinkPHP快取原始碼深度解析

當在建立Cache時建立Facade實例,在這個過程中註意咔咔下圖圈起來的部位,執行了一個見了八百次的ThinkPHP快取原始碼深度解析了。

ThinkPHP快取原始碼深度解析
建立Facade實例

來到ThinkPHP快取原始碼深度解析只需要看喀喀爾的地方即可

ThinkPHP快取原始碼深度解析第二次执行的位置
ThinkPHP快取原始碼深度解析第二次執行的位置

然後在進入到invokeClass方法,這個方法是呼叫反射執行類別的實例化支援依賴注入。

在這個方法中透過反射執行了Cache中的ThinkPHP快取原始碼深度解析。

调用反射执行类的实例化 支持依赖注入
呼叫反射執行類別的實例化支援依賴注入

所以就會執行Cache類別中的ThinkPHP快取原始碼深度解析,這個方法就會進行實例化本類,並且執行建構函數,接下來看一下。

缓存类的ThinkPHP快取原始碼深度解析
快取類別的ThinkPHP快取原始碼深度解析

來到建構子中你會看到從ThinkPHP快取原始碼深度解析取得到的cache設定檔的設定項傳遞到了init方法,也就是自動初始化快取的部分。

ThinkPHP快取原始碼深度解析
建構子

所以從這裡看到init方法自動初始化快取第一次執行是在容器實例化的時候執行的所以 $options才會存在值。

接下來會沿著這個流程進行連線快取也就是程式碼$this->handler = $this->connect($options);這塊的內容。

這個方法就很簡單了,就是使用了之前一直講解的工廠模式實作的載入不同類型的快取方式。

接著會把回傳的物件存放在以$optionsmd5為下標的快取實例屬性$instance裡邊。

ThinkPHP快取原始碼深度解析
連線快取

最終程式碼會傳回cache中的__call方法,類別為object(think\cache\driver\File)方法為set

ThinkPHP快取原始碼深度解析
呼叫不存在的方法時會執行

於是執行流程會來到下圖位置寫入快取

ThinkPHP快取原始碼深度解析
寫入快取

取得檔案名稱

在這個方法中主要需要理解的一件事情就是在快取中是如何進行獲取具體的檔案名稱然後進行儲存資料的。

這個name值就是咱們需要設定的值,wechat。

ThinkPHP快取原始碼深度解析
取得變數的儲存檔名

然後來到getCacheKey取得變數的儲存檔名。

在這個方法中第一步就是透過hash的方式進行型別和快取值加密,這個options是在本類別宣告好了的,這裡一定要明確。

因為框架中大量的使用了options這個變數千萬不要搞混淆了。

在這個方法中需要明白的就是這個檔名是怎麼確定的。

ThinkPHP快取原始碼深度解析
取得檔案名稱

還是要來到本類別的開始位置檢視一下這個options的值,在這個類別中可以看到上圖中使用的加密類型為hash_type就是md5

ThinkPHP快取原始碼深度解析
關於快取到檔案的值
##然後來到建構函式中可以看到關於path的設定

ThinkPHP快取原始碼深度解析取得快取檔案的路徑
在上圖中可以看到

Container::get('app')這行程式碼,這行程式碼就是使用的容器執行的也是ThinkPHP快取原始碼深度解析,關於這個ThinkPHP快取原始碼深度解析在容器中扮演的角色是十分大的,所以需要好好理解。

然後有一個小細節不知道大家有沒有看到,那就是在下方有一個init方法,我們一起去看看這個方法是做什麼的。

來到這個方法後你會發現這裡是直接按照取得到的快取檔案的路徑進行建立檔案。

ThinkPHP快取原始碼深度解析
初始化檢查

這時可以查看一下建立的文件,可以看到文件已經建立好了。

ThinkPHP快取原始碼深度解析
快取檔案的路徑

最後透過file_put_contents函數將資料存放至剛剛取得的快取檔案存放位置

ThinkPHP快取原始碼深度解析
在快取檔案中寫入資料

資料庫儲存形式就是下圖

ThinkPHP快取原始碼深度解析
#資料儲存形式

直到這裡關於框架快取設定就結束了,其實流程並不難,在這個案例中咔咔使用的檔案形式的,至於redis還是其它都是一樣的。

二、快取cache所取得的執行流程以及原始碼解析

既然學習了快取設定的原始碼解析,那麼也應該來簡單的了解一下快取所取得的源碼解析。

同樣示範案例還是之前的那個,只不過是把set換為get即可

ThinkPHP快取原始碼深度解析
示範案例

跟設定快取的流程是一樣的,首先會來到門面類別中建立快取的對應實例

ThinkPHP快取原始碼深度解析
#門面類別建立快取實例

門面類別創建了快取類別的時候之後就會來到cache類別這個檔案thinkphp/library/think/Cache.php

#在這個檔案中可以看到還是使用了__call方法,這個方法就是呼叫不存在的方法會執行。

ThinkPHP快取原始碼深度解析
快取的檔案

接著會來到這init方法,這個方法在設定快取值的時候已經進行深入講解了。

根據執行流程我們將會看到init這個方法自動初始化快取(這裡要注意,第一次並不是在這裡進行執行的,而是ThinkPHP快取原始碼深度解析,當ThinkPHP快取原始碼深度解析執行完後會把值存放在handler這個屬性,第二次透過call方法進來之後就直接返回了,而不會在進行一次執行,這裡一定要注意)

這裡為什麼先會執行cache的ThinkPHP快取原始碼深度解析,是因為在容器中建立cache類別實例的時候會在ThinkPHP快取原始碼深度解析中判斷類別中是否存在ThinkPHP快取原始碼深度解析,如果存在就會先執行。

ThinkPHP快取原始碼深度解析
自動初始化快取

所以說在cache這個類別中return call_user_func_array([$this->init(), $method], $args );這塊程式碼會去執行thinkphp/library/think/cache/driver/File.php這個類別的get方法

ThinkPHP快取原始碼深度解析##讀取快取
在這個類別中你可以看到一個在設定快取值時花了好久解析的一個方法

getCacheKey

在這個方法中主要就是使用了sbustr來進行了加密值的節,前兩個值為目錄,其餘字元為檔案名稱。

然後將檔案名稱給回傳。

ThinkPHP快取原始碼深度解析取得變數的儲存檔案名稱
然後就使用file_get_contents來將檔案的內容取得出來

ThinkPHP快取原始碼深度解析
讀取檔案內容

然後可以接著往下看,這裡有一個過期刪除快取檔案。

框架中的過期策略是當你設定了過期時間時,快取過期後不會直接刪除而是當你再一次造訪之後才會進行刪除。

這種策略就是redis中的惰性刪除,當我們使用惰性刪除時,資料到期了也不會自動刪除,那麼他的刪除方式是,在下一次在取得這個key值時,會做一個判斷,判斷這個key是否過期,如果過期了在執行刪除。

ThinkPHP快取原始碼深度解析
過期杉樹快取檔案

截止到這裡關於快取取得的執行流程已經原始碼解析就完成了,其實大多數內容在取得的時候就已經解析完了。

那為什麼還是要在聊一下取得快取數據,那是因為這裡還需要給大家在解釋一些東西。

三、資料壓縮

#在設定快取的時候將快取的值寫入檔案時有過一個函數gzcompress

然而在取得快取值的時候從檔案將資料讀出時又遇到的一個函數gzuncompress

其實從設定快取和取得快取的這兩個功能中就可以看出,設定的為壓縮數據,所取得的解壓縮數據。

在PHP中關於壓縮函數還有其它兩個分別為gzdeflate、gzencode,同樣的解壓縮函數也是對應的gzinflate gzdecode

#這幾個函數雖說都是壓縮函數,但是底層實作是不一樣的。

gzcompress使用的是ZLIB格式;

gzdeflate使用的是純粹的DEFLATE格式;

gzencode使用的是GZIP格式;

以上就是關於資料壓縮和解壓的一些知識,了解即可。

四、總結

#在這一節中咔咔帶大家領略了框架對於快取的處理結果。

其實咔咔之前測試過關於框架自帶的快取回應時間應該會縮短三分之一,當然這個也是根據資料量的大小有區別的。

至此關於PHP框架ThinkPHP的原始碼解讀這裡就結束了,後期如果有時間將會對其中一些沒有提到的內容在進行解讀。

最後說一句閱讀原始碼是真的累。

堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在諾大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。

#

以上是ThinkPHP快取原始碼深度解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!