【Laravel】Redis ライブラリは PhpRedis が推奨されているが、Predis を採用した方がいい場面も多いのでは?

memory システム開発

【 環境 】
MySQL version : 5.7
Laravel version : 8.16.1
PHP version : 7.4.7

Laravel で Redis を使う時のライブラリ

Laravel で Redis を使う時、PHP のライブラリに以下の2つの候補が出てきます。

デフォルトだと、composer.lock に「predis」が記述されています。

composer.lock

    "packages": [
        {
            "require-dev": {
                "predis/predis": "^1.1.2",
                "symfony/cache": "^5.1.4"
            },

config\database.php

    'redis' => [
        'client' => env('REDIS_CLIENT', 'phpredis'),

composer.lock にて指定している predis は、使用されていない。(デフォルトの設定では)

database.php で指定している phpredis は、別途 phpredis をインストールしなければ、使う事ができない。

何なんだこの中途半端な状態は。

疑問に思って調べてみると、predis はデフォルトから外される予定だったけど、やっぱ外すのやめたーって事になり、とはいっても phpredis を推奨したいし・・・
といった感じで、どっちつかずの状態になっているようです。(推測)

どちらを採用するべき?

どちらを使えばいいのかについては議論が活発なようで、こんなのがありました。

PHP向けRedisクライアントのpredisを使うのは止めた方がいいです

predisはPHP向けのRedisクライアントです。

リポジトリを見て察しのいい方は気づいたと思うのですが、2年ぐらいメンテ(コミットすら)されていません。

すでにPHP7.3周りで問題が出てます。これが「どういった事情でメンテされていないのか?」「されないのではなく、できないのか?」などは誰もわからないと思いますし、もしかしたら将来的に再度メンテされる可能性はありえます。

現在はどうなっているのか気になって調べてみたところ、2022年 9月現在は、無事開発は再開され、活発に活動されています。
https://github.com/predis/predis/pulse

そのため、開発ストップによる懸念事項は無いものと考えて良さそうです。

Laravelのドキュメントにも書いてありますが、phpredis使えばいいと思います。

こちらはcomposerでインストールできない(PHP拡張モジュールなので)のでpeclでインストールします。

いやああああ!!!
マジなの? 令和にもなって、PHPライブラリを composer でインストールできないとか正気なの??

さすがに今では改善されているんじゃ・・・と思って公式サイトの PhpRedis 公式のインストールガイドを見てみた。
が、pecl を使えという夢も希望も無いメッセージが。

File not found · phpredis/phpredis
A PHP extension for Redis. Contribute to phpredis/phpredis development by creating an account on GitHub.

こんなのもあった。
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拡張機能をインストールして使用することを推奨します。

Many developers highly recommended phpredis.

PhpRedis のインストール

インストールコマンド

ディストリビューションは Debian と Alpine で試してみました。

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

上記のエラーが出た時に実行するコマンド

apk add --no-cache \
        $PHPIZE_DEPS \
        openssl-dev

Dockerfile に記述する場合

FROM php:7.4.11-fpm

# 中略

RUN git clone https://github.com/phpredis/phpredis.git /usr/src/php/ext/redis
RUN docker-php-ext-install redis

インストールチェック

You can check whether PhpRedis is installed correctly with the following command.

php -m | grep redis

If you see the following message, PhpRedis has been successfully installed.

redis

Redis コンテナの設定

docker-compose.yml

version: '3'
services:

# 中略

  redis:
    image: "redis:6.0"
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"

Laravel の設定

.env

CACHE_DRIVER=redis

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

config\database.php

    'redis' => [

        'client' => env('REDIS_CLIENT', 'phpredis'),

アプリ実行前に、以下のコマンドでキャッシュをクリア。

php artisan config:clear

実験用ソース

以下のような超適当なコードを書いて実験してみました。

routes\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');
});

// http://localhost:8000/cache/remember
Route::get('/cache/remember', function () {
    echo "remember";

    // 値を恒久的に保存する
    cache = \Cache::remember('key02', 10, function(){
        return "value02_remember";
    });

    dump(cache);
});

// http://localhost:8000/cache/get
Route::get('/cache/get', function () {
    echo "get";

    // キャッシュからアイテム一つを取得する
    cache01 = Cache::get('key01');cache02 = Cache::get('key02');

    dump(cache01);
    dump(cache02);
});

// http://localhost:8000/cache/forget
Route::get('/cache/forget', function () {
    echo "forget";

    // キャッシュからアイテムを消去
    Cache::forget('key01');
    Cache::forget('key02');
});

無事、Redis を動作させる事が出来ました。

その他注意事項

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 に extension=redis.so を追記

まずは 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 の内容を確認。

その後、再起動。

Predis を使う場合

こちらも試してみました。

composer でインストールができるので、PhpRedis よりも遥かに楽です。

詳細は公式サイトを。
https://readouble.com/laravel/8.x/ja/redis.html

以下、実行コマンドです。

composer require predis/predis

.env や config を正しく設定できていれば、すんなり行くのではないかと思います。

Laravel の設定

config\database.php

    'redis' => [

        'client' => env('REDIS_CLIENT', 'predis'),

それ以外の設定や、実験にて使用したコードは上記と共通です。

ディストリビューションによる差異を受けないので、想定外の事に遭遇する事も無く、心に余裕ができます。

採用選定基準についての所管

PhpRedis 速い! PhpRedis 最高! 絶対 PhpRedis にするべき!
みたいな意見もちらほら見かけるけど、パッケージマネージャーによる管理ができず、ハードに近い部分に手を加えなければいけないので気を回す部分が増えます。

結果として、環境構築の難易度が上がったり通常運用時に不測の事態が発生する可能性が上がったりするので、いっそ Predis を選択するのもアリなのでは?
というのが個人的な意見。

Predis 開発の中断が懸念事項に上がってけど、少なくとも現在は再開しているし、composer で管理できるし、色々メリットはある。

性能は PhpRedis の方が上だけど、システムによってはキャッシュへのアクセスがそこまで頻繁に起こらないケースもあるだろうし、そこまで厳しいアクセススピードの性能が求められないなら、管理コストを下げられるライブラリを選ぶ、というのも1つの選定基準だと思う。

少なくとも自分は、上記のような理由で PhpRedis ではなく Predis を採用する責任者が居たとしても何ら疑問はないし、その意見に反対するつもりも無い。

ちなみに自分は
「高速化と軽量化は常に正義!(たとえフロント側のパフォーマンスが厳しく求められないアプリケーションでも。技術負債を抱えてでも実施するべき!)」
という意見には否定的です。

composer で管理できない以上、Docker イメージを作り直す必要があるし、EC2 のような仮想サーバで動かす事を想定するならディストリビューションごとにインストールコマンド用意したりする必要があったりと、ややこしい作業が増えるし。

まとめ

  • Laravel で Redis を使う場合、2種類のライブラリのうち、どちらかを採用する。「Predis」か「PhpRedis」
  • 昔は Predis が使われていたが、現在では PhpRedis が推奨されている。(公式でさえ)
  • PhpRedis は composer で管理できず、pecl でインストールする必要がある
  • そのため、コンテナを使っている場合、イメージを作り替える必要がある
  • php.ini に “extension=redis.so” の追記が必要かもしれないけど、無くても動く。ただし環境によるかも。

「キャッシュドライバを使うだけで、何でこんなに苦労を・・・? このシステムではフロントは大して重要じゃないのに」と思った方は、是非 Predis の採用を検討してみてください。

おまけ

ある日、何をやってもブラウザに「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 を弄ってて、環境設定ファイルが読み込みエラーになってたのが原因だった。(Redis と全く関係無い部分)

それ以外の全てのエラーを優先して前面に出て来るとは、なかなか主張が強いな・・・

コメント

タイトルとURLをコピーしました