Настройте кеш Symfony для использования реплик чтения AWS Redis

Я запустил кластер Redis в AWS с двумя узлами: основным и репликой. Кластер имеет две точки входа: основную точку входа и точку входа читателя.

В моем приложении Symfony я использую основную точку входа в конфигурации .env.

REDIS_HOST=xxx-redis.yyy.ng.0001.zone.cache.amazonaws.com
REDIS_PORT=6379

и конфигурацию кеша в рамках framework.cache в кэше.yaml следующим образом:

app: cache.adapter.redis
default_redis_provider: redis://%env(REDIS_HOST)%:%env(int:REDIS_PORT)%

Приложение работает хорошо, кеш используется, но я заметил, что используется только основной узел, реплика не регистрирует никаких попаданий.

Я много искал в Google примеры конфигурации о том, как добавить точку входа только для чтения в конфигурацию Symfony Redis, но ничего не нашел.

Итак, я надеюсь, что у кого-то была такая же проблема и он нашел решение. Я думаю, может быть, стоит сделать специальный адаптер кэша или что-то в этом роде?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
210
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы использовать репликацию, вы можете предоставить несколько URL-адресов внутри Redis DNS, как указано в этой документации . Используйте AWS, предоставляя основные конечные точки Primary и Reader, а не конечные точки отдельных узлов. Итак, вам нужно только 2 URL-адреса, нет

default_redis_provider: 'redis:?host[xxx-redis.yyy.ng.0001.zone.cache.amazonaws.com]&host[xxx-redis.yyy-ro.ng.0001.zone.cache.amazonaws.com]'

Обратите внимание, что после // нет redis:. Всю эту информацию можно прочитать и отладить внутри /vendor/symfony/cache/Traits/RedisTrait.php метода createConnection.

Теперь самое интересное при использовании пакета Predis:

Для этого необходимо добавить ?role=master и, возможно, ?role=slave в URL-адрес хоста.

Итак, ваша конфигурация YAML будет выглядеть так:

default_redis_provider: 'redis:?host[xxx-redis.amazonaws.com%3Frole%3Dmaster]&host[xxx-redis-ro.amazonaws.com%3Frole%3Dslave]'

  • Имейте в виду, что вам также нужно сбежать %
  • Чтобы обойти экранирование, вы можете сделать host[xxx-redis.amazonaws.com][role]=master
  • Если написать предыдущую точку в многострочном формате с помощью >-, к параметрам будут добавлены пробелы:
default_redis_provider: >-
    ?host[xxx-redis.amazonaws.com][role]=master
    &host[xxx-redis-ro.amazonaws.com][role]=slave

становится ?host[xxx-redis.amazonaws.com][role]=master &host[xxx-redis-ro.amazonaws.com][role]=slave


Для этого я сделал собственную реализацию RedisAdapter:

framework:
    cache:
        prefix_seed: '%env(ENVIRONMENT)%'
        pools:
            external.cache:
                adapter: cache.adapter.redis_tag_aware
                provider: App\Component\Cache\Adapter\RedisAdapter

services:
    App\Component\Cache\Adapter\RedisAdapter:
        factory: [null, 'createReplicaConnection']
        arguments:
            $primaryHost: '%app.cache.redis.host.primary%'
            $readerHost: '%app.cache.redis.host.reader%'
use Predis\Client;
use Symfony\Component\Cache\Adapter\RedisAdapter as BaseRedisAdapter;

class RedisAdapter extends BaseRedisAdapter
{
    public static function createReplicaConnection(
        string|array $primaryHost,
        null|string|array $readerHost = null,
        array $options = [],
    ): \Redis|\RedisArray|\RedisCluster|ClientInterface|Relay {
        $data = [
            'host' => [],
            'class' => Client::class,
            'replication' => 'predis',
        ];

        $primaryHost = array_merge(
            ['role' => 'master', 'alias' => 'primary'],
            is_string($primaryHost) ? ['host' => $primaryHost] : $primaryHost,
        );

        $data['host'][$primaryHost['host']] = $primaryHost;

        if ($readerHost !== null) {
            $readerHost = array_merge(
                ['role' => 'slave', 'alias' => 'reader'],
                is_string($readerHost) ? ['host' => $readerHost] : $readerHost,
            );
            $data['host'][$readerHost['host']] = $readerHost;
        }

        return static::createConnection('redis:?' . http_build_query($data), $options);
    }

У Symfony 7.1 проблемы с Predis: https://github.com/symfony/symfony/issues/49238

Другие вопросы по теме