容错 Memcached 池中的 PHP 会话存储

Joe*_*Joe 5 memcached php-fpm php-memcached

我最近有机会将 Web 应用程序从使用 Nginx 代理“负载均衡器”转移到 F5 负载均衡器。不幸的是,在迁移过程中,很明显memcached会话存储需要从 Nginx 代理服务器移动到“某个地方”。我的想法是我应该安装memcached所有 3 个 Web 服务器(位于池中 F5 后面的服务器)并使用php-memcachephp-memcached保存会话。麻烦来了:

我已经尝试了两者php-memcachephp-memcached并且如果其中一台服务器出现故障,任何一个都无法正常运行。我最近的尝试是使用这种配置:

memcached 带有配置设置的 2.2.0 版:

session.save_handler = memcached
session.save_path = "172.29.104.13:11211,172.29.104.14:11211"

我没有什么特别的memcached.ini比其他extension=memcached.so

使用服务器 1 和 2 上的此配置(我暂时删除了 3 个进行测试),我将 JMeter 指向 F5 VIP 并启动流量。我可以memcached.log在两个系统上看到(守护进程),虽然还没有花时间破译,开始运行。

然后如果我停止其中一个memcached守护进程,流量开始失败,我的回报是

session_start(): Write of lock failed

memcached剩下的那个。

归根结底,我的目标很简单 - 我需要能够 a) 不在memcached单个服务器上运行(单点故障),并且集群需要能够适应池成员的故障。

我也试过,php-memcache但也失败了。对于php-memcache配置如下所示:

memcache 具有配置设置的 3.0.8 (beta) 版:

 
session.save_handler = memcache
session.save_path = "tcp://172.29.104.13:11211, tcp://172.29.104.14:11211"

并在memcache.ini

扩展=内存缓存.so
[内存缓存]
memcache.dbpath="/var/lib/memcache"
memcache.maxreclevel=0
memcache.maxfiles=0
memcache.archivememlim=0
memcache.maxfilesize=0
memcache.maxratio=0
memcache.hash_strategy=一致
memcache.allow_failover=1
memcache.session_redundancy=2

这里的错误只是无效的会话令牌(对我来说暗示剩余的服务器没有实际存储会话令牌,这意味着保存会话的复制未激活)。

我还没有考虑将会话持久性重新放在 F5 上,但作为最后的手段,我可​​以这样做,并且客户端试图连接到丢失的成员将不得不重新进行身份验证。

rma*_*ter 0

让客户端在 cookie 中为您存储会话状态要简单得多。这意味着服务器端没有会话存储,只有几微秒的 CPU 使用率来解密和验证 cookie。由于 CPU 是数据中心中迄今为止最丰富的资源,因此该方案的性能比从 memcached 或任何其他服务器会话存储进行查找要好得多。

请参阅https://github.com/ascorbic/php-stateless-cookies了解一种实现,还有许多其他实现。请注意,会话数据应加密,但必须通过 HMAC 或 AEAD 密码进行身份验证。除非您是密码学家,否则不要自己编写此代码;使用经过严格审查的低温库。

Facebook 使用这种技术,因此任何服务器都可以响应任何用户请求,即使用户会话是在另一个数据中心启动的。