Хранение PHP сессий в memcached: испытание на production сервере

// Июль 22nd, 2010 // Memcached, PHP, Zend Framework

Сегодня на работе выкатили свежую версию проекта на production-сервер. Посмотрели, потестили под одним юзером, всё нормально. Но потом наштестировщик, обнаружил, что постоянно начали отваливаться сессии, часто происходила подмена сессий, т.е. когда человек логиниться, то в его сессии лежат данные другого пользователя, а именно того, кто залогинился ранее.


Я пробовал исследовать проблему со всех сторон, нашел, что ошибка возникает, только когда для хранения сессий используется ZendExtra_Session_SaveHandler_Memcached. Когда же используется Zend_Session_SaveHandler_DbTable и сессии хранятся в бд, то всё нормально. Поискав по интернету, понял, что такая проблема возникает не только у меня.
Некто minorgod пишет:

I’m trying to track down a rather hard to duplicate bug on a web app where the sessions are occasionally getting lost when a user submits a request or reloads a page. Sessions are being stored in memcached on a different machine from the web server (the same machine that hosts the MySQL server). It doesn’t seem to have anything to do with what page a user is on, it just seems like the sessions are getting lost randomly between requests sometimes. I’ve never been able to catch it in my debugger on the rare occasion it happens to me, but I’ve heard that setting session_regenerate config to 0 can help, so I did that already on the production site. I’m wondering if anyone else has any advice. So I was thinking that maybe there’s an intermittent communication probelm with the memcached server. I’ve also heard that memcached has a limit of 1MB per cache entry, so maybe my sessions are simply growing too large sometimes? In either case I wonder if using APC would solve the problem. I’m almost tempted to switch back to file-based caching if I weren’t afraid of bringing the whole site to a crawl (it’s a rather high traffic site). I’m considering switching all my session storage to the local APC cache and am currently testing this on a beta version of the site while I wait to hear if turning off session_regenerate did the trick on the live site. I’m just looking for any other advice or hints anyone can think of to help me solve this problem.

На что получает закономерный ответ, что хранить сессии в memcached плохо, т.к. он не гарантирует хранение, и данные с сессиями могут быть вытеснены в любой момент:

Storing sessions in memcache is a pretty bad idea, because of one particular feature of memcache: When the memory allocated to memcache fills up, memcache will start deleting the oldest items in order to make room for the new data you are adding. Effectively, this makes memcache totally unreliable in high-traffic situations. APC will have the same issue.
If you want to handle lots of traffic and still maintain lightweight sessions, use signed cookies.

Но с помощью хитрой настройки ему удается победить проблему:

Thanks for the info Shadowhand….I just came back to the forum to see if anyone had replied to this thread since I didn’t get any email notifications about replies, otherwise I would have replied sooner. Anyway, I tried switching to storing sessions in APC, and like you said it was no better, in fact it was about 100x worse…losing sessions every few requests.. So then, I switched back to memcached and turned off session regeneration in my session config file and it seems to have solved all the problems. We also increased the memory available to memcached on our memcached server. I haven’t had a single complaint of a lost session in almost 2 weeks now and our traffic is still fairly heavy.

I’ve never used signed cookies for session storage (or anything else) and am not sure if our session data is too big for cookies or not, but it seems like that would mean sending all the session data to the browser on every request, which seems like a major bandwidth waste depending on how big the session data is. I just looked at some session files in the file cache and data files appear to be anywhere from 500bytes to 3K.

File-based session caching always seems to work great for me. I didn’t see any major performance impacts on my test site, but I’m afraid file-based sessions would be too slow for use on our live server. Do you have any info on just how fast/slow file based caching is compared to other session storage mechanisms such as storing sessions in MySQL. I’ve searched the web for comparisons, but I can’t find anything with relevant info. I’d love to see some benchmarks comparing the speeds of Kohana’s file-based caching versus memcached versus mysql versus native PHP sessions. But for now, it seems the problem is solved so I’m not going to switch to something else unless we start losing sessions again. I think there should be a note in the Kohana cache library documentation that mentions turning off session regeneration if you’re storing sessions in a RAM-based cache such as memcached or APC.

Мне она, к сожалению не помогла, или применял я её не так. Возможно, кстати, сказалось увеличение объема памяти виртуальнйо машины с memcached. У нас был 1Гб, потом сделали 1,5Гб, теперь 2Гб. Но ведь, по идее, должно было стать лучше, а после этого появились проблемы.

Резюмируя могу сказать следующее:

  • Хранить сессии в memcached плохо, т.к. они могут отвалиться в любой момент
  • Избажать этого по-идее поможет увеличение объема памяти, выделенной memcached
  • Можно также попробовать хрнаить сессии в /dev/shm (tmpfs) используя NFS. Говорят, нормально работает.
  • Хранить сессии в MySQL но использовать Memmory storage engine. Но тут встает вопрос с репликацией. Именно так мы пока и сделали.
CREATE TABLE IF NOT EXISTS `session` (
`id` char(32) NOT NULL DEFAULT »,
`modified` int(11) DEFAULT NULL,
`lifetime` int(11) DEFAULT NULL,
`data` varchar(2048) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `session` (  `id` char(32) NOT NULL DEFAULT »,  `modified` int(11) DEFAULT NULL,  `lifetime` int(11) DEFAULT NULL,  `data` varchar(2048) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=MEMORY DEFAULT CHARSET=utf8;

Updates:

Возможно у нас старая версия memcached (3.0.1) и проблема в этом, в версии 3.0.4 реализована поддержка блокировки сессий.

— Added session locking to avoid concurrency problems with AJAX apps

Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


6 Responses to “Хранение PHP сессий в memcached: испытание на production сервере”

  1. […] Сессии в пямяти мы уже храним, а если хрнаить там картинки через mysqlfs может еще прирост получится? // […]

  2. Pomoshnik:

    Хороший блог очень понравился буду следить за вашими новостями.

  3. […] В MySQL есть несколько движков хранения данных. Среди них есть «MEMORY», который хранит данные в RAM. Таблицу с таким движком можно использовать, например, для хранения сессий. ОБновляются они часто, если все сотрутся – это не будет большой проблемой. Тут некотоыре могут возразить, что можно хранить сессии в Memcached. Им я советую прочитать мою статью на эту тему. […]

  4. Alex:

    Use OS memory disk and mount it to session save path — this is the best simple solution

Комментировать