PHP 垃圾回收说明

2022-08-30 11:54:08

从PHP手册中,session.gc_probability和session.gc_divisor基于此概率发生gc的状态。我明白了。

我不清楚的是,这种概率是逐个会话还是整个会话。

因此,如果我发生GC的概率为1%(1/100),这是否意味着如果一个会话不断延长,则每次发生1%的变化时,该特定会话将被清理?或者这是否意味着所有现有会话(以及新会话)的 1% 将触发所有其他现有会话的 GC?

我很确定是后者,我只是想确保。

这个问题的目的是,在我们的网站上,我希望用户有长期的会话(6个月)。如果所有会话中有1%触发GC,那么这实际上消除了进行长期会话的目的,因为GC最终将每隔一两个小时发生一次。


答案 1

每次执行 PHP 脚本并启动会话时,它都有可能扫描会话文件夹,从而杀死旧会话。

清理只会删除在特定时间内未访问的会话。但是,PHP 不保证会话将在该时间内被销毁。

您的长期会话策略应该可以正常工作,但您可能希望将1%减少到0.1%左右。

另一件需要注意的事情是,操作系统可能会在重新启动期间清理你的/tmp文件夹,所以即使PHP不会这样做。


答案 2

上次我查看了源代码,每次调用session_start()“掷骰子”,可以这么说,使用除数和概率。如果命中,则会从目录中删除早于 的所有文件。我忘记了它是否使用了文件的修改或访问时间,尽管这在正常的curcumstance中并不重要,因为php在脚本执行结束时默认会覆盖会话文件,因此mod和访问时间几乎总是应该非常接近。session.save_pathsession.gc_maxlifetime

// Rough psuedo code of how php's session_start() function works regarding garbage collection.
function session_start() {
    $percentChanceToGC = 100 * ini_get('session.gc_probability') / ini_get('session.session.gc_divisor');
    $shouldDoGarbageCollection = rand(1, 100) < $percentChanceToGC;
    if ($shouldDoGarbageCollection) {
        $expiredCutoffTime = time() - ini_get('session.gc_maxlifetime');
        foreach (scandir(ini_get('session.save_path')) as $sessionFile) {
            if (filemtime($sessionFile) < $expiredCutoffTime) {
                unlink($sessionFile);
            }
        }
    }

    // ... rest of code ....
}

我不知道如果你想让他们至少存活6个月,你最终会有多少会话文件。考虑到php可能需要一段时间才能统计数千个文件以确定它们的年龄。也许可以考虑使用此数据进行持久存储的其他选项。或者,您可以禁用php gc,然后运行cron作业来删除过时的会话文件。否则,1%的请求将触发gc并必须等待php;换句话说,它可能会滞后。


推荐