如何在多个 Symfony 实例(共享缓存池)之间共享应用程序缓存?

alv*_*ery 2 php symfony symfony-cache symfony4 symfony-messenger

我的 symfony 应用程序有多个实例在单独的 docker 容器中运行

我已经配置我app.cache使用redis:

framework:
    cache:
        app: cache.adapter.redis
Run Code Online (Sandbox Code Playgroud)

我有同样的prefix_seed

framework:
    cache:
        prefix_seed: 'dev'
Run Code Online (Sandbox Code Playgroud)

结果,我在 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"
Run Code Online (Sandbox Code Playgroud)

从上面可以看出,2 个不同的实例试图通过相同的键从 redis 中获取值,workers.restart_requested_timestamp但即使使用相同的prefix_seed.

在这个例子中,我使用了 messenger 组件,我想通过stop-workers命令(通过共享 redis)停止在任何地方运行的工人。但一般来说这与缓存配置有关。

如何克服这个问题并告诉两个应用程序使用相同的池?这是什么配置?

alv*_*ery 5

最后,我找到了解决方案。可以选择使用映射的适配器创建自己的缓存池。这里的主要技巧是将标签传递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' }
Run Code Online (Sandbox Code Playgroud)

就是这样!您在 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"
Run Code Online (Sandbox Code Playgroud)