是否可以使用Memcache守护程序池更有效地共享会话?


25

我们正在从1个Web服务器设置过渡到两个Web服务器设置,我需要开始在两个负载平衡的计算机之间共享PHP会话。我们已经安装并启动了memcached,因此我感到很惊讶,我只需更改文件中的3行(session.save_handlersession.save_path)就可以完成新服务器之间的共享会话:php.ini

我更换:

session.save_handler = files

与:

session.save_handler = memcache

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

session.save_path="tcp://localhost:11211"

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

session.save_path="tcp://192.168.0.1:11211"

工作完成,我对其进行了测试,并且可以正常工作。但...

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

主:

session.save_path="tcp://localhost:11211, tcp://192.168.0.2:11211"

奴隶:

session.save_path="tcp://localhost:11211, tcp://192.168.0.1:11211"

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

注意:我并不是真正在问有关Memcache复制的问题-有关PHP Memcache客户端是否可以在池中的每个Memcache守护程序内部达到峰值,如果找到一个则返回一个会话,如果找不到则仅创建一个新会话在所有商店。在写这篇文章的时候,我想我在向PHP提出很多要求,哈哈...

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


1
Memcache文档不建议将Memcache用于会话存储。请参阅code.google.com/p/memcached/wiki/…

Answers:


37

免责声明:你会拼了命地听我说不用做测试和从别人资格获得第2个见仁见智的吨- 我是新来这个游戏

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

经过一些测试和研究,我得出的结论是,您可以使用Memcache BUT在服务器之间共享会话,但您可能不想这样做-它似乎不受欢迎,因为它不像使用共享存储那样可扩展它的数据库不那么健壮。非常感谢您对此的反馈,以便我可以了解更多...

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


提示1:如果要使用memcache在两台服务器之间共享会话:

在安装PHP Memcache客户端并在文件中添加以下内容后,请确保对“是否启用Memcache会话处理程序支持? ” 回答“ ”。/etc/php.d/memcache.ini

session.save_handler = memcache

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

session.save_path="tcp://192.168.0.1:11211"

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

session.save_path="tcp://192.168.0.1:11211"

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

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

memcache.hash_strategy = consistent
memcache.allow_failover = 1

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

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

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

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

笔记:

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

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

与技巧2相同,除了需要在/etc/php.d/memcache.ini文件中添加以下内容:

memcache.session_redundancy=2

笔记:

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

您能否评论“它不像使用共享数据库那样可扩展”?我看不出它与典型的主从数据库设置有何不同。谢谢!
Boy Baukema'3

这是一个非常酷的细目分类,尽管有谣言(也就是错误报告)说,当您使用ext/memcache3.x版时,这种方法无法按预期工作。我们也正在使用该选项,因此我决定遍历服务器列表并自己写。
直到2012年

在技​​巧3的情况下,如果一台内存缓存的主机关闭然后又出现了,然后几秒钟的主机关闭了怎么办。据我了解-没有会话数据将被恢复,其中一些将丢失,对吗?
GioMac 2014年

28

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

这些错误报告似乎捕获了这一点:


1
不能给你足够的投票..
2013年

1
我很高兴我向下滚动。这就是问题所在。
Daren Schwenke 2013年

我不清楚,此功能仅在PECL memcache 3.x系列中可用吗?所有这些都在pecl.php.net/package/memcache的 Beta版软件中列出,而在2.2.7中,如果我杀死了看到领导者的服务器,那么一切都会消亡。
2014年

老实说,距离我看过已有好几年了。我记得这是3.x功能(icbw)。我们使用该插件的“ beta”版本(其中一些流量非常高)部署了许多系统,并且似乎没有与此相关的任何问题。YMMV,在将其投入使用之前对其进行测试,等等。:)我几年来一直没有在PHP中工作,因此一些琐碎的琐事开始逐渐消失。
2014年

3

连同上面显示的php.ini设置一起,确保也设置了以下内容:

memcache.allow_failover = 1  
memcache.hash_strategy = 'consistent'

然后,您将获得完整的故障转移和客户端冗余。使用此方法的警告是,如果localhost上的memcached关闭,则在php memcache客户端尝试在session.save_path中指定的池中的下一个服务器之前,始终会出现读取未命中的情况。

请记住,这会影响Web服务器上运行的php memcache客户端的全局设置。


consistent考虑到session.save_path每个Web服务器上的哈希值不同,使用哈希策略是否有意义?
汤姆(Tom)2010年

1

memcached不能那样工作(如果我输入错了,请纠正我!)

如果您希望应用程序具有冗余的会话存储,则必须创建一些东西来更改/添加/删除两个内存缓存实例的条目。memcached无法处理此问题,它提供的唯一功能就是密钥哈希存储。因此,没有复制,同步,没事,nada。

我希望我在这件事上没有错,但这是我对memcached的了解,距离我接触它已有几年了。


如果你错了,对我来说将很方便。:-) phpslacker.comphpslacker.com/2009/03/02/php-session-clustering-with-memcache)中有一篇文章建议memcached可以按照问题中的描述工作。也许这取决于内存缓存客户端如何实施哈希策略?
汤姆(Tom)2010年

1
memcache不能那样工作,但是php可以按照您希望的方式工作。您将必须更改php.ini或如所述更改您的应用程序。从博客中:您问的集群在哪里好吧,事实是,没有任何集群。到目前为止,我们有一个由2个服务器组成的内存缓存池。PHP已配置为写入池。PHP按照“ session.save_path” ini指令指定的顺序读取/写入服务器池。对于读取,PHP将通过池中的键请求缓存对象。因为“故障转移”已启用PHP将查询内存缓存服务器,一个接一个的游泳池,直到[...]
tore-

1

memcached不会立即复制,但是repcached(修补的memcached)会复制。但是,如果您已经在使用mysql,那么为什么不将它的复制功能与master-master复制结合使用,并获得完整数据复制的好处。

C。


谢谢(你的)信息。我追求的不是真正的复制。更多情况是希望依次进入每个内存缓存,直到找到会话。即首先检查localhost,因为它是最快的,然后再检查其他服务器。
汤姆(Tom)2010年

1
以众神的名义为什么???? 这是完全错误的解决方案……几乎所有我能想到的问题。如果仅添加2台服务器,效率将非常低下,而且如果您添加更多服务器,性能也会很快变得越来越差。而且,这没有考虑到您的解决方案发生故障的可能性是单个服务器的两倍,而实际上在群集中添加服务器应该可以减少发生中断的可能性。(顺便说一句,如果您的意思是基于DNS的轮询,那么会话亲和力是隐式的!)
symcbean 2010年

感谢您的反馈,是的,我自由地承认我是会话共享的新手!:-)但是,我仍然不明白为什么我的建议如此丑陋。我认为它比使用共享数据库更有效,而且还可以减少停机的可能性。
汤姆(Tom)2010年

不,这使他们更有可能。当节点数量非常多时,像这样进行数据联合是很有意义的,因为这样可以减少复制量,但是通常会在没有定义数量的池的情况下进行一些复制以保持可用性。您需要对性能非常挑剔,才能看到repcached复制和mysqld复制之间的差异。
symcbean

我已经测试并确认,只要我使用allow_failover = 1,多个镜像就不会造成中断。我可以关闭一个镜像,然后重新启动并关闭另一个镜像,然后重新启动并再次关闭第一个镜像-所有这些都无需注销。我猜想PHP内存缓存客户端在幕后做了很多骗术。
汤姆(Tom)2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.