Как хранить сеансы PHP в кэше APC?

Хранение сессий на диске очень медленно и болезненно для меня. У меня очень высокий трафик. Я хочу сохранить сеанс в Advanced PHP Cache, как я могу это сделать?

Я пытался заманить лучшие ответы, предложив 100 баллов в качестве щедрости, но ни один из ответов не был действительно удовлетворительным.

Я бы обобщил рекомендуемые решения следующим образом:

Использование APC в качестве хранилища сеансов

APC нельзя реально использовать в качестве хранилища сеансов, потому что для APC нет механизма, который позволяет правильно блокировать, но эта блокировка необходима, чтобы никто не изменял первоначально прочитанные данные сеанса перед тем, как записать их обратно.

Итог: избегайте этого, это не сработает.

альтернативы

Может быть доступно несколько обработчиков сеансов. Проверьте вывод phpinfo() в разделе Session для «Зарегистрированных обработчиков сохранения».

Файловое хранилище на RAM-диске

Работает из коробки, но по какой-либо причине требуется файловая система, смонтированная как RAM-диск.

Общая память (мм)

Доступно, когда PHP скомпилирован с включенным значением mm . Это встроено в окна.

Memcache (д)

Для этого PHP имеет специальный обработчик сохранения сеанса. Требуется установленный сервер memcache и клиент PHP. В зависимости от того, какая из двух расширений memcache установлена, обработчик сохранения называется memcache или memcached .

 <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } не <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } этот <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } не <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } не <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } этот <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } не <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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); } } не <?php // to enable paste this line right before session_start(): // new Session_APC; class Session_APC { protected $_prefix; protected $_ttl; protected $_lockTimeout = 10; // if empty, no session locking, otherwise seconds to lock timeout public function __construct($params=array()) { $def = session_get_cookie_params(); $this->_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 , также имело бы серьезный прирост производительности и было бы намного более прозрачным переключателем с нулевыми изменениями кода.

Увеличение производительности может быть значительно меньше, но оно будет значительно быстрее, чем на дисковых сеансах.

Храните его в файлах cookie (зашифрованных) или MongoDB. APC на самом деле не предназначена для этой цели.

Вы можете хранить ваши данные сеанса в общей памяти внутри PHP.

 session.save_handler = mm 

Но он должен быть доступен: http://php.net/manual/en/session.installation.php

Еще одно хорошее решение – хранить PHP-сессии в memcached

session.save_handler = memcache

Явное закрытие сеанса сразу после сеанса Запуск, открытие и запись должны решить проблему блокировки в ответе Unirgy (где доступ к сеансу всегда циклический (start / open-write-close). Я также представлю второй класс – APC_journaling или что-то подобное, используемое совместно с сеансами будет в конечном счете лучше … Сессия начинается и записывается с уникальным внешним идентификатором, назначенным каждому сеансу, этот сеанс закрыт, и журнал (массив в кэше apc через _store & _add) открывается / создается для любые другие записи, предназначенные для перехода на сеанс, которые затем могут быть прочитаны, подтверждены и записаны на сеанс (идентифицированный этим уникальным идентификатором!) в apc при следующей удобной возможности.

Я нашел хорошее сообщение в блоге. Объясняя, что блокирующий хаос Sven ссылается, происходит от блокировки сеанса до его закрытия или завершения скрипта. Сессия, которая немедленно закрывается, не препятствует чтению только записи. http://konrness.com/php5/how-to-prevent-blocking-php-requests – ссылка на сообщение в блоге. Надеюсь это поможет.

Кэширование внешних данных в PHP

Ссылка на учебник – http://www.gayadesign.com/diy/caching-external-data-in-php/

Как использовать кэширование APC с помощью PHP

Ссылка на учебник – http://www.script-tutorials.com/how-to-use-apc-caching-with-php/