Concrete CMS (v9 以降) でセッションやキャッシュを ElastiCache (Redis) に保存する方法

Concrete CMS Version 9 以降で、Redis を使うようにする設定を解説します。

Concrete CMS はサーバー構成を簡単に冗長化することができます。方法の二つが、EFS などのネットワークドライブでサーバー間を共有する方法と、AWS の EasltiCache などの Redis や Memcached にセッションやキャッシュを保存し、ファイルを Amazon S3 などのオブジェクトストレージで管理するという方法です。

その、セッションやキャッシュデータを保存する場所として選ばれるのが、ElastiCache の Redis です。

Concrete CMS 8.x の解説はこちら
https://qiita.com/katzueno/items/0f172a2d5bc65fc9acb2


- Redis のエンドポイント・ポート番号を適宜設定変更してください
- php-pecl-redis をサーバーにインストールしてください。
    - Amazon Linux 2 へは後述の参考記事参照。
    - Amazon Linux 2023 は、Intel は Remi レポジトリ、Graviton はコンパイルする必要があります。
- 複数の Concrete5 を同じ Redis 内で動かす場合は、キャッシュ部分の `database` の ID が被らないように設定してください。
- Session の設定は `prefix` が被らないようにしてください。database は `0` のままで良いです。
- Redis のデフォルトでは `database` は 0~15 までしか設定できないため、理論上は 7 つの Concrete CMS サイトの共存が可能です。(Session 情報は database 0 を利用し続けたとして) ただし、キャッシュのサイズなどでパフォーマンスや容量不足が起こる可能性がありますので、かならずパフォーマンスの検証をしてください。

Concrete CMS 9 以降の config への Redis サーバーの設定方法のサンプルを書いておきます。

以下 concrete.php の設定ファイルに保存して使ってください。

```
<?php
$redisDriverOverrides = [
    'preferred_driver' => 'redis',
    'drivers'=> [
        'redis'=>[
            'class' => \Concrete\Core\Cache\Driver\RedisStashDriver::class,
            'options' => [
                'servers' => [
                    [
                        'server' => '【Redis エンドポイント】',
                        'port' => 6379,
                        'ttl' => 10 //Connection Timeout - not TTL for objects
                    ],
                ],
                'prefix'=>'concrete_overrides',
                'database'=> 1
            ],
        ],
        'core_ephemeral' => [
            'class' => '\Stash\Driver\Ephemeral',
            'options' => [],
        ],
        'core_filesystem' => [
            'class' => \Concrete\Core\Cache\Driver\FileSystemStashDriver::class,
            'options' => [
                'path' => DIR_FILES_UPLOADED_STANDARD . '/cache/overrides',
                'dirPermissions' => DIRECTORY_PERMISSIONS_MODE_COMPUTED,
                'filePermissions' => FILE_PERMISSIONS_MODE_COMPUTED,
            ],
        ],
    ],
];
$redisDriverExpensive = [
    'preferred_driver' => 'redis',
    'drivers'=> [
        'redis'=>[
            'class' => \Concrete\Core\Cache\Driver\RedisStashDriver::class,
            'options' => [
                'servers' => [
                    [
                        'server' => '【Redis エンドポイント】',
                        'port' => 6379,
                        'ttl' => 10 //Connection Timeout - not TTL for objects
                    ],
                ],
                'prefix'=>'concrete_expensive',
                'database'=> 1
            ],
        ],
        'core_ephemeral' => [
            'class' => '\Stash\Driver\Ephemeral',
            'options' => [],
        ],
        'core_filesystem' => [
            'class' => \Concrete\Core\Cache\Driver\FileSystemStashDriver::class,
            'options' => [
                'path' => DIR_FILES_UPLOADED_STANDARD . '/cache/expensive',
                'dirPermissions' => DIRECTORY_PERMISSIONS_MODE_COMPUTED,
                'filePermissions' => FILE_PERMISSIONS_MODE_COMPUTED,
            ],
        ],
    ],
];

$cache = [];
$session = [];

// キャッシュ設定の定義。フルページキャッシュの保存先の設定と、さきほどの $redisDriverOverrides & $redisDriverExpensive の設定値を適用。Objectキャッシュはデフォルトのメモリのままにする（その方が高速) その他 Expensive キャッシュを SQLite に設定する方法などもあり
$cache = [
    'page' => [
        'adapter' => 'redis',
        'redis' => [
            'class' => \Concrete\Core\Cache\Driver\RedisStashDriver::class,
            'servers' => [
                [
                    'server' => '【Redis エンドポイント】', // localhost もしくは ElastiCache などのエンドポイント
                    'port' => 6379, // ポート番号
                    'ttl' => 30 //Connection Timeout - not TTL for objects
                ],
            ],
            'prefix'=>'concrete_cache',
            'database'=> 2
        ],
    ],
    'levels' => [
        'overrides' => $redisDriverOverrides,
        'expensive' => $redisDriverExpensive,
        'object' => [
            'preferred_driver' => 'core_ephemeral'
        ],
    ],
];

// PHP Session の保存先を定義
$session = [
    'handler' => 'redis',
    'redis' => [
        'servers' => [
            [
                'server' => '【Redis エンドポイント】',
                'port' => 6379,
                'ttl' => 30 //Connection Timeout - not TTL for objects
            ],
        ],
        'prefix' => 'scg_session',
        'database'=> 0
    ],
    /*
    'cookie' => [
        'cookie_secure' => true,
    ],
    */
];

// よく使っている config のサンプルも置いておきます。

/* Concrete CMS のキャッシュ設定
--------------------------
環境別にキャッシュ設定を分けたい場合に、
下記のコメントアウト部分を有効にし設定します。
参考記事 https://qiita.com/katzueno/items/43258716424aac82468f
*/
/*
$cache = array_merge(
    $cache,  [
    'blocks' => true,
    'assets' => false,
    'theme_css' => false,
    'overrides' => true,
    'pages' => 'blocks',
]
);
*/

// ここで Concrete CMS に設定を返す

return [
    'cache' => $cache,
    'session' => $session,
    // よく使っている config のサンプルも置いておきます。
    /*
    * ------------------------------------------------------------------------
    * Setting VPC's IP range as trusted proxy
    * ------------------------------------------------------------------------
    */
    /*
    'security' => [
        'trusted_proxies' => [
            'ips' => [
                '10.0.0.0/16',
            ],
        ]
    ],
    */
    /* ******************************
    Debug Setting - Prod Site may not want to display the error message.     If it's load balancing, generated override settings won't be saved UNLESS you use Redis stored setting which was introduced in 8.5.3.
    ****************************** */
    'debug' => [
        'display_errors' => false,
        'detail' => 'debug',
        'error_reporting' => null,
    ],
    /*
    * ------------------------------------------------------------------------
    * Marketplace settings
    * ------------------------------------------------------------------------
    */
    /*
    'marketplace' => [
        'enabled' => false,
        'intelligent_search' => false,
    ],
    */
    /*
    * ------------------------------------------------------------------------
    * Getting external news and help from concrete5.org
    * ------------------------------------------------------------------------
    */
    /*
    'external' => [
        'intelligent_search_help' => false,
        'news' => false,
    ],
    */
];
```

## 参考記事

- [Amazon Linux 2 の PHP7.2 で ElastiCache の Redis を使う方法](https://qiita.com/katzueno/items/95254fdcf5e357c52202)
- [Concrete CMS で環境ごとに別の設定ファイルを読み込む方法](https://qiita.com/katzueno/items/43258716424aac82468f)
- [Amazon Linux 2023 で PHP Redis エクステンションをコンパイルする](https://qiita.com/katzueno/items/bdfb87a9a15120a9f409)