Laravel 中缓存驱动的速度比较

Laravel 中缓存驱动的速度比较

缓存是web开发中重要的一部分,我相信很多人和我一样,经常忽略这个问题。 随着工作经验的累积,我已经意识到缓存是多么的重要,这里我通过 Scotch 来解释一下它的重要性。

通过观察发现,Scotch每天按照计划发布文章,然而,上一次发布文章的24小时内,新的文章不会被放出,因此,登陆页面上的数据将保持24小时不变。 换句话说,在24小时内( 更准确的说是22-23个小时)向数据库请求文章数据是没有意义的。

缓存可以很好的解决这个问题,当遇到一个页面请求时,我们可以把结果缓存22个小时,只要在这个时间内通过控制器请求的数据,都是缓存中的数据,直到缓存超时。

下面我们来看看Laravel 中缓存的基本用法,然后看一个简单的例子,试试缓存到底能带来多大的加速。

在 Laravel 中缓存的基本用法

Laravel 使得我们可以轻松地转换出我们想要生成缓存的方式。我们很容易修改缓存驱动方式。只需到 config / cache.php 来查看可用的驱动程序:


  • apc
  • array
  • database
  • file
  • memcached
  • redis

你可以在 .env 文件中修改缓存驱动:

CACHE_DRIVER=file
你可以继续尝试修改它们而不用担心配置,因为它默认驱动是 file

Cache facade 暴露了很多静态方法来创建,更新,获取,删除和检查缓存内容的存在。让我们在构建演示应用程序之前先了解一下这些方法。

建立/更新缓存值

我们使用 put() 方法来新增或更新缓存值。该方法必须使用 3 个参数:


  • 键名
  • 键值
  • 过期时间 单位分钟

例如:

Cache::put('key', 'value', 10);

键名 是缓存的唯一标识,需要时要用它来获取值。

此外,我们也可以用 remember() 方法自动获取和更新一个缓存值。该方法首先检查 键名 是否存在,如果已经创建则返回结果。否则它会创建新的 键名 ,并用闭包返回结果进行赋值,就象下面:

Cache::remember('articles', 15, function() {
    return Article::all();
});

参数 15 是要缓存的分钟数。这样的话,我们甚至根本不必检查缓存是否过期。Laravel 不仅会替我们打理,而且会获取或重新生成该缓存,不需要我们显式地告诉它如何操作。

检索缓存值

缓存的值可以通过 get() 方法去获取,这个方法接受一个参数 key

Cache::get('key');

检查是否已存在key

有时候在更新或者取回缓存值之前判断这个缓存的key是否存在是很有必要的,使用 has() 方法就可以实现:

if (Cache::has('key')){
    Cache::get('key');
} else {
    Cache::put('key', $values, 10);
}

删除缓存值

删除缓存值可以用 forget() 方法并把需要删除的 key 作为参数传进去:

Cache::forget('key');

我们也可以检索缓存值并删除它。我喜欢把这个称为一次性缓存:

$articles = Cache::pull('key');

我们还可以使用以下命令在缓存过期前就把所有缓存清楚掉:

php artisan cache:clear

一个例子

这是一个简单的演示,主要是为了说明是否使用缓存对请求响应所需要时间的影响,为了让你能更直接的了解,我建议你跟着教程自己来 构建 一个 Laravel 例子。

模型和表迁移

使用下面命令新建一个 Article 模型:

php artisan make:model Article -m

-m 参数会自动创建一个 migration ,所以无需再使用 create migration 命令了,这个命令会创建 App/Article.phpdatabase/migrations/xxxx_xx_xx_xxxxxx_create_articles_table.php 文件。

修改你的 migration 文件并添加以下两行:

public function up() {
    Schema::create('articles', function (Blueprint $table) {
        $table->increments('id');

        // add the following
        $table->string("title");
        $table->string("content");

        $table->timestamps();
    });
}

然后我们就可以用以下命令迁移我们的数据库了:

php artisan migrate

填充数据库

接下来我们需要填充文章的数据库表,在 database/seeds/DatabaseSeeder.php 中,修改 run() 如下所示:

public function run() {
    Model::unguard();

    // use the faker library to mock some data
    $faker = Faker::create();

    // create 30 articles
    foreach(range(1, 30) as $index) {
        Article::create([
            'title' => $faker->sentence(5),
            'content' => $faker->paragraph(6)
        ]);
    }

    Model::reguard();
}

Laravel中包含 Faker 库用以快速生成假数据,我们可以使用PHP的 range() 方法去生成30条假数据。

接下来我们就可以通过这条 artisan 命令去填充数据库了:

php artisan db:seed

创建文章控制器

接下来,我们可以创建一个处理请求和缓存的控制器,首先它是空的:

php artisan make:controller ArticlesController

...然后我们增加一个路由 app/Http/routes.php 指向这个文章控制器的 index 方法:

Route::group(['prefix' => 'api'], function() {

    Route::get('articles', 'ArticlesController@index');

});

现在我们的数据库都是用样本数据建立起来的,我们可以进行测试了。

未使用缓存的响应

让我们看看我们传统的控制器方法是什么样的,没有缓存,处理响应需要多长时间,在 index() 方法中,返回文章的资源数据:

public function index() {
    $articles = Articles::all();
    return response()->json($articles);
}

你也可以使用 Postman 去请求(localhost/api/articles) 或者直接用浏览器打开,你就可以看到如下所示。



请注意在本地开发服务器上完成此请求所花费的时间。

从缓存中返回的响应

现在让我们尝试使用缓存,看看数据响应所花费的时间是否会有显着差异。修改 index()方法为:

public function index() {
    $articles = Cache::remember('articles', 22*60, function() {
        return Article::all();
    });
    return response()->json($articles);
}

现在我们使用 remember() 方法缓存了文章,缓存时间为 22 小时,再次运行并观察所花费的时间,可以看我的截图:



结果和建议

在我的标准开发环境中测试得出,使用缓存时产生响应所需的时间比没有使用的时候要少:

是不是很酷呢?这里有两点需要注意:


  1. 即使使用了缓存,第一次请求响应还是需要比较多的时间,因为当第一次请求的时候缓存里面还是空的。
  2. 与 file 驱动相比,Memcached 和 Redis 的速度更快,所以建议在项目较大时使用外部缓存驱动。

结论

使用文件、数据库作为驱动,两者在速度上没有很明显的区别。但是如果我们使用第三方服务作为驱动, 可以很明显地看到性能提升。所以投资高速缓存是值得的。

更多现代化 PHP 知识,请加入 PHP / Laravel 知识社区 一起学习成长吧。
编辑于 2018-03-29

文章被以下专栏收录