我一直使用 cookie 和数据库实现会话处理,而不是通过 php 的 ext/session api。
我使用行锁和必要的隔离来做到这一点。我的方法从未遇到过并发问题,尽管我认为我没有足够的流量来暴露此类问题。
我最近被告知 ext/session 比人们想象的要多,而且它比我想象的要复杂得多,这让我质疑我的方法。
您能否提供并发请求的示例以及扩展/会话解决数据不一致的方式?
通过其基于文件的会话,ext/session
在打开的会话上以文件锁定的形式实现并发保护。文件锁会阻止任何其他打开会话文件的尝试,并且在会话关闭之前(在请求结束时或使用 session_write_close
显式(不会释放锁。
这有效地序列化了对会话的访问,在会话和一次写入的整个会话之间(而不是作为单独的值(,应该不存在不一致数据的问题。
如果要使用自定义会话实现实现正确的锁定和隔离,则执行的操作ext/session
执行的操作相同,但使用不同的后备存储。
如果要使用 PHP 的 SessionHandlerInterface
和 session_set_save_handler
实现自定义会话处理程序,则可以通过在open
实现中执行锁定并将锁定作为close
实现的一部分来释放来实现这一点。
对于并发请求,逻辑流将如下所示:
Connection 1 Connection 2
session open session open - blocks
session read //blocked
// do stuff //blocked
session write //blocked
session close //blocked
session open returns
//reset of session handling as per normal
由于Connection 2
在尝试打开会话后(以及在接收会话数据之前(被完全阻止,因此它无法采取任何可能扰乱有权访问会话数据的其他连接中的数据的操作。
请注意,自定义会话处理程序必须正确实现锁定,否则可能会由于多次并发访问会话数据而获得不一致的数据。这种不一致将采取何种形式将取决于自定义处理程序如何实现读取和写入会话数据的确切详细信息。