在磁盘中存储会话对我来说非常缓慢和痛苦.我的流量非常高.我想在高级PHP缓存中存储会话,我该怎么做?
_ttl = $def['lifetime']; if (isset($params['ttl'])) { $this->_ttl = $params['ttl']; } if (isset($params['lock_timeout'])) { $this->_lockTimeout = $params['lock_timeout']; } session_set_save_handler( array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destroy'), array($this, 'gc') ); } public function open($savePath, $sessionName) { $this->_prefix = 'BSession/'.$sessionName; if (!apc_exists($this->_prefix.'/TS')) { // creating non-empty array @see http://us.php.net/manual/en/function.apc-store.php#107359 apc_store($this->_prefix.'/TS', array('')); apc_store($this->_prefix.'/LOCK', array('')); } return true; } public function close() { return true; } public function read($id) { $key = $this->_prefix.'/'.$id; if (!apc_exists($key)) { return ''; // no session } // redundant check for ttl before read if ($this->_ttl) { $ts = apc_fetch($this->_prefix.'/TS'); if (empty($ts[$id])) { return ''; // no session } elseif (!empty($ts[$id]) && $ts[$id] + $this->_ttl < time()) { unset($ts[$id]); apc_delete($key); apc_store($this->_prefix.'/TS', $ts); return ''; // session expired } } if (!$this->_lockTimeout) { $locks = apc_fetch($this->_prefix.'/LOCK'); if (!empty($locks[$id])) { while (!empty($locks[$id]) && $locks[$id] + $this->_lockTimeout >= time()) { usleep(10000); // sleep 10ms $locks = apc_fetch($this->_prefix.'/LOCK'); } } /* // by default will overwrite session after lock expired to allow smooth site function // alternative handling is to abort current process if (!empty($locks[$id])) { return false; // abort read of waiting for lock timed out } */ $locks[$id] = time(); // set session lock apc_store($this->_prefix.'/LOCK', $locks); } return apc_fetch($key); // if no data returns empty string per doc } public function write($id, $data) { $ts = apc_fetch($this->_prefix.'/TS'); $ts[$id] = time(); apc_store($this->_prefix.'/TS', $ts); $locks = apc_fetch($this->_prefix.'/LOCK'); unset($locks[$id]); apc_store($this->_prefix.'/LOCK', $locks); return apc_store($this->_prefix.'/'.$id, $data, $this->_ttl); } public function destroy($id) { $ts = apc_fetch($this->_prefix.'/TS'); unset($ts[$id]); apc_store($this->_prefix.'/TS', $ts); $locks = apc_fetch($this->_prefix.'/LOCK'); unset($locks[$id]); apc_store($this->_prefix.'/LOCK', $locks); return apc_delete($this->_prefix.'/'.$id); } public function gc($lifetime) { if ($this->_ttl) { $lifetime = min($lifetime, $this->_ttl); } $ts = apc_fetch($this->_prefix.'/TS'); foreach ($ts as $id=>$time) { if ($time + $lifetime < time()) { apc_delete($this->_prefix.'/'.$id); unset($ts[$id]); } } return apc_store($this->_prefix.'/TS', $ts); } }
从理论上讲,您应该能够编写一个自定义会话处理程序,它使用APC为您透明地执行此操作.然而,我实际上在五分钟的快速搜索中找不到任何真正有希望的东西; 大多数人似乎都在使用APC进行字节码缓存并将其会话放在memcached中.
简单地将/ tmp磁盘(或者,无论PHP会话文件存储在何处)放到RAM磁盘上,tmpfs
或者ramfs
也会产生严重的性能提升,并且将是一个更加透明的开关,零代码更改.
性能增益可能会显着降低,但仍然会比磁盘上的会话快得多.
我试图通过提供100分作为赏金来引诱更好的答案,但没有一个答案真的令人满意.
我会聚合推荐的解决方案,如下所示:
APC实际上不能用作会话存储,因为APC没有允许正确锁定的机制,但是这种锁定对于确保在写回之前没有人改变最初读取的会话数据是必不可少的.
底线:避免它,它将无法正常工作.
可能有许多会话处理程序.检查的输出phpinfo()
在Session
为"注册保存处理程序"一节.
开箱即用,但出于显而易见的原因需要安装为RAM磁盘的文件系统.
在mm
启用PHP编译时可用.这是建在窗户上.
PHP为此提供了专用的会话保存处理程序.需要安装memcache服务器和PHP客户端.根据安装的两个memcache扩展中的哪一个,可以调用memcache
或使用保存处理程序memcached
.