Использование memcached для хранения сессия. Какие могут быть проблемы?

KhmelevskyY

Новичок
Использование memcached для хранения сессия. Какие могут быть проблемы?

Здравствуйте.
Решил хранить сессии не в файловой системе, а в memcached. Сессии используются только для идентификации пользователя, в принципе, там будет хранится только логин пользователя и его user_agent. Вроде проблем быть не должно, принцип такой: запускает отдельный демон мемкешд, этот демон будет использоваться исключительно для сессий, делается это с той целью, чтобы кеша всегда хватало и данные не затирались (людей не разлогиневалоне ни с того, ни с сего) и если будет несколько бэкендов, чтобы было одно место хранения сессий. При таком подходе есть какие-то невидимые грабли, люди которые реализовывали данную возможность поделитесь опытом, не будут ли данные затираться ни с того ни с сего?
 

dimagolov

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

KhmelevskyY

Новичок
Нашел статью http://www.softwareprojects.com/resources/programming/t-memcached-for-php-sessions-1654.html , где автор предлагает для подстраховки использовать базу данных. То есть, при каждой аутентификации данные сессии заносятся в базу данных и мемкешд. При считывании, проверяется, есть ли сессия с таким идентификатором в мемкешд, если есть - возвращает ее, иначе считывает ее с базы данных и повторно заносится в мемкешд.

Такой подход защитит от случайной потери данных сессий, но увеличиться нагрузка на субд при аутентификации пользователей, так как придется писать данные еще и в базу. Хотя, по идее, можно этим пренебречь, так как пользователь раз "запомнился", и все. Получается операций записи будет несоизмеримо меньше, чем операциями чтения, хотя в любом случае это увеличит нагрузку на субд. Стоит ли использовать такой подход? Или может не заморачиваться по этому поводу и хранить сессии только в мемкешд, и только следить чтобы места, зарезервированного под демон хватало для хранения сессий, чтобы не было вытеснения? Какой алгоритм используете вы в своих highload проектах?

-~{}~ 12.02.10 20:58:

Автор оригинала: dimagolov
есть у пхп стандартный механизм хранения сессия в memcached.
знаю про стандартный механизм хранения сессия в memcached.
Автор оригинала: dimagolov
разлогинивание решается не сессией, а автоматической авторизацией по кукам, сессии жить дольше 24 минут не должны в принципе и проблема с вытеснением из кеша не должна стоять.
непонятно, я могу сделать чтобы сессия у меня жила месяц, например, и не вижу в этом проблемы,а в куках хранить только ее идентификатор. просто и удобно ( http://habrahabr.ru/blogs/webdev/40714/ )
 

dimagolov

Новичок
KhmelevskyY, ты %уем девушку удовлетворяешь? А омлет им взбиваешь? Нет? Почему? Движения почти те же самые?

Сессионная кука живет в браузере до его закрытия. Рассчитывать не то, что значительное кол-во пользователей будут держать месяцами открытый браузер, это как омлет %уем взбивать. А если на это не рассчитывать, то долгий срок хранения сессионных данных на сервере становится совершенно бессмысленным. Учти, что с каждым обращением пользователя к сайту, сессия обновляется и ей опять вытеснение из кеша не грозит. Раз так, то и велосипедов с "подстраховкой" придумывать нету смысла. Для долговременного хранения используй себе БД, никто не запрещает, но мешать их с сессией не нужно.
 

fixxxer

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

Можно немного пропатчить memcached для продление жизни ключей при каждом get-е.

Примерно так:

http://symbi.org/misc/memcached-1.2.2-autoprolongate.patch

Смысл в том, что при определенном взведенном бите flags, при очередном get-е автоматически продлевается время жизни ключа.
Если используется библиотека, которая flags не выпячивает наружу, а использует для своих целей (как pecl/memcached), соответственно, тоже нужно патчить для поддержки этого режима.

Конечно, это не спасает от вытеснения сессионных данных при нехватке памяти в slab-е, но это тоже можно решить использованием отдельного (отдельных) инстансов memcached под сессии.

Дублировать в базе как-то жирно :) если речь идет о хайлоаде. А если высоких нагрузок нет, а нужно просто обеспечить sharing сессии между веб-мордами - дык можно и в базе хранить. Или, в конце-то концов, делать запись в memcached _каждый раз_, независимо от того, изменились ли сессионные данные.

Как это интегрировать со стандартным php-шным механизмом хранения сессий в memcached, не знаю (хотя, очевидно, либо пропатчить, либо написать свои хендлеры) - я вообще не люблю стандартный механизм сессий и его всячески избегаю, хотя многие мне говорят что это и необоснованно. =)
 

Alexandre

PHPПенсионер
Дублировать в базе как-то жирно
это просто бред, хранить сессии в БД. Это делали когда-то давно (в эпоху пхп3/4), когда не было memcache
как один из вариантов, если боитесь вытеснение сессий - хранить сессии в редисе, хотя в наше время при цене на память - можно себе позволить и мемкеш.
 

fixxxer

К.О.
Партнер клуба
>> как один из вариантов, если боитесь вытеснение сессий - хранить сессии в редисе

Зачем? memcached можно сказать, чтобы он не вытеснял, а возвращал ошибку в случае нехватки памяти:

$ memcached -h | grep error
-M return error on memory exhausted (rather than removing items)

Это всяко лучше, чем начать люто, бешено свопиться.

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

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

dimagolov

Новичок
fixxxer, можно заранее оценить какой объем памяти понадобиться для хранения сессионных данных. хотя бы приценившись на файлах при рабочей нагрузке. ну и дать запас.
 

KhmelevskyY

Новичок
Автор оригинала: dimagolov
KhmelevskyY, ты %уем девушку удовлетворяешь? А омлет им взбиваешь? Нет? Почему? Движения почти те же самые?

Сессионная кука живет в браузере до его закрытия. Рассчитывать не то, что значительное кол-во пользователей будут держать месяцами открытый браузер, это как омлет %уем взбивать. А если на это не рассчитывать, то долгий срок хранения сессионных данных на сервере становится совершенно бессмысленным. Учти, что с каждым обращением пользователя к сайту, сессия обновляется и ей опять вытеснение из кеша не грозит. Раз так, то и велосипедов с "подстраховкой" придумывать нету смысла. Для долговременного хранения используй себе БД, никто не запрещает, но мешать их с сессией не нужно.
Уважаемый, то ли я вас не понимаю то ли вы ошибаетесь. Выдержка с php.net
PHP:
  session.cookie_lifetime  integer     
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser. 
The value 0 means "until the browser is closed." Defaults to 0.
Вот я установил время жизни куки у пользователя месяц.
PHP:
ini_set('session.cookie_lifetime', 2073600);
Не вижу в общем пролемы...

Автор оригинала: fixxxer
Можно немного пропатчить memcached для продление жизни ключей при каждом get-е.
Супер, не знал. Сто процентов буду патчить, спасибо за наводку.

Автор оригинала: fixxxer
Конечно, это не спасает от вытеснения сессионных данных при нехватке памяти в slab-е, но это тоже можно решить использованием отдельного (отдельных) инстансов memcached под сессии.
так и собирался делать

Автор оригинала: Alexandre
это просто бред, хранить сессии в БД. Это делали когда-то давно (в эпоху пхп3/4), когда не было memcache
как один из вариантов, если боитесь вытеснение сессий - хранить сессии в редисе, хотя в наше время при цене на память - можно себе позволить и мемкеш.
Автор оригинала: fixxxer
Зачем? memcached можно сказать, чтобы он не вытеснял, а возвращал ошибку в случае нехватки памяти:
$ memcached -h | grep error
-M return error on memory exhausted (rather than removing items)
Это всяко лучше, чем начать люто, бешено свопиться.
Но я себе не очень представляю, как обрабатывать такую ситуацию в случае нехватки памяти.
Лучше мониторить соотношения hit/miss, выпадение из общей статистики покажет, что надо доставлять память.
Спасибо за советы, помогли мне определится. Будет использоваться только memcached, отдельным инстансом, в случае нехватки памяти будет возвращать ошибку. Обязательно будут мониториться соотношения hit/miss и кол-свободной памяти забиксом, например. Единственное, что немного смущает, если использование памяти будет доходить до максимума, придется перезапускать мемкеш с увеличенным количеством выделенной для него памяти, соответственно все данные потеряются и пользователям придется заново перелогинится.
Хотя, если это так критично, можно запустить новый инстанс на другом порту с увеличенным количеством используемой памяти, перелить все данные с старого кеша в новый и в приложении изменить настройки подключения к memcached. Если и будут потери, то минимальные.

Всем спасибо!
 

fixxxer

К.О.
Партнер клуба
ini_set('session.cookie_lifetime', 2073600);
Не вижу в общем пролемы...
Кука-то, может, и не сдохнет, а сессионные данные наверняка.

Так что лучше заводить отдельную куку для авторизации по ней, если сессионной нет или сессия сдохла. Класть туда хоть бы и что-то типа json_encode(array($user_id, md5(SALT . md5($password))). Хотя вместо password я предпочитаю отдельное поле со случайно сгенеренной при регистрации строкой.
 
Сверху