July 16, 2021 • ☕️☕️☕️ 15 min read
【 環境 】
Laravel のバージョン: 8.16.1
PHP のバージョン: 7.4.7
MySQL のバージョン: 5.7
Laravel で Redis を使う時、PHP のライブラリに以下の2つの候補が出てくる。
デフォルトだと、composer.lock に「predis」が記述されている。
"packages": [
{
"require-dev": {
"predis/predis": "^1.1.2",
"symfony/cache": "^5.1.4"
},
しかし、config\database.php には「phpredis」が記述されている。
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
何なんだこの中途半端な状態は。
と思って調べたら、predis はデフォルトから外される予定だったけど、やっぱ外すのやめたーって事になり、とはいっても phpredis を推奨したいし・・・
といった感じで、どっちつかずの状態になっているみたい。
どちらを使えばいいのかについては議論が活発なようで、こんなのがありました。
PHP向けRedisクライアントのpredisを使うのは止めた方がいいです
predisはPHP向けのRedisクライアントです。
リポジトリを見て察しのいい方は気づいたと思うのですが、2年ぐらいメンテ(コミットすら)されていません。
すでにPHP7.3周りで問題が出てます。これが「どういった事情でメンテされていないのか?」「されないのではなく、できないのか?」などは誰もわからないと思いますし、もしかしたら将来的に再度メンテされる可能性はありえます。
(今はどうなのか気になって調べてみたところ、2021年7月現在は、無事開発は再開されているようです。)
Laravelのドキュメントにも書いてありますが、phpredis使えばいいと思います。
こちらはcomposerでインストールできない(PHP拡張モジュールなので)のでpeclでインストールします。
いやああああ!!!
マジなの? 令和にもなって、PHPライブラリを composer でインストールできないとか正気なの??
さすがに今では改善されているんじゃ・・・と思って公式サイトの PhpRedis 公式のインストールガイドを見てみた。
が、pecl を使えという夢も希望も無いメッセージが。
https://github.com/phpredis/phpredis/blob/develop/INSTALL.markdown
こんなのもあった。
How to install phpredis using composer?
I need to install phpredis using composer on windows server running IIS. What is the package name for this?
You cannot. Composer is for pure-PHP library not for C extension (pickle will do it later)
You need to compile it! See more information here:
どうやら composer でインストールするのは絶望的で、今後もできるようになる可能性は限りなくゼロに近そう。
念のため、他の記事も参考にしてみた。
Laravel 8のRedisクライアントのパフォーマンスの比較
性能比較をして、PhpRedis の方が上だった模様。
上記のコマンドをそれぞれ50回実行し、平均(±標準偏差)を算出しました。
- PhpRedis … 1.317 ± 0.03 (秒)
- Predis … 1.509 ± 0.026 (秒)
Predisを使用した場合の処理時間はPhpRedisの場合の約1割増しと、明らかに差がでました
Laravel 8 でPhpRedisとPredisを比較しました。PhpRedisの方が普通に速いので、導入できる環境であれば、Laravelの推奨に従ってPhpRedisで良さそうです。
でも composer で管理できないのは嫌だ。
PhpRedis vs Predis: Comparison on real production data
PhpRedis is faster about x6 times. Using igbinary serializer reduces stored data size about 3x times.
If Redis installed on separate machines, reducing network traffic is a very significant speedup.
ここでも PhpRedis を絶賛。
以下、Laravel公式の見解。
Redis 8.x Laravel
LaravelでRedisを使い始める前に、PECLにより phpredis HP拡張機能をインストールして使用することを推奨します。
これはもう phpredis で確定か。
そうなると、docker コンテナを弄らないといけない・・・
今使っているコンテナ、Alpine なんだよな。。
Alpine は、軽量な Linux ディストリビューション。
Docker コンテナのイメージのベースに使われる事も多くなってきた。
ちなみに当方、Alpine は、あまり積極的に採用したくない派です。
理由は以下。
Dockerイメージのベースディストリは、Alpine がいい感じなの?
ざっくり言うと、Alpine の嫌な所、こんな感じ。
何てこった! 自分がこんなに Alpine に悪い印象持ってたなんて!
ちなみに Alpine に否定的な意見を持ってるのは、自分だけじゃないぞ。(道連れ)
軽量Dockerイメージに安易にAlpineを使うのはやめたほうがいいという話
とはいえ、文句たれてても仕方ないんで、試しにインストールしてみよう。
という事で、公式のインストールガイドに沿ってみる。
https://github.com/phpredis/phpredis/blob/develop/INSTALL.markdown
コンテナビルドの前に、まずはコンテナログインしてインストールできるかを確認してみる。
以下、インストールコマンド。
pecl install redis
実行結果。
/application # pecl install redis
downloading redis-5.3.4.tgz ...
Starting to download redis-5.3.4.tgz (268,154 bytes)
........................................................done: 268,154 bytes
29 source files, building
running: phpize
Configuring for:
PHP Api Version: 20190902
Zend Module Api No: 20190902
Zend Extension Api No: 320190902
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.
ERROR: `phpize' failed
予想通り、上手く行かない。
これで行けるのか? https://github.com/docker-library/php/issues/412
コマンド
apk add --no-cache \
$PHPIZE_DEPS \
openssl-dev
実行結果
/application # apk add --no-cache \
> $PHPIZE_DEPS \
> openssl-dev
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
(1/22) Upgrading musl (1.2.2-r0 -> 1.2.2-r1)
中略
(22/22) Installing re2c (1.3-r1)
Executing busybox-1.32.1-r0.trigger
Executing ca-certificates-20191127-r5.trigger
OK: 357 MiB in 81 packages
行けたっぽい。
という事で、気を取り直して、「pecl install redis」を再実行。
/application # pecl install redis
downloading redis-5.3.4.tgz ...
Starting to download redis-5.3.4.tgz (268,154 bytes)
........................................................done: 268,154 bytes
29 source files, building
running: phpize
Configuring for:
PHP Api Version: 20190902
Zend Module Api No: 20190902
Zend Extension Api No: 320190902
enable igbinary serializer support? [no] :
(中略)
Build complete.
Don't forget to run 'make test'.
(中略)
Build process completed successfully
Installing '/usr/local/lib/php/extensions/no-debug-non-zts-20190902/redis.so'
install ok: channel://pecl.php.net/redis-5.3.4
configuration option "php_ini" is not set to php.ini location
You should add "extension=redis.so" to php.ini
どうやら上手く行ったみたい。
あとは、Laravel の設定を変更。
CACHE_DRIVER=redis
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
あとはキャッシュをクリア
php artisan config:clear
php artisan config:cache
無事、Redis を動かす事が出来ました。
ちなみに、web.php に以下のような超適当なコードを書いて実験してみました。
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Cache;
//============================================================================================
// Cache
//============================================================================================
// http://localhost:8000/cache/put
Route::get('/cache/put', function () {
echo "put";
Cache::put('key01', 'value01');
});
Route::get('/cache/remember', function () {
echo "remember";
$cache = \Cache::remember('key02', 10, function(){
return "value02_remember";
});
dump($cache);
});
Route::get('/cache/get', function () {
echo "get";
$cache01 = Cache::get('key01');
$cache02 = Cache::get('key02');
dump($cache01);
dump($cache02);
});
Route::get('/cache/forget', function () {
echo "forget";
Cache::forget('key01');
Cache::forget('key02');
});
pecl install redis コマンドにてインストールした後、以下のメッセージが表示されています。
You should add “extension=redis.so” to
との事ですが、別に追記せずとも動きました。
詳細は私も良く分かってないのですが、Laravel が気を利かせて、勝手に読みに行ってるとか?
Laravel Redisのライブラリをインストールしたらエラーが発生した
こちらでは、
『エラーが出たけど、php.ini「extension=“redis.so」をコメントアウトしたら直った。』
といった内容が書かれています。
という事は、Laravel を使う場合は、この設定は不要なのかもしれません。
ただ、別の環境にアップする時にはエラーが発生するケースがあるようです。
AWSにLaravelをデプロイしたらエラーが出たときの対応方法
EC2 にアップすると動かなかったので、php.ini に extension=redis.so を追記しているようです。
「本番環境では動かない!」という場合のため、こんな現象があるという事を記憶に留めておいた方がよさそう。
おそらく Amazon Linux(RedHat系)を使っているのも、考えられる原因の1つでしょうか。
後で試してみたのですが、Debian では特に問題なく動作できました。
まずは php.ini のパスを確認。
以下、コマンド。
php -i | grep php.ini
実行結果例
/application $ php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => /usr/local/etc/php/php.ini
上記では、保存パスが「/usr/local/etc/php/php.ini」だったので、追記パスは以下。
echo "extension=redis.so" >> /usr/local/etc/php/php.ini
追記後は php.ini の内容を確認。
その後、再起動。
こちらも試してみました。
composer でインストールができるので、PhpRedis よりも遥かに楽です。
詳細は公式サイトを。
https://readouble.com/laravel/8.x/ja/redis.html
後は、アプリ動かそうとしたら
「Predis Client not found」
というメッセージが出てきたので、ググって解決したという感じでしょうか。
.env や config を正しく設定できていれば、すんなり行くのではないかと思います。
PhpRedis 速い! PhpRedis 最高! 絶対 PhpRedis にするべき!
みたいな意見もちらほら見かけるけど、結局、OS に手を加えざるを得ず、そこに余計に気を回さないといけなくなり、環境構築の難易度を上げるぐらいなら、いっそ Predis を選択するのもアリなのでは?
と思った。
開発が中断されるのが懸念事項に上がってけど、少なくとも今は再開しているし、composer で管理できるしで、色々メリットはある。
性能は PhpRedis の方が上だけど、システムによってはキャッシュへのアクセスがそこまで頻繁に起こらないケースもあるだろうし、そこまで厳しいアクセススピードの性能が求められないなら、管理コストを下げられるライブラリを選ぶ、というのも1つの選定基準だと思う。
少なくとも自分は、上記のような理由で PhpRedis ではなく Predis を採用する責任者が居たとしても何ら疑問はないし、その意見に反対するつもりも無い。
ちなみに自分は
「高速化と軽量化は常に正義!(たとえ厳しく求められないケースであっても。技術負債を抱えてでも実施するべき!)」
という意見には否定的です。
が、現在の場面においては、オフィシャルのアナウンス通り、PhpRedis にしておこうかと思います。
キャッシュドライバを使うだけで、何でこんなに苦労を・・
という事で、時代の流れに沿って PhpRedis を使う事にしたんだけど、コンテナイメージ作り直すの面倒くせええええ!!!
PHP ライブラリは composer で管理したい。
以下、インストールコマンド。
pecl install redis
特に何も問題が出ることはありませんでした。
やっぱ Debian の方がいいんじゃないのか・・・?
ある日、何をやってもブラウザに「500 エラー」としか出なくなってたので、laravel.log を見たら、こんなの出てた。
local.ERROR: Please make sure the PHP Redis extension is installed and enabled.
{"exception":"[object] (LogicException(code: 0): Please make sure the PHP Redis extension is installed and enabled.
at /var/www/html/my-laravel-app/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php:77)
あれ? 特に何も触ってないのに?
と思いきや、.env を弄ってて、環境設定ファイルが読み込みエラーになってたのが原因だった。
それ以外の全てのエラーを優先して前面に出て来るとは、なかなか主張が強いな・・