可以使用内存缓存守护进程池更有效地共享会话吗?

Tom*_*Tom 25 php performance lamp memcached

我们正在从 1 个网络服务器设置转移到两个网络服务器设置,我需要开始在两台负载平衡机器之间共享 PHP 会话。我们已经安装(并启动)了memcached,所以我很高兴我可以通过只更改文件中的3 行(session.save_handlersession.save_path)来完成新服务器之间的共享会话:php.ini

我替换了:

session.save_handler = files
Run Code Online (Sandbox Code Playgroud)

和:

session.save_handler = memcache
Run Code Online (Sandbox Code Playgroud)

然后在主 Web 服务器上,我将session.save_path指向 localhost:

session.save_path="tcp://localhost:11211"
Run Code Online (Sandbox Code Playgroud)

在从属网络服务器上,我将 设置session.save_path为指向主服务器:

session.save_path="tcp://192.168.0.1:11211"
Run Code Online (Sandbox Code Playgroud)

工作完成,我测试了它并且它有效。但...

显然,使用 memcache 意味着会话在 RAM 中,如果机器重新启动或 memcache 守护进程崩溃,会话将会丢失 - 我对此有点担心,但我更担心两个网络服务器之间的网络流量(尤其是当我们扩大规模),因为每当有人负载平衡到从网络服务器时,他们的会话将从主网络服务器通过网络获取。我想知道是否可以定义两个,save_paths以便机器在使用网络之前查看自己的会话存储。例如:

掌握:

session.save_path="tcp://localhost:11211, tcp://192.168.0.2:11211"
Run Code Online (Sandbox Code Playgroud)

奴隶:

session.save_path="tcp://localhost:11211, tcp://192.168.0.1:11211"
Run Code Online (Sandbox Code Playgroud)

这会成功地跨服务器共享会话并帮助提高性能吗?即节省 50% 的时间网络流量。还是这种技术仅适用于故障转移(例如,当一个内存缓存守护进程无法访问时)?

注意:我并不是特别询问内存缓存复制 - 更多关于 PHP 内存缓存客户端是否可以在池中的每个内存缓存守护进程内达到峰值,如果找到一个会话,则返回一个会话,如果没有找到,则只创建一个新会话在所有商店。在我写这篇文章的时候,我想我对 PHP 的要求有点高,哈哈...

假设:没有粘性会话、循环负载平衡、LAMP 服务器。

Tom*_*Tom 37

免责声明:如果没有进行大量测试并从合格的人那里获得第二意见,你会很生气 - 我是这个游戏的新手

这个问题提出的效率提升思路是行不通的。我犯的主要错误是认为 memcached 存储在池中定义的顺序决定了某种优先级。事实并非如此。当您定义一个 memached 守护进程池(例如 using session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211")时,您无法知道将使用哪个存储。数据是均匀分布的,这意味着一个项目可能存储在第一个,也可能是最后一个(如果 memcache 客户端配置为复制,则可能两者都存储 - 请注意,处理复制的是客户端,memcached 服务器会不要自己做)。无论哪种方式都意味着使用 localhost 作为池中的第一个不会提高性能 - 有 50% 的机会命中任一存储。

经过一些测试和研究后,我得出结论,您可以使用 memcache 跨服务器共享会话,但您可能不希望这样做 - 它似乎并不流行,因为它的扩展性不如使用共享它的数据库不那么健壮。我很感激对此的反馈,以便我可以了解更多...

除非您有 PHP 应用程序,否则请忽略以下内容:


提示 1:如果您想使用 memcache 在 2 个服务器之间共享会话:

确保您在安装 PHP 内存缓存客户端并在文件中添加以下内容时对“启用内存缓存会话处理程序支持? ”回答/etc/php.d/memcache.ini

session.save_handler = memcache
Run Code Online (Sandbox Code Playgroud)

在网络服务器 1(IP:192.168.0.1)上:

session.save_path="tcp://192.168.0.1:11211"
Run Code Online (Sandbox Code Playgroud)

在网络服务器 2(IP:192.168.0.2)上:

session.save_path="tcp://192.168.0.1:11211"
Run Code Online (Sandbox Code Playgroud)

提示 2:如果您想使用 memcache 在 2 个服务器之间共享会话并具有故障转移支持:

将以下内容添加到您的/etc/php.d/memcache.ini文件中:

memcache.hash_strategy = consistent
memcache.allow_failover = 1
Run Code Online (Sandbox Code Playgroud)

在网络服务器 1(IP:192.168.0.1)上:

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"
Run Code Online (Sandbox Code Playgroud)

在网络服务器 2(IP:192.168.0.2)上:

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这突出了我在原始问题中犯的另一个错误 - 我没有session.save_path在所有服务器上使用相同的。
  • 在这种情况下,“故障转移”意味着如果一个内存缓存守护进程失败,PHP 内存缓存客户端将开始使用另一个。即任何在商店中进行会话失败的人都将被注销。它不是透明的故障转移。

提示 3:如果您想使用 memcache 共享会话并具有透明的故障转移支持:

与提示 2 相同,但您需要将以下内容添加到您的/etc/php.d/memcache.ini文件中:

memcache.session_redundancy=2
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这使得 PHP 内存缓存客户端将会话写入 2 个服务器。您获得冗余(如 RAID-1),以便将写入发送到 n 个镜像,并get's在镜像上重试失败。这意味着在一个内存缓存守护进程失败的情况下,用户不会丢失他们的会话。
  • 镜像写入是并行完成的(使用非阻塞 IO),因此速度性能不应随着镜像数量的增加而大幅下降。但是,如果您的 memcache 镜像分布在不同的机器上,网络流量将会增加。例如,不再有 50% 的机会使用 localhost 和避免网络访问。
    • 显然,写入复制的延迟会导致检索旧数据而不是缓存未命中。问题是这对您的应用程序是否重要?你多久写一次会话数据?
  • memcache.session_redundancy用于会话冗余,但memcache.redundancy如果您希望 PHP 应用程序代码具有不同级别的冗余,还可以使用一个ini 选项。
  • 您需要PHP memcache 客户端的最新版本(此时仍处于测试阶段) - pecl 的 3.0.3 版对我有用


小智 28

回复:上面的提示 3(对于碰巧通过 google 遇到此问题的任何其他人),似乎至少目前为了使其正常工作,您必须使用memcache.session_redundancy = N+1池中的 N 个服务器,至少这似乎是最低阈值有效的价值。(在 debian stable、pecl memcache 3.0.6、两台 memcached 服务器上使用 php 5.3.3 进行测试。 session_redundancy=2一旦我关闭 中的第一台服务器就会失败save_pathsession_redundancy=3工作正常。)

这似乎在这些错误报告中被捕获: