Memcache+PHP 会话调优:Memcache 如何使密钥过期?

Memcache+PHP 会话调优:Memcache 如何使密钥过期?

我对此进行了一些研究,但并未找到明确的答案。

我们有一个使用 PHP+Memcache 会话处理程序的 Web 应用程序。

我有几个问题,都是相互关联的,但最终我的问题是,“为什么 PHP 会话在我们认为应该过期的时候却没有过期?”即最终用户应该在设定的时间后退出应用程序,但事实并非如此。

以下是要点,请帮我将它们连接起来,并告诉我我哪里错了:

  • 我的理解是,Memcache 根据设定的时间(以秒为单位)使密钥过期(对于较大的值,则为 unix 时间戳)。
  • 过期是懒惰的——即不会提前删除任何内容
  • PHP memecache 会话处理程序使用 session.gc_max_lifetime 来设置 memcache 密钥过期时间。我不知道,也许它没有?
  • 在提供请求的密钥并发现它已过期时,Memcache 应该不再提供该密钥(然后可能还会删除它?)。但至少不提供该密钥。
  • 对于 PHP 来说,这种不提供服务的行为等同于删除会话并将用户注销。

用户尚未被注销。

我该如何调试它?Memcache 并不完全透明。

一个无法正常工作的示例案例是将会话超时设置为两小时的网站。示例用户最后一次使用该网站是在晚上,然后 8-10 小时后,再次访问该网站时仍处于登录状态。

答案1

我们也遇到过这种情况,但已经设法深入研究并找出了到底发生了什么。我们遇到的症状是 memcache(在多个服务器上运行的内存分配相当大)开始驱逐内容。这是不受欢迎的,因为它会对网站上的当前访问者产生不利影响。

通过监控网络流量,我们看到从PHP到Memcache的消息如下:

设置 memc.sess.key.abcdabcdabcdabcdabcdabcd 0 0 1823 数据...

第二个零是导致问题的根源 - 它决定了 memcache 缓存项目的时间长度。通过将其设置为零,memcache 永远不会使该项目过期。在您的案例中,这意味着用户可以在几个小时后返回并继续访问您的网站。在我们的案例中,memcache 已满并导致所需数据被逐出。

我进一步挖掘,发现问题出在 PHP memcached 扩展上。截至 1.0.2(我们正在运行),此代码如下:

sess_lifetime = zend_ini_long(ZEND_STRL("session.gc_maxlifetime"), 0);
if (sess_lifetime > 0) {
    expiration = time(NULL) + sess_lifetime;
} else {
    expiration = 0;
}

在此摘录中,它ZEND_STRL("session.gc_maxlifetime")未返回预期值。这已被报告为 PHP 的一个错误,并且对 memcached 库的修复描述如下https://bugs.php.net/bug.php?id=59641

我已经部署了此补丁,检查了网络流量,发现它确实按预期设置了到期时间。

相关内容