Как разделить кеш приложения между несколькими экземплярами Symfony (общий пул кеша)?

У моего приложения symfony есть несколько экземпляров, которые работают в отдельных контейнерах докеров.

И я настроил свой app.cache использовать Redis:

framework:
    cache:
        app: cache.adapter.redis

У меня такая же prefix_seed:

framework:
    cache:
        prefix_seed: 'dev'

В результате я попадаю в redis примерно так:

1605259288.470950 [0 172.18.0.28:55044] "MGET" "HnMEIyUlZ+:workers.restart_requested_timestamp"
1605259288.471680 [0 172.18.0.28:55044] "SET" "HnMEIyUlZ+:workers.restart_requested_timestamp" "d:1605259288.471522;"
1605259314.483389 [0 172.18.0.29:42884] "MGET" "8TMgMtnOAG:workers.restart_requested_timestamp"

Как видно из приведенных выше двух разных экземпляров, они пытаются получить значение из Redis одним и тем же ключом. workers.restart_requested_timestamp но приставка разная даже у одинаковых prefix_seed.

В этом примере я использую компонент обмена сообщениями, и я хочу остановить выполнение рабочих повсюду с помощью stop-workersкоманда (через общий Redis). Но в целом это связано с настройкой кеша.

Как это преодолеть и указать обоим приложениям использовать один и тот же пул? Какая конфигурация для этого?

2 ответа

Решение

Наконец, я нашел решение. Есть возможность создать свой собственный кеш-пул с подключенным к нему адаптером. Основная хитрость здесь - передать тег с помощью namespace к вашему адаптеру (имя также должно быть cache.pool):

framework:
    cache:
        pools:
            cache.redis_shared_pool:
                adapter: app.cache_shared_redis_adapter

services:
    app.cache_shared_redis_adapter:
        parent: 'cache.adapter.redis'
        tags:
            - { name: 'cache.pool', namespace: 'shared' }

Это оно! Все ваши ключи в Redis будут иметь префикс shared:. Теперь вы должны передать @cache.redis_shared_pool на любую услугу, которую вы хотите.

А что касается компонента мессенджера, мы должны переопределить службы (но я не уверен, что это лучший способ):

console.command.messenger_stop_workers:
    class: Symfony\Component\Messenger\Command\StopWorkersCommand
    arguments:
       $restartSignalCachePool: "@cache.redis_shared_pool"

messenger.listener.stop_worker_on_restart_signal_listener:
    class: Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener
    arguments:
       $cachePool: "@cache.redis_shared_pool"

В определении конфигурации пакета фреймворка Symfony вы можете найти:

    private function addCacheSection(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('cache')
                    ->info('Cache configuration')
                    ->addDefaultsIfNotSet()
                    ->fixXmlConfig('pool')
                    ->children()
                        ->scalarNode('prefix_seed')
                            ->info('Used to namespace cache keys when using several apps with the same shared backend')
                            ->example('my-application-name')
                        ->end()
                        ...

prefix_seed - это именно то, что вы ищете. Проверьте документацию здесь: https://symfony.com/doc/current/reference/configuration/framework.html#prefix-seed

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