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

JDS*_*JDS 7 php moodle memcache session

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

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

我有几个问题,都是相互关联的,但最终我的问题是,“为什么 PHP 会话在我们认为应该到期时显然没有到期?” 即最终用户应该在设定的时间后退出应用程序,但不是。

下面是点,请帮我把它们连接起来,并告诉我我错在哪里:

  • 我的理解是 Memcache 根据设置的时间使键过期,以秒为单位(或更大值的 unix 时间戳)。
  • 过期是懒惰的——即什么都没有被提前删除
  • PHP memecache session handler 使用sessions.gc_max_lifetime 来设置memcache key 过期时间。idk,也许不是?
  • Memcache 应该在提供请求的密钥并看到它已过期时不提供它(然后也可能删除它?)。但至少不会为它服务。
  • 对于 PHP 而言,这种不提供服务的行为应该等同于删除的会话和用户被注销。

用户没有被注销。

我怎么能调试呢?Memcache 并不完全透明。

没有工作的示例案例是会话超时设置为两小时的站点。示例用户会在晚上最后一次使用该站点,然后在 8 到 10 小时后返回该站点并仍处于登录状态。

小智 10

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

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

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

这是导致问题的第二个零 - 这决定了 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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