php数据加锁redis php redis锁( 四 )


session.gc_maxlifetime 指定过了多少秒之后数据就会被视为"垃圾"并被清除 。垃圾搜集可能会在 session 启动的时候开始( 取决于 session.gc_probability 和 session.gc_divisor) 。session.gc_probability 与 session.gc_divisor 合起来用来管理 gc(garbage collection 垃圾回收)进程启动的概率 。此概率用 gc_probability/gc_divisor 计算得来 。例如 1/100 意味着在每个请求中有 1% 的概率启动 gc 进程 。session.gc_probability 默认为 1 , session.gc_divisor 默认为 100 。
继续用我上面那个不太恰当的比方吧:如果我们把物品放在超市的储物箱中而不取走 , 过了很久(比如一个月),那么保安就要清理这些储物箱中的物品了 。当然并不是超过期限了保安就一定会来清理,也许他懒 , 又或者他压根就没有想起来这件事情 。
再看看两段手册的引用:
如果使用默认的基于文件的会话处理器,则文件系统必须保持跟踪访问时间(atime) 。Windows FAT 文件系统不行,因此如果必须使用 FAT 文件系统或者其他不能跟踪 atime 的文件系统,那就不得不想别的办法来处理会话数据的垃圾回收 。自 PHP 4.2.3 起用 mtime(修改时间)来代替了 atime 。因此对于不能跟踪 atime 的文件系统也没问题了 。
GC 的运行时机并不是精准的 , 带有一定的或然性 , 所以这个设置项并不能确保旧的会话数据被删除 。某些会话存储处理模块不使用此设置项 。
对于这种删除机制 , 我是存疑的 。
比如 gc_probability/gc_divisor 设置得比较大,或者网站的请求量比较大,那么 GC 进程启动就会比较频繁 。
还有,GC 进程启动后都需要遍历 Session 文件列表,对比文件的修改时间和服务端的当前时间 , 判断文件是否过期而决定是否删除文件 。
这也是我觉得不应该使用 PHP 自带的 files 型 Session 处理器的原因 。而 Redis 或 Memcached 天生就支持 key/value 过期机制的 , 用于作为会话处理器很合适 。或者自己实现一个基于文件的处理器,当根据 session_id 获取对应的单个 Session 文件时判断文件是否过期 。
为什么重启浏览器后 Session 数据就取不到了
session.cookie_lifetime 以秒数指定了发送到浏览器的 cookie 的生命周期 。值为 0 表示"直到关闭浏览器" 。默认为 0 。
其实,并不是 Session 数据被删除(也有可能是,概率比较小,参见上一节) 。只是关闭浏览器时,保存 session_id 的 Cookie 没有了 。也就是你弄丢了打开超市储物箱的钥匙(session_id) 。
同理,浏览器 Cookie 被手动清除或者其他软件清除也会造成这个结果 。
为什么浏览器开着,我很久没有操作就被登出了
这个是称为“防呆”,为了保护用户账户安全的 。
这个小节放进来,是因为这个功能的实现可能和 Session 的删除机制有关(之所以说是可能,是因为这个功能不一定要借住 Session 实现,用 Cookie 也同样可以实现) 。说简单一点 , 就是长时间没有操作,服务端的 Session 文件过期被删除了 。
一个有意思的事情
在我试验的过程中,发现了小有意思的事情:我把 GC 启动的概率设置为 100% 。如果只有一个访问者请求,该访问者即使过了很久(超过了过期时间)后才发起第二次请求 , 那么 Session 数据也还是存在的('session.save_path' 目录下面的 Session 文件存在) 。是的,明明就超过了过期时间 , 却没有被 GC 删除 。这时,我用另外一个浏览器访问时(相对于另一个访问者),这次请求生成了新的 Session 文件,而上一个浏览器请求生成的那个 Session 文件终于没有了(之前那个 Session 文件在 'session.save_path' 目录下面的消失了) 。

推荐阅读