Pull to refresh

Comments 75

Мысль интересная, но лично я бы подошел к проблеме счётчика по другому. При инициализации сессии я бы создал переменную, а потом использовал бы такое:
$memcache->increment('user_visit_counter'.$userid);
Счетчик был взят для примера, чтобы наглядно воспроизвести потерю данных.
тоже заморачивался с сессиями в memcache, при интенсивной работе данные теряются. Писал свою реализацию, вводил отдельную переменную в которой был флаг блокировки сесии, но это всё равно не помогало. Решил отказаться пока от сессий на memcache
Memcache подходит больше для readonly сессий и счётчиков, т.к. у него есть increment/decrement, которые гарантировано без потери данных увеличат/уменьшат счётчик.

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

Систему нужно строить изначально так, что бы сессия была больше readonly, с редко обновляемыми данными. Хранить, к примеру, корзину товаров в сессии, которая в memcache — явно плохая идея, такое нужно хранить в базе.
Это не решает проблему уничтожения данных, или вы хотите в ручную перебирать данные, сравнивая версию сессии из скрипта и версию сессии из memcache и пробовать решать конфликты в коде?

Тогда уж надо примерно так:
Имеем объект, который имеет API для обновления данных в сессии и запоминает все изменения (он хранит оригинальные данные) и при закрытии сессии считывает то, что находиться в memcached на текущий момент и сравнивает с оригинальными значениями. Если данные расходятся — обновляет, а потом уже применяет к ним изменения из скрипта и всё это сохраняет. По крайней мере таким извращённым способом мы избежим долгих блокировок, хотя лично мне такой вариант не очень нравиться.

Моё имхо остаётся таким-же, как и было — если нам нужно что-то обновить в memcache — то блокируем, читаем, обновляем, разблокируем в том месте, где это надо, а не глобально на весь скрипт (механизм блокировки каждый придумывает сам).

Данная тема весьма непроста и подойти к ней можно кучей способов и каждый из них имеет недостатки. Идеального решения просто нет.
я это написал касательно файловых сессий, чтобы другим потокам скрипта не пришось долго ждать, можно закрыть сессию по завершении работы с ней.
Искажена идея memcached — хранение кэша, а не данных.
Идея memcached в том что бы хранить в памяти что угодно. В контексте PHP и JAVA удобно хранить объекты. Но это могут быть и бинарные данные, и все что угодно если это выгоднее хранить в памяти чем на диске.
> memcached is a high-performance, distributed memory object caching system

Memcached не гарантирует сохранность данных, это не система хранения данных, а система кэширования. Почуствуй разницу, username.

Хранить сессии, на сколько бы они временными не были, в memcached — ошибка проектирования.

… кэширования чего? Не данных ли?
Кэш тоже данные, продублированные и положенные в доступное место. И там и там храняться данные, насколько я понимаю. Вопрос сохранности и целостности а так же как именно вы их собираетесь использовать вопрос скорее реализации чем дизайна. А данным в сессии быть, поскольку memcached is a high-performance, DISTRIBUTED memory object caching system
Кэш — не дублирование данных. Учите матчасть, в общем. Разговор пустой.
Определите понятие кэш в вашем понимании
ru.wikipedia.org/wiki/Кэш

Кэш (англ. cache[1]) — промежуточный буфер с быстрым доступом, содержащий копию той информации, которая хранится в памяти с менее быстрым доступом, но с наибольшей вероятностью может быть оттуда запрошена. Доступ к данным в кэше идёт быстрее, чем выборка исходных данных из медленной памяти или их перевычисление, что делает среднее время доступа короче.

Доступ к чему идет быстрее? Да как они посмели не выучить матчасть… А еще словари пишут
К кэшу доступ быстрее. Для того и кэш. Но кэш — не хранилище, еще раз повторюсь.
Цитирую
Доступ к данным в кэше идёт быстрее, чем выборка исходных данных из медленной памяти или их перевычисление, что делает среднее время доступа короче.
Конец цитаты
Ему уже нечего доказывать, по нику понятно что он в танке :)
Вот смотрел я на этот диалог и думал. На мой взгляд, оба случая разделяет ответ на один деликатный вопрос. Что делает memcached, когда у него заканчивается память — удаляет старые данные, или всётаки не принимает новых?

Если не принимает новых, то можно использовать Memcached как хранилище. Если же удаляет старые данные, то только как кеш.
Удаляет, я пытаюсь донести что в кэше тоже храняться данные как и в базе данных как и на диске, как и в файловой системе. А КЭШ это не сущность это механизм хранения. Данных.
memcache — это кеш. если память кончается, удаляются самые старые записи:

FAQ по мемкешу:
«If the server is out of memory, expired slabs are replaced first, then the oldest unused slabs go next.»

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

«How is memcached redundant?

It's not! Surprise! Memcached is a caching layer for your application. It is not designed to have any data redundancy. If a node loses all of its data, you should still be able to fetch it all again from the source. Especially be careful that your application can survive losing memcached instances. Don't write awful queries and expect memcached to be a fix-all! If you're worried about having too much of a spike in database usage during failure, you have some options. You can add more nodes (lessen impact of losing one), hotspares (take over IP address when down), etc.»

www.socialtext.net/memcached/index.cgi
Весь этот пост пронизан мудростью :) Начиная с сессий в мемкэшед, заканчивая реализацией слиплока. А здесь ещё вы убеждаете что 'идея мемкэшед в том чтобы хранить в памяти что угодно'.
Да, не заметил :)

Прекращаю кормить тролля…
Да, храни кэш в кэше и базу данных в базе данных :)
Такие вещи решаются помощью инкремента и декримента. Хранить в сессии такую информацию как-то не логично. Лучше мемкеш-хендлера пока ничего не придумали. Как вы обойдетесь без него на высокой нагрузке в ситуации, когда серверов больше, чем один. Save handler реализованный через БД не прокатит, так как база загнется.
Чем то напоминает присказку о микроскопе и гвоздях…
один из больших плюсов использования memcache в качестве хендлера для сессий — отсутствие блокировки. а тут некоторые предлагают от этого плюса отказаться, введя ручную блокировку. это не есть гут.
Использую memcached для хранения cache в symfony. Многое спорно, очень часто функция set возвращает false и ни привета не ответа, что происходит не ясно. Как-то странно работает. Наверное на 1000 memcached серверов оно не так заметно но на 3 как у меня что-то не рабоатет как надо.

В реализации PECL memcache класса нет никаких способов идентификации ошибок. Щас сижу и не могу понять почему половина кэша не сохраняется :-(

Может кто что подскажет. У меня 3 сервера Memcache и на доном из них крутится symfony. Под Memcache выделено 2Gb памяти но используется только по 200Mb. В чем может быть проблема с сохранением кэша? И как ошибки то выловить?

Кто как кстати мониторит состояние memcache? Я юзаю www.cacti.net/
А можно поподробнее о настройке мониторинга?
да, я нашел инфу в инете, но к сожалению по этой ссылке битые линки на шаблоны :(
Только не совсем понятно, как с указанным выше темплейтом мониторить несколько демонов memcached на одной машине (висящих на разных портах).
а зачем отдельным процессом считать такие данные?

у меня все проходит через index.php и подобных проблем нету.
А здесь тоже все данные проходят через один файл counter.php, однако, при наличии двух конкурирующих запросов возможны проблемы. В примере я постарался добиться максимальной воспроизводимости. Если уменьшить время в usleep, то поймать мемент потери данных гораздо сложнее.
зачем вообще разделять?

єсть запрос на index.php сгенерировал страницу + в базу закинул информацию где был, обновил сессию конец роботы.
я кажется понял — ето просто пример чтоб продемонстрировать как можно потерять данные.

хотя данную схему приєма статистических данных я б не использовал.
А ещё пхпшники удивляются почему их называют быдлокодерами :)
— слиплок! ещё и на пхп! ещё и с мемкэшд!
— мемкэшд для хранения данных
— каждый php файл — отдельный процесс
Кажется Вы вопроса так и не поняли, меня интересуєт именно почему нужно было процесс сбора таких данных распараллеливать?

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

Попрошу также без таких слов я не из тех програмеров что пишут тока на одном языке.
Если вы про два ифрэйма, то видимо чтобы продемонстрировать проблему когда у человека заела кнопка f5 :) Просто я ваш коммент так прочитал, что связались слова index.php и отдельный процесс.
А про быдлокодинг — это больше даже не к пхп, а к данной страничке на хабре :) Я даже удивился что столько людей отплюсовало подобный пост и подумалось, что либо они не читали что там внутри, либо — а про быдлокодинг :)
а что если хранить сессии в /dev/shm? блокировка файлов вроде бы поддеживается
На сколько я понял, /dev/shm (tmpfs) сама по себе доступна только на одной машине. Для многосерверной разработки придётся поднимать, например, nfs, которая почти не поддерживает блокировки. Либо другую сетевую файловую систему.
очень даже поддерживает, у нас как раз сессии на nfs
и как работает? насколько нагруженный проект?
работает нормально, уже несколько лет.

ну и проект довольно нагруженный — бесплатный хостинг, примерно 9 млн. пользователей (на nfs хранятся пользовательские сессии)
дело в том что мы наоборот активно боремся с NFS… когда сервер начинает тормозить, клиенты намертво подвисают, и ничего не поделать.

Когда я спрашивал про нагруженность, имел в виду скорее интенсивность записи сессий
да, я понимаю что Вы имели в виду, просто другого показателя интенсивности записи сессий привести не могу.

Может я неясно выразился, но все сессии 9 миллионов пользовательских сайтов хранятся в одном месте. Не знаю правда какой процент сайтов использует сессии.
там ограничена память, вроде в РНР можно тольл 32 Мб, но я не уверен.
статья ни о чём. храню данные (в том числе сессии) в memcache. уже как год использую такую реализацию, проблем нет.
На счёт быдлокодеров не согласен, есть и умные люди. Но их мало, что огорчает :(
мне кажется тут нарушена сама идея мемкешд. мемкешд для промежуточных либо статических данных.
Сама по себе возможность модификации этих данных в параллельно происходящих рассчетах есть извращение над идеей.
Для односерверной конфигурации даже заморачиваться с memcached не стоит. Работать с файлами быстрее чем с memcached через сокеты. И гораздо быстрее будет хранить файлы сессий в диск в памяти (/dev/shm)

Memcached преднозначен для распределенных систем.
м, если в сессии не очень много данных, можно бы юзать таблицы типа MEMORY =)
приведите, пожалуйста, реальную ситуацию, в которой при выполнении скрипта происходит дважды одновременное (!!!) обращение к значению, хранящемуся в сессии. Просто не укладывается в голове, как же вообще такое может произойти?? А потому и проблема кажется надуманной.
Также нужно понимать, что последний «писатель» заносит актуальную информацию, и его не волнует, что кто-то из «читателей» получил ее раньше.
Вот как лично я столкнулся с параллельным выполнением.

Со страницы запускается загрузка большого файла и отображается прогресс бар загрузки. Обновляются данные примерно раз в секунду. Процесс идёт около 20 минут. На обработку аякс запроса в проекте необходимо было запускать сессию. Параллельно с этим открывается новое окно, в котором пользователь продолжает работать и часть данных должна оседать в сессии, если происходили одновременные запросы к серверу, то данные могли не сохраниться. Вот такая рабочая ситуация.
PS Сейчас за приёмку файлов и аплоад прогресс отвечает самописный сервер, который не затрагивает сессии.
PPS Не забывайте про медленные каналы, там очень интересно могут запросы приходить.
Юзер открывает страницу на которой Х ссылок. Просмотрев список быстро кликает средней кнопкой Y ссылок которые начинают открываться в фоне. Как отразится на сессии зависит от множества факторов, но шанс потери данных возрастает.
Здорово. Правда еще не в stable версии да и проблемы вытеснения из кэша не решит.
конечно статья отличная и исследовательская работа произведена качественно
но можно сессии хранить в shm — не пробовали?
и доступ быстрее и блокировка предусмотрена.
преимущество мемкеша — его можно посадить на отдельный сервер, и нет проблем масштабируемости
а shm все-таки живет на том же сервере что и РНР и ограничен физическим размером.
Вы сами ответили на свой вопрос. Могу добавить, что у проекта 8 машин, которым нужны общие сессии.
а про другое хранилище не думали?
я тут начал тарантула осваивать.
Для сессий то что надо: и сохраняемость есть как у редиса и скорость по утверждениям разработчиков выше редиса
Проект маленький. Прикручивать к нему монстров типа редиса смысла нет. Мемеш мал и достаточен. Нет смысла переделывать то, что работает и прекрасно справляется с задачей.
Могу добавить, что у проекта 8 машин. Проект маленький.

Я бы сказал не такой уж и маленький.
интересные масштабы 8 машин и маленький проект.

Участвовал в одном проекте, социалка среднего уровня, там было 4 сервера, они позиционируют себя как  HiLoad, 120-130К хостов. Так там использовали и мемкеш и редис и даже монгоДБ собирались использовать (не знаю как все закончилось...) Так что, на мой взгляд кол-во компонент не зависит от масштаба проекта.
Прикручивать к нему монстров типа редиса смысла нет

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

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

знаю что в некоторых проектах для хранения сессий используют редис;
в чем преимущество не знаю, но мемкеш все же немного пошустрее.
Sign up to leave a comment.

Articles