首頁 後端開發 php教程 TP5之Cache的原理及使用

TP5之Cache的原理及使用

May 11, 2018 pm 03:09 PM
cache php tp5

在当今大流量的互联网之中,Cache的重要性不言而喻。ThinkPhp5作为国内主流框架,提供了强大的Cache功能。让我们跟随本文,来剖析TP5 Cache的原理及使用。

为什么需要Cache(缓存)?

假设现在有一个小说网,有非常多的读者,有一篇新的章节更新了,那么可能一分钟内有几万几十万的访问量.

如果没有缓存,同样的内容就要去数据库重复查询,那可能网站一下就挂掉了.

追求性能的web站点应该充分利用缓存,常见的缓存类型有File,Memcache,Redis等,这里就不说他们的区别了

今天我们分析下TP5 Cache的内部实现原理.

首先看官方文档如何使用缓存的.

TP5之Cache的原理及使用

如上图,调用Cache类的的静态方法set就可以直接使用了,我们查看Cache类文件  在application/thinkphp/library/think目录下

   protected static $instance = [];    
   public static $readTimes   = 0;    
   public static $writeTimes  = 0;   
   /**
     * 操作句柄
     * @var object
     * @access protected     */
    protected static $handler;     /**
     * 写入缓存
     * @access public
     * @param string        $name 缓存标识
     * @param mixed         $value  存储数据
     * @param int|null      $expire  有效时间 0为永久
     * @return boolean     */
    public static function set($name, $value, $expire = null)
    {
        self::$writeTimes++;       
         return self::init()->set($name, $value, $expire);
    }
登入後複製

看到原来set方法是这样的, 其中writeTimes 是Cache类的静态变量,主要记录缓存的读取次数,这不是重点.

注意到了吗,有个静态变量命名为 $instance, 上次说过这样命名大概率就是 单例模式了.

set方法的重点是init方法

我们再看init方法

  public static function init(array $options = [])
    {        if (is_null(self::$handler)) {            // 自动初始化缓存
            if (!empty($options)) {                
            $connect = self::connect($options);
            } elseif ('complex' == Config::get('cache.type')) {                
            $connect = self::connect(Config::get('cache.default'));
            } else {                
            $connect = self::connect(Config::get('cache'));
            }
            self::$handler = $connect;
        }        return self::$handler;
    }
登入後複製

handler就是操作的句柄(巨饼:-) ), 这里一看,果然是单例模式了,如果句柄为空才去初始化对象,不然直接返回.句柄

同样,这里重点是connect函数, 传入的参数是 配置信息

同样,我们查看connect方法

/**
     * 连接缓存
     * @access public
     * @param array         $options  配置数组
     * @param bool|string   $name 缓存连接标识 true 强制重新连接
     * @return Driver
     */
    public static function connect(array $options = [], $name = false)
    {

        $type = !empty($options['type']) ? $options['type'] : 'File';
        if (false === $name) {
            $name = md5(serialize($options));
        }

        if (true === $name || !isset(self::$instance[$name])) {
            $class = false !== strpos($type, '\\') ? $type : '\\think\\cache\\driver\\' . ucwords($type);
            // 记录初始化信息
            App::$debug && Log::record('[ CACHE ] INIT ' . $type, 'info');
            if (true === $name) {
                return new $class($options);
            } else {
                self::$instance[$name] = new $class($options);
            }
        }

        return self::$instance[$name];
    }
登入後複製

self::$instance[$name] = new $class($options); 这一句里,我们就可以知道句柄的真实身份拉,
$class = false !== strpos($type, '\\') ? $type : '\\think\\cache\\driver\\' . ucwords($type);
这一句的意思是class的名字由type决定, 如果type没有包含反斜线, 则class = \think\cache\driver\.ucwords($type)
thinkPhp 是把think作为核心目录的别名的,所以他真实路径就是 \thinkphp\libray\\think\driver\.ucwords($type)
根据自动加载的尿性,自然是去该文件夹下加载对应的对象
 (额外提一句,这利用的是PHP动态变量的一个特性,其实就和工厂模式一个原理,运行中动态决定实例化的对象)
 type是什么呢? type就是函数传入的参数,也就是配置信息,我们看下配置信息
TP5之Cache的原理及使用type就是驱动方式,如果我们type填写的是File,那么就使用文件驱动,实例化的是 \think\cache\driver\File.class
我们看下 \think\cache\driver文件下有什么文件,那就知道thinkphp为我们提供了多少种缓存驱动了

TP5之Cache的原理及使用

原来有这么多!

点进去

每个文件,我们可以发现一个共同点, 每个类都是继承了 抽象类 Driver

Driver决定了 每一个Cache驱动应该是什么样子的,他们的方法基本是一样的,而实现方式因每个驱动不同而异

其实这就是 适配器模式,如果是我们自己写,当然不会写那么多拉,不过TP5是为了造福广大PHP开发者,所以编写了那么多不同的驱动供我们使用.

我们重点看Redis吧, 如果要去实验,记得把 config中的 Cache.type更改为 redis

Redis类的方法很少,先看看构造函数

public function __construct($options = [])
    {
        if (!extension_loaded('redis')) {
            throw new \BadFunctionCallException('not support: redis');
        }
        if (!empty($options)) {
            $this->options = array_merge($this->options, $options);
        }
        $func          = $this->options['persistent'] ? 'pconnect' : 'connect';
        $this->handler = new \Redis;
        $this->handler->$func($this->options['host'], $this->options['port'], $this->options['timeout']);
        if ('' != $this->options['password']) {
            $this->handler->auth($this->options['password']);
        }
        if (0 != $this->options['select']) {
            $this->handler->select($this->options['select']);
        }
    }
登入後複製

可见TP5的 redis驱动 是基于phpredis的阿, handler 就是实例化的phpredis类, 因此选了哪个驱动,Cache的类自然就是哪些驱动.
所以说如果要使用 TP5的 redis,必须要先安装phpredis扩展.
这里就顺便解析下 redis重写的 set方法

/**
     * 写入缓存
     * @access public
     * @param string    $name 缓存变量名
     * @param mixed     $value  存储数据
     * @param integer   $expire  有效时间(秒)
     * @return boolean
     */
    public function set($name, $value, $expire = null)
    {
        if (is_null($expire)) {
            $expire = $this->options['expire'];
        }
        if ($this->tag && !$this->has($name)) {
            $first = true;
        }
        $key = $this->getCacheKey($name);
        //对数组/对象数据进行缓存处理,保证数据完整性  byron sampson<xiaobo.sun@qq.com>
        $value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
        if (is_int($expire) && $expire) {
            $result = $this->handler->setex($key, $expire, $value);
        } else {
            $result = $this->handler->set($key, $value);
        }
        isset($first) && $this->setTagItem($key);
        return $result;
    }
登入後複製

原本的phpredis set方法 只能是 普通的键值对, 而重写的set方法现在可以是 键,数组啦,这是非常有用的方法

可以看到实现的 原理是把 数组或者对象 序列化为json, 取值的时候则反序列化成为数组.

到这里我们就基本分析完了一个驱动是如何实现的,首先必须 继承Driver类,实现Driver规定的方法,然后将handler交给Cache类去使用

我们回到Cache类

TP5之Cache的原理及使用

可以看到Cache类调用函数的方法基本斗是这样, init()获取 到handler,然后操作handler对象,也就是我们真正的 操作对象,这里就是 phpredis类啦,

当然我们是没办法直接操作 phpredis类的, 只能使用Cache类 的寥寥几种方法,所以有些人不满意,因为队列,集和,哈希都认为没办法使用了,我也在网上看到有些同学 重写TP5的 redis类

其实大可不必, Cache类还是暴露了一个接口给我们的.

我们可以这样

        $res  = Cache::init();        
        $redis = $res->handler();        
        $redis->lpush(&#39;test&#39;,111);        
        $redis->rpush(&#39;test&#39;,111);        
        $redis->lpop(&#39;test&#39;);
登入後複製

获得了 handler 也就是获得了 phpredis,这样就可以随便使用 phpredis原生的方法啦,而且还是单例模式哦, 没有新建对象额外的消耗

本文就到这里结束啦, 如果要知道更多Cache类的使用方法,可以按上文的方式直接看源代码,或者再去查阅官方文档.

虽然没有讲解如何使用,但是分析了 Cache的实现原理有助于提高我们的编程抽象水平, 上文分析源码的方式也同样可以用来分析其他的核心类库.

相关阅读:

ThinkPHP5商城项目实战视频教程课件源码分享

thinkphp5入门该了解的知识

thinkphp5.0学习笔记之数据库的操作

以上是TP5之Cache的原理及使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

CakePHP 日期和時間 CakePHP 日期和時間 Sep 10, 2024 pm 05:27 PM

為了在 cakephp4 中處理日期和時間,我們將使用可用的 FrozenTime 類別。

討論 CakePHP 討論 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的開源框架。它旨在使應用程式的開發、部署和維護變得更加容易。 CakePHP 基於類似 MVC 的架構,功能強大且易於掌握。模型、視圖和控制器 gu

CakePHP 檔案上傳 CakePHP 檔案上傳 Sep 10, 2024 pm 05:27 PM

為了進行文件上傳,我們將使用表單助理。這是文件上傳的範例。

CakePHP 建立驗證器 CakePHP 建立驗證器 Sep 10, 2024 pm 05:26 PM

可以透過在控制器中新增以下兩行來建立驗證器。

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

CakePHP 快速指南 CakePHP 快速指南 Sep 10, 2024 pm 05:27 PM

CakePHP 是一個開源MVC 框架。它使應用程式的開發、部署和維護變得更加容易。 CakePHP 有許多函式庫可以減少大多數常見任務的過載。

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

See all articles