
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、ウェブサイト開発でページ表示の速度を向上させるためによく「キャッシュ」を利用することがあります。
キャッシュとは、時間がかかる計算結果を一時的に保管しておいて、一定時間は重たい処理を省略するテクニックですが、Laravelではこの「キャッシュ」がとても簡単に利用できるようなっています。(キャッシュのもっと詳しい説明はこちら)
ただし、Laravelには多くのキャッシュ機能があるため、少し頭が複雑に感じることもあったりするのも事実です。
そこで、今回はキャッシュ機能についてまとめた「大全」的な記事を公開することにしました。
ぜひ開発の参考にしてください。
※ 実行環境は、Laravel 5.7です。
目次 [非表示]
- 1 お急ぎの人向け(キャッシュの保存&取得)
- 2 キャッシュを保存したい
- 3 キャッシュを呼び出したい
- 4 キャッシュを削除したい
- 5 自動更新(作成)するキャッシュをつくりたい
- 6 キャッシュが存在するかチェックしたい
- 7 キャッシュ方法を切り替えたい
- 8 数字をどんどん増やしたい/減らしたい
- 9 キャッシュにタグを使いたい
- 10 様々なキャッシュ方式を使いたい
- 11 キャッシュ・イベントを使いたい
- 12 キャッシュを一時的にロックしたい
- 13 独自のキャッシュ・ドライバーを使いたい
- 14 そもそもキャッシュとは??
- 15 キャッシュの上書きについて
- 16 キャッシュが保存できるデータ(型)は?
- 17 キャッシュが保存される場所は??
- 18 array方式のキャッシュについて
- 19 実際、どのキャッシュ方式が高速ですか??
- 20 cache()ヘルパー関数はどのように使えますか??
- 21 よくあるエラー
お急ぎの人向け(キャッシュの保存&取得)
Laravelでシンプルにキャッシュを扱いたい場合はヘルパー関数cache()
を使うと便利です。
// 10分間、キャッシュ保存
cache(['key' => '保存データ'], 10);
// 取得
$cache = cache('key');
キャッシュを保存したい
有効時間(分)を指定して保存
例えば、1時間(=60分間)有効なキャッシュを作成する場合です。
$minutes = 10; // 有効期間(分)
\Cache::put('key', '保存データ', $minutes);
※ ちなみに、$minutes
の数を0
にするとキャッシュは保存されません。(以前は有効期限がないキャッシュとして保存されていました)
【注意】
ビジターさんからの指摘で気づきましたが、Laravel 5.8からは「分」ではなく「秒」での指定に変更になっています。(本家の説明はこちら)サンプルは以下のとおりです。
$seconds = 600; // 有効期間(秒)。10分。
\Cache::put('key', '保存データ', $seconds);
これって結構大きな変更ですよね^^;
わざわざ連絡をくださってありがとうございます!
有効時間(秒)を指定して保存
Laravel 5.8からは「分」ではなく「秒」でキャッシュの時間を指定するよう変更になりました。詳しくは有効時間(分)を指定して保存をご覧ください。
有効期限(日時)を指定して保存
例えば、今から15分後まで有効なキャッシュを作成する場合です。
$dt = now()->addMinutes(15); // 15分後
\Cache::put('key', '保存データ', $dt);
有効期限がないキャッシュを保存
\Cache::forever('key', '保存データ');
もしキャッシュがないなら保存したい
キャッシュがなければ、保存をしたい場合はadd()
を使います。
$minutes = 10;
\Cache::add('key', '新しいデータ', $minutes);
※ もしすでにkey
という名前のキャッシュがある場合は何も起こりません。
※ 有効期限が切れている場合は、新しいキャッシュが作成されます。
なお、add()
は「キャッシュが作成された?」が分かるように、true
/false
が返してくれます。そのため、以下のようにするとコードの切り替えも可能です。
$minutes = 10;
$result = \Cache::add('key', '新しいデータ', $minutes);
if($result) {
echo '新しいキャッシュを作りました。';
}
キャッシュを呼び出したい
すでに保存されているキャッシュからデータを呼び出すにはget()
を使います。
基本形
$cache = \Cache::get('key');
デフォルト値を指定して取得
有効期限があるキャッシュは時間が来ると削除されてしまうため、データがいつでも取得できるわけではありません。そのため、キャッシュが存在しない場合に使う「代わりのデータ」をあらかじめ指定しておくことができます。
$cache = \Cache::get('key', '代わりのデータ');
※ もしkey
というキャッシュがなければ$cache
は「代わりのデータ」になります。
functionを使ったデフォルト値を指定して取得
例えば、日曜日だけキャッシュのデフォルト値を切り替えたい場合はfunction
を使うと便利です。
$cache = \Cache::get('key', function(){
if(today()->isSunday()) {
return '日曜のデフォルト値';
}
return 'その他のデフォルト値';
});
キャッシュを呼び出して、すぐ削除したい
キャッシュのデータを取得し、すぐそのキャッシュを消したい場合は、pull()
を使います。
$cache = \Cache::pull('key'); // キャッシュは削除されます
なお、以下のようにデフォルト値を指定することもできます。
$cache = \Cache::pull('key', 'デフォルト値');
キャッシュを削除したい
特定のキャッシュを削除したい
\Cache::forget('key'); // 「key」のキャッシュだけ削除
全てのキャッシュを削除したい
\Cache::flush(); // 全キャッシュを削除
自動更新(作成)するキャッシュをつくりたい
put()
やadd()
を使えば、気軽に変数内のデータをキャッシュ化することができますが、毎回has()
メソッドでキャッシュの存在チェックして、もしなければキャッシュを作成するというコードを書くのはめんどうだったりします。
その場合に使えるのがremember()
です。
以下の例は10分ごとにキャッシュを更新する(つまり、10分間はキャッシュが有効になる)例です。
$minutes = 10;
$cache = \Cache::remember('key', $minutes, function(){
return now()->toDateTimeString(); // 10分ごとに自動更新
});
また、有効時間を決めない場合は、rememberForever()
を使いますが、こちらはキャッシュが手動で消されるまで更新されることはありません。
$cache = \Cache::rememberForever('key', function(){
return now()->toDateTimeString();
});
キャッシュが存在するかチェックしたい
例えば、key
という名前のキャッシュがあるか(有効期限がきれていないか)をチェックする場合です。
if(\Cache::has('key')) {
echo 'キャッシュが見つかりました。';
}
キャッシュ方法を切り替えたい
Laravelでは、ファイル方式のキャッシュだけではなく以下のような方式でキャッシュを管理することができます。
- apc
- array ※array方式のキャッシュについて
- database
- file(デフォルト)
- memcached
- redis
そして、動的にこのキャッシュ方式を変更したい場合はstore()
を使います。以下はapc
方式でキャッシュを保存する方法です。
\Cache::store('apc')->put('key', '保存データ', 10);
ちなみに、デフォルトのキャッシュ方式を変更したい場合は.env
内のCACHE_DRIVER
で設定してください。(実際にはこの設定が/config/cache.php
の中で反映されるようになっています)
数字をどんどん増やしたい/減らしたい
数字をどんどん増やしたい
例えば、表示回数をカウントしてキャッシュに保存しておきたい場合です。
\Cache::increment('key');
echo \Cache::get('key'); // 1からどんどん増えていく
もし増やす数字を変えたい場合は第2引数で指定します。
\Cache::increment('key', 100); // 100ずつ増える
数字をどんどん減らしたい
逆に数字をどんどん減らしていきたい場合は、decrement()
を使います。
\Cache::decrement('key'); // 1ずつ減る
もちろん、第2引数は減らす数値を指定できます。
\Cache::decrement('key', 100); // 100ずつ減る
もともと違う型のデータが入っていたら??
一旦キャッシュの中身がゼロ(数値)になり、そこからincrement()
もしくはdecrement()
されます。
\Cache::put('key', 'データ', 10); // テキストデータ
\Cache::increment('key');
echo \Cache::get('key'); // 「1」になります。
キャッシュにタグを使いたい
注意: キャッシュ・タグを使う場合はキャッシュ方式が以下のものでないといけません。
- apc
- array
- memcached
- redis
そのため、今回は.env
で以下のようにapc
を使うよう変更して実行しました。
CACHE_DRIVER=apc
タグをつけてキャッシュを保存する
例えば、コカ・コーラに「炭酸飲料」と「黒」というタグをつけて保存する場合です。
\Cache::tags(['炭酸飲料', '黒'])->put('coke', 'コカ・コーラ', $minutes);
タグを指定してキャッシュを取得する
同じようにタグを指定してget()
するだけでOKです。
$cache = \Cache::tags(['炭酸飲料', '黒'])->get('coke'); // コカ・コーラ
ただし、取得の際に気をつけないといけないのが、tags()には保存時と同じ内容で、しかも同じ並びでないといけないということです。
つまり、以下の例ではキャッシュ・データを取得することはできません。
\Cache::tags(['炭酸飲料', '黒'])->put('coke', 'コカ・コーラ', 10);
// 全て取得できません
echo \Cache::tags(['炭酸飲料'])->get('coke');
echo \Cache::tags(['黒'])->get('coke');
echo \Cache::tags(['黒', '炭酸飲料'])->get('coke');
個人的にはタグというからには、ひとつでも該当するものがあればデータ取得してほしいのですが、現在の使用ではそのようにはなっていません。
また、タグ付きで保存したデータはタグ付きでしかデータ取得できません。つまり、以下の例ではデータは取得できません。
\Cache::tags(['炭酸飲料', '黒'])->put('coke', 'コカ・コーラ', 10);
echo \Cache::get('coke'); // タグなしなので、取得できない!
タグ付きのキャッシュを削除
タグが付けられたキャッシュを削除するにはflush()
を使います。
\Cache::tags(['炭酸飲料', '黒'])->flush();
ここで注意が必要なのが、以下のような例です。
\Cache::tags(['炭酸飲料', '黒'])->put('coke', 'コカ・コーラ', 10);
\Cache::tags(['炭酸飲料', '透明'])->put('cider', '三ツ矢サイダー', 10);
\Cache::tags(['エナジードリンク', '黄色'])->put('red-bull', 'レッドブル', 10);
\Cache::tags(['炭酸飲料'])->flush();
echo \Cache::tags(['炭酸飲料', '黒'])->get('coke'); // 取得できない!
echo \Cache::tags(['炭酸飲料', '透明'])->get('cider'); // 取得できない!
echo \Cache::tags(['エナジードリンク', '黄色'])->get('red-bull'); // 取得できる
この場合、flush()
で「炭酸飲料」というタグが付いているキャッシュ自体が削除されてしまうので、「コカ・コーラ」と「三ツ矢サイダー」のキャッシュ・データを取得することはできません。
様々なキャッシュ方式を使いたい
データベースを使ったキャッシュを使いたい
まず以下のコマンドでマイグレーションを作成します。
php artisan make:migration create_cache_table
すると、/database/migrations
フォルダ内に、****_**_**_******_create_cache_table.php
というファイルが作成されるのでこれを開いて以下のように変更します。(変更する場所は太字のところ)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCacheTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('cache');
}
}
そして、以下のコマンドでデータベースを作成します。
php artisan migrate
このコマンドを実行するとデータベース内に以下のようなテーブルが作成されます。
後は、.env
のCACHE_DRIVER
を以下のようにdatabase
へ変更すれば準備は完了。
CACHE_DRIVER=database
※ 実際にキャッシュをDBへ保存した場合は以下のようになります。
ちなみに、より詳しいデータベース・キャッシュの設定をしたい場合は/config/cache.php
の中で変更ができます。
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
],
apcでキャッシュを使いたい
apc
キャッシュを使うには、PHPにapc(u)をインストールする必要があります。(実行環境: Ubuntu 18.04)
sudo apt install php-apcu
インストールが完了したら、ウェブサーバー(apache, nginxなど)を再起動してphpinfo()
を確認してみましょう。以下のようになっていれば成功です。
後は、.env
のCACHE_DRIVER
を以下のようにapc
へ変更すれば完了です。
CACHE_DRIVER=apc
memcachedでキャッシュを使いたい
Laravelでmemcached
を使う場合は、PECLのmemcachedが必要なので以下のコマンドでインストールします。(実行環境はUbuntu 18.04)
sudo pecl install memcached
もし、error: memcached support requires libmemcached
というようなエラーが出た場合は、パッケージが足りていないので、以下のようなコマンドでインストールしてください。
sudo apt install libmemcached-dev libmemcached
PELCでmemcachedのインストールが完了したら、php.iniに以下のようなラインを追加してウェブサーバー(apacheやnginx)を再起動します。
extension=memcached.so
phpinfo()
でmemcached
が表示されていればインストールは成功です。
そして、memcached
本体もインストールします。
sudo apt install memcached
では、以下のコマンドでmemcached
を起動します。
sudo systemctl start memcached
後は、.env
のCACHE_DRIVER
を以下のようにmemcached
へ変更すれば完了。
CACHE_DRIVER=memcached
memcached
の設定は/config/cache.php
内で変更できます。
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
redisでキャッシュを使いたい
redis
が使えるようにパッケージをインストールします。(実行環境: Ubuntu 18.04)
まずはredis
本体をインストールして起動しておきます。
sudo apt install redis-server
sudo systemctl start redis-server
次にPHPのredis
パッケージをインストールです。
sudo apt install php-redis
インストールが完了したら、ウェブサーバー(apache, nginxなど)を再起動してphpinfo()
を確認してみましょう。以下のようになっていれば成功です。
さらに、Laravelでredis
を使う場合はpredis/predis
というパッケージが必要なので、これもcomposer
でインストールしましょう。
composer require predis/predis
※ ちなみに、このパッケージのインストールを忘れるとClass 'Predis\Client' not found
というエラーが発生します。
後は、.env
のCACHE_DRIVER
を以下のようにredis
へ変更すれば完了です。
CACHE_DRIVER=redis
もし詳しい設定をしたい場合は、/config/cache.php
内で変更できます。
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
],
キャッシュ・イベントを使いたい
Laravelで使えるキャッシュ関連のイベントは以下の4つです。
- LogCacheHit ・・・ キャッシュ・データが取得された時
- CacheMissed ・・・ キャッシュが見つからなかった時
- LogKeyForgotten ・・・ キャッシュが削除された時
- LogKeyWritten ・・・ キャッシュが書き込まれた時
ただし、デフォルトではイベント・リスナーはありませんので自分で作る必要があります。
以下のコマンドで各イベントに対応するイベント・リスナーを作成します。
php artisan make:listener LogCacheHit
php artisan make:listener LogCacheMissed
php artisan make:listener LogKeyForgotten
php artisan make:listener LogKeyWritten
そして、各リスナーの中ではhandle()
メソッド内で該当するキャッシュ・データを取得できますので、ここで様々な処理をすることになります。
public function handle($event)
{
$cache_key = $event->key; // キャッシュのキー
$cache_value = $event->value; // キャッシュのデータ
$cache_tags = $event->tags; // タグ(配列)
$cache_minutes = $event->minutes; // 有効時間
}
※ ただし、LogCacheMissed
とLogKeyForgotten
にはvalue
はありません。また、minutes
にアクセスできるのはLogKeyWritten
のみです。
後は、作成したイベント・リスナーを/app/Providers/EventServiceProvider.php
で登録すればイベントが実行されるようになります。
protected $listen = [
'Illuminate\Cache\Events\CacheHit' => [
\App\Listeners\LogCacheHit::class,
],
'Illuminate\Cache\Events\CacheMissed' => [
\App\Listeners\LogCacheMissed::class,
],
'Illuminate\Cache\Events\KeyForgotten' => [
\App\Listeners\LogKeyForgotten::class,
],
'Illuminate\Cache\Events\KeyWritten' => [
\App\Listeners\LogKeyWritten::class,
],
];
キャッシュを一時的にロックしたい
Laravelでは、負荷が集中しない目的などのために、キャッシュを一時的に使えないようロックすることができます。
※ 注意: キャッシュ・ロックはmemcached
とredis
方式のみ有効です。
まずは、基本的な使い方です。
$lock = \Cache::lock('redis', 10)->get();
if($lock) {
echo '10秒間ロックを開始しました!';
}
また、もう一つはfunction
を使う方法です。以下のようにすることで、function
の処理が終了するとロックが解除されます。
\Cache::lock('redis', 10)->get(function(){
sleep(5); // これが終わるとロック解除
});
さらに、get()
ではなくblock()
を使うと指定した時間ロックの解除を待たせることができます。
dd(\Cache::lock('redis', 10)->block(7));
この例では、10秒間のロックを実行し、最大7秒間解除されるのを待つコードです。
つまり、コードを実行して3秒を超えてからリロードすると7秒間の待機中にロックが解除されるので、処理は問題なく実行できますが、3秒以内にリロードすると待機する秒数が足りないため、LockTimeoutException
の例外が発生します。
そのため、try〜cacth()
などで例外処理するといいでしょう。
※なお、2018/10/02現在、LaravelのドキュメントではblockFor()を使うよう書かれていますが、Illuminate\Cache\Lock
のソースコードを見る限りblock()
となっています。
独自のキャッシュ・ドライバーを使いたい
Laravelには始めから様々なキャッシュが利用できるようになっていますが、もしかすると全く異なったキャッシュ方式を使いたい場合があるかもしれません。そんな場合には独自のキャッシュ・ドライバーを自分で定義することができます。
今回はテストとして、JSONファイルにデータを保存する簡易的なキャッシュ・ドライバーjson
を実装してみます。ただし、実装テストなので作成するメソッドはget()
、put()
、forget()
、flush()
の4つで、有効期限の機能は省略します。
まず、データを保存するJSONファイルを/storage/app/json/cache.json
に作成し、権限を変えて書き込みできるようにしておきます。
そして、/config/cache.php
にjson
ドライバーを追加し、さらに.env
のキャッシュ・ドライバーを同じくjson
へ変更します。
'json' => [
'driver' => 'json'
]
CACHE_DRIVER=json
さらに、\app\Extensions\JsonStore.php
を作成し、その中へ以下のようなコードを追加します。
<?php
namespace App\Extensions;
use Illuminate\Contracts\Cache\Store;
class JsonStore implements Store
{
private $_json_path = '';
private $_json_data = [];
public function __construct()
{
$this->_json_path = storage_path('app/json/cache.json');
$this->_json_data = [];
if(file_exists($this->_json_path)) {
$this->_json_data = json_decode(
file_get_contents($this->_json_path),
true
);
}
}
public function get($key) {
return array_get($this->_json_data, $key);
}
public function put($key, $value, $minutes) {
$this->_json_data[$key] = $value;
$this->saveJson();
}
public function forget($key) {
if(array_has($this->_json_data, $key)) {
unset($this->_json_data[$key]);
$this->saveJson();
}
}
public function flush() {
$this->_json_data = [];
$this->saveJson();
}
private function saveJson() {
file_put_contents($this->_json_path, json_encode($this->_json_data));
}
// その他(省略できません)
public function many(array $keys) {}
public function putMany(array $values, $minutes) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function getPrefix() {}
}
※ やっていることは、単純にJSONからデータの読み書きができるようにしているだけです。
では最後に、このJsonStore
をAppServiceProvider
のboot()
内で登録して使えるようにしましょう。
public function boot()
{
\Cache::extend('json', function ($app) {
return \Cache::repository(
new \App\Extensions\JsonStore()
);
});
}
以上で、独自ドライバーが定義されました。キャッシュの保存、取得、削除は今までと同じですので、ぜひトライしてみてください。
そもそもキャッシュとは??
例えば、Amazonのような物販サイトでアクセサリー部門のランキング結果を作る場合を考えてみましょう。
手順は以下のようなものになります。
- ある一定期間の全ての注文データを取得
- その注文データを売れた個数などで集計
- 商品の並べ替えをして、ランキングが完成
ここで特に問題となるのが2番の集計をする部分です。データ数が少ないなら、集計にそれほど時間はかかりませんが、Amazonのような巨大サイトではコンピュータの負荷が莫大なものになってしまい、アクセスがある度にランキング計算するわけにはいきません。
キャッシュは、これを解決するための技術になります。
つまり、今回の例で言うと、
- 計算に時間がかかるランキング結果をすぐ読み込める一時ファイルに保存
- キャッシュが存在していればランキング計算はせず、保存した結果を使用
- 一定時間を超えたらこの一時ファイルを削除
- また計算をして新しいキャッシュを作成
という手順をとることで、時間がかかる計算をショートカットできるわけです。
そして、キャッシュを作成するのは大量データの計算部分だけではなく、先ほどの1番で見た「ある一定期間の注文データを取得」の部分でも利用されることがあります。
例えば、いつも同じ内容を取得するのに毎回データベースへアクセスするのは負荷がかかります。そのため、この「データ取得」部分にキャッシュを作っておけば高速化が期待できるというわけです。
このように、キャッシュをうまく利用するとページ表示は劇的に早くなり、さらにサーバーへの負荷も少なくなるので一石二鳥のテクニックと言えるでしょう。
アクセスが多いサイトはぜひキャッシュを活用したいですね!
キャッシュの上書きについて
まだ有効時間内のキャッシュがある場合に、put()
などで新しいキャッシュを保存する場合は、有効時間を含めた全てのデータが上書きされます。
キャッシュが保存できるデータ(型)は?
Laravelでキャッシュに保存できるデータは、以下のように様々な型に対応しています。
文字列
\Cache::forever('key', 'テキスト');
数値
\Cache::forever('key', 1);
配列
\Cache::forever('key', ['赤', '青', '黄色']);
オブジェクト
\Cache::forever('key', [
'red' => '赤',
'blue' => '青',
'yellow' => '黄色'
]);
インスタンス
\Cache::forever('key', new Carbon());
キャッシュが保存される場所は??
file
方式(初期状態)の場合、/storage/framework/cache/data
フォルダ以下にファイルが作成されます。もし有効時間つきでテキストデータを保存した場合は以下のような内容になります。
1538293956s:12:"テキスト";
array方式のキャッシュについて
/config/cache.php
の中にはarray
という方式のキャッシュを選択できるようになっています。
Laravelの公式サイトでは、array
方式のキャッシュに関する詳しい説明を見つけることはできませんでしたが、Illuminate\Cache\ArrayStore
のソースコードを見る限り、この方式は実際にはどこかにデータ保存せず、単にデータを配列に格納しているだけのようです。つまり、ページ表示単位でデータはその都度消えてしまうことになります。
public function put($key, $value, $minutes)
{
$this->storage[$key] = $value;
}
※ 実際に一旦保存したキャッシュをリロードしても、キャッシュ・データを取得することはできませんでした。
実際、どのキャッシュ方式が高速ですか??
キャッシュ方式を切り替えたいでも書いたとおり、Laravelでは現在のところ以下6つのキャッシュ方式を利用することができます。
- apc
- array ※array方式のキャッシュについて
- database
- file
- memcached
- redis
ただ、高速化を目的とした場合は一体どのキャッシュを選択するべきかを検討してみましょう。
検証方法
Laravel 5.6の高速化検証・artisanコマンド3つのキャッシュでも利用したループを使った方法で、100万回キャッシュの読み込み/書き込みをさせ、より少ない時間で完了できたものがもっとも高速なキャッシュ方式とします。
<?php
$start = microtime(true);
for($i = 0 ; $i < 100000 ; $i++) {
// キャッシュの書き込みや読み込み
}
$time = microtime(true) - $start;
echo $time .'秒';
では、まずは読み込みの実行結果から見ていきましょう。
もっとも読み込みが早いキャッシュ方式は??
実行するコードは以下になります。
$start = microtime(true);
$cache = \Cache::store('CACHE-TYPE'); // キャッシュ方式を指定
$cache->put('key', '保存データ');
for($i = 0 ; $i < 100000 ; $i++) {
echo $cache->get('key');
}
$time = microtime(true) - $start;
echo $time .'秒';
まず始めにキャッシュ方式を切り替えてデータを保存、そして100万回呼び出してみます。
では、結果です。
- array ・・・ 0.14071893692017秒
- apc(PHP 7.2) ・・・ 0.17040491104126秒
- file(SSD環境) ・・・ 1.6274020671844秒
- memcached ・・・ 3.2162840366364秒
- redis ・・・ 4.5471999645233秒
- database(MySQL 5.7) ・・・ 29.163866996765秒
やはり、単純に配列を利用しているだけのarray
方式が早かったです。ただ、予想とは違ってapc
がとても早く実行できたので驚きました。なお、期待していたmemcached
やredis
はfile
方式と比べても、それほど高速化するわけではなく、DBに至っては「・・・」という結果になりました。
もっとも書き込みが早いキャッシュ方式は??
コードはこちらです。
$start = microtime(true);
$cache = \Cache::store('CACHE-TYPE'); // キャッシュ方式を指定
for($i = 0 ; $i < 100000 ; $i++) {
$cache->put('key', '保存データ');
}
$time = microtime(true) - $start;
echo $time .'秒';
では結果です。
- redis ・・・ 0.016289949417114秒
- apc(PHP 7.2) ・・・ 0.016727209091187秒
- database(MySQL 5.7) ・・・ 0.016852140426636秒
- memcached ・・・ 0.016862869262695秒
- file(SSD環境) ・・・ 0.017729043960571秒
- array ・・・ 0.017874002456665秒
書き込みに関しては、ほぼ全てが横並びという結果になりました。その差はわずかなので、リロードしてみると順位が変わってしまう場合もあるでしょう。
結論
読み込み/書き込みどちらの検証でも上位をキープしているため、今回の結果だけみるとapc
方式が高速化には有利という結果になりました。(ただし、もちろん環境によって変化があるでしょう)
cache()ヘルパー関数はどのように使えますか??
今回の記事では\Cache::get()
のようにFacadeを使った記述をしていますが、以下のようにcache()
を使って置き換えることも可能です。
cache()->put('key', 'データ', 10); // 保存
if(cache()->has('key')) { // 存在チェック
echo cache()->get('key'); // 取得
}
よくあるエラー
Laravelのキャッシュ関連で一番よく表示されるエラーは以下のものではないでしょうか。
file_put_contents(/***/storage/framework/cache/data/*****): failed to open stream: Permission denied
この場合、フォルダ(もしくは)ファイルへの書き込み権限がないことが原因なので、以下のようなコマンドでstorage
以下全てのファイルに実行権限を与えてください。
sudo chmod -R 777 storage
以上です。