Pull to refresh

Comments 72

Интересно — это самописный доклад или перевод? Если самописный, товам явно нужно тренировать свое умени формулировать мысли. потом учто просто бьет по ушам английский способ строить предложения. Обратный порядок слов и так далее. По-русски так не говорят. Поэтому и возник вопрос — не перевод ли это.
Нет, не перевод. Текст самописный. Насчет стиля согласен, буду стараться писать лучше. Спасибо.
программисты man'ы пишут на английском… вот и манера строить предложения :)
Хорошо, что с чужим языком ты знаком,
Но не будь во вражде со своим языком!

С. Маршак
Извините, а вы не смотрели вот это — code.google.com/p/memcached-tag/? Просто очень часто надо что бы значения удалялись сразу по нескольким ключам. Можно конечно самими организовать на бэкенде, но это медленнее чем если бы на уровне сервера было.

На тестовых данных вроде не плохо себя показывает, а вот на продакт пока боимся.
Эту штуку не смотрел, через пару-тройку постов в серии опубликую «наш» метод работы с тэгами, который не требует патчей (но требует больше операций get).

Подобных патчей к memcached было довольно много, этот — один из самых разумных. Покуда оно не войдет в стабильную ветку, пользоваться этим будет немного рискованно, как мне кажется (в силу того, что оно сильно завязано на ядро memcached и совместимость с последующими версиями под вопросом). Но тут каждый решает сам, конечно же.
спасибо за ответ. На своей стороне мы уже реализовали. но вот хочется на уровне сервера мемкэш попробовать.
Правильно боитесь, почитайте лучше у Котерова (если что, это автор МоегоКруга) его апгрейд для мемкешд. В описании он говорит, что ваше предложение работает, но периодически делает это криво.
Я читал у Котерова, более того, так получилось, что аналогичное с ним решение нам пришло в голову практически одновременно. Я уже рассказывал о своем варианте на конференции, а в следующих постах будет кусок, посвященный тэгированию.
насколько я помню котеров не автор МоегоКруга, он присоединился чуть позже.
А никто не знает как бороться с «миганием» демонов?
Например есть три сервера…
Жмем ф5- уже два
Еще раз жмем ф5 — три, один, три, ни одного, три и так далее
Ммм? Это о чем? И как мы смотрим на «мигающих демонов»?
$memcached->AddServer…

print_r(memcache_get_extended_stats($memcache_obj));

Возможно, проблемы с сетью, у addServer есть последний параметр — failure_callback, через него советую попробовать настроить логгинг в файл, например. Каждая запись там будет сетевой проблемой с конкретным серверов.
ну дык — когда виснет понятно и видно
а почему — нет
Сетевые проблемы — потери пакетов, например. Недостаточность пропускной способности и т. п. Просто измерить ping и потери иногда бывает достаточно ;)
пинг нормально — гигабит соединение без участия свича. те прямой кабель
как измерить потери — не знаю даже :(
Тем же пингом можно, интервал поменьше, потери он покажет. Если честно, я совсем не админ, так что тут, возможно, нужен «админский глаз». Если я прав про сетевые проблемы, конечно.
AddServer использует pconnect. Согласно Google вещь далеко не самая стабильная.
Здесь способ борьбы с ним

david-m.livejournal.com/993877.html

Можно попробовать что-то вроде
$conn = new Memcache;
if(!$conn->AddServer($ip, $port) and !$conn->pconnect($ip, $port))
throw new Exception(«Memcache connection error»);

Было бы интересно узнать результат.
Подправил

$conn = new Memcache;
if(!$conn->AddServer($ip, $port) and !$conn->AddServer($ip, $port))
throw new Exception(«Memcache connection error»);
Как не странно — работает!
Прекратили сервера отваливаться наконецто
Немного погуглил и выявил несколько вопросов которые было бы хорошо уточнить
1. Соединение с кешедом может упасть когда угодно
2.(Я пока не пробовал) Но если схитрить и в failure_callback сделать конект тудаже где упало — упадет весь ПХП
3. При addServer соединение не производиться до тех пор пока хэшер не решит залесть на частную ноду.
Получается что после старта нельзя проверить какие сервера живы(экстендед статусом) иначе это приведет к конекту ко всем серверам, что не есть гуд.
Хотя… наверное надо будет уменьшить лимиты памяти на демоны кешеда, но задублировать их.
Будет не три по гигу, а 6 по 500.
Вероятность отказа сильно меньше
Это все проблемы отсутствия полноценной реализации кетама в PHP.

www.lastfm.ru/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients
не впечатлила.

Сейчас пытаюсь смотреть в сторону libmemcached
tangent.org/
У нее большой плюс — с полпинка завелась в MySQL, через UDF полный доступ ко всем основным функциям.

Есть сомнения по совместимости с организацией кластера memcached в том же PHP.

Можно конечно привинтить ее в PHP
labs.gree.jp/Top/OpenSource/libmemcached-en.html
Смущает номер версии 0.1.0 и шалашики.

Соединение может пропасть когда угодно, это правда. Но интерфейс клиента прозрачный.

failure_callback не для пересоединения, конечно! Там есть таймауты на новую попытку коннекта и всё остальное. Надо искать причину рассоединения — их не должно быть по-хорошему.

Коннект ко всем серверам — это нормально, если они перзистенты. Какая разница? Потом всё равно с высокой вероятностью все понадобятся.
Данные «совсем нельзя потерять» нельзя хранить в memcached. Чему вы учите людей?
Почему же нельзя? Если есть кластер memcached серверов, можно ввести избыточное хранение — запись на несколько, чтение с любого. Понятие «нельзя терять» относительно, конечно.

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

Потеря данных возможна при любом способе хранения, речь идёт об относительной вероятности потери. И данные, которые имеет смысл хранить в memcached, всё равно можно разделить по нашему отношению из возможной потере.
Потому что есть множество условий при которых memcached начнёт освобождать buckets. Вы это никак не контролируете, а сессию пользователь потеряет.

Memcached работает на buckets, освобождает он их в порядке вхождения.
Не вхождения, а в обратном порядке «использования». Это раз. Освобождение зон в слабах, конечно, не контролируется, но при достаточном объеме кэширующей памяти и нормальном распределении размеров мы получим ситуацию, что сессия «живёт» ровно столько, сколько мы хотим.

Речь про потери идёт в двух ситуациях: потеря сервера и вытеснение ключа. Первое — решается избыточностью, второе — правильной настройкой/использованием. Конечно, если мы хотим положить в memcached 2 Гб сессий, а у нас всего 1 Гб — то будет вытеснение, но мы хотим от memcached того, что он не умеет ;)
Про обратный порядок использования пруфлинк, пожалуйста. Что такое <достаточный объём>? Какой объём достаточный? Я понимаю на винтах доступны сотни гигабайт, в памяти такого близко нет.

Про корзины (buckets) вы, кстати, ничего не сказали. Мне кажется или вы не знаете что это? Что будет, если у вас много данных по 16.1Кб вы знаете? Что память забъётся быстрее, чем вы ожидаете тоже знаете? Что потери в памяти могут достигать 50% тоже знаете? И что у вас нет никакого <запаса>, если вы расчитали, что ваши данные могут достигать 1Гб, а у вас их всего два?

Memcached — далеко не самая удачная технология. Не говоря уже о откровенно глупом паттерне его использования: поставить его на тот же сервер, где крутится всё остальное.
Памяти в кластере memcached доступно столько, сколько есть. Сколько каждому нужно. Сегодня есть инсталляции (не самые большие), где кластер имеет ёмкость 750Гб, например. (Это то, о чем я знаю, есть и больше, я думаю).

Про slab-аллокатор я не сказал не случайно. Это тема отдельного разговора и статьи, которая будет попозже в цикле. Да, действительно он так работает, что если зоны будут иметь размер 16 и 32 Кб, то выделения в 16.1Кб пойдут в зону 32Кб и будут потери 50%. Однако сегодня memcached более умно адаптирует slab-аллокатор под потребности конкретной задачи (выделяет зоны нужного размера). Такое поведение slab-аллокатора — это его «фича», он обладает своими недостатками и своими преимуществами.

Запас есть всегда, надо лишь рассчитать грамотно и грамотно мониторить. Я не призываю всё хранить в memcached, я рассказываю о нём как о решении.

Насчет LRU — прямо под рукой линка нет, можете заглянуть в исходники, там механизм LRU достаточно явный.
Я в одно время переписывался с одним из авторов memcached (с avva), он мне рассказывал именно про такой механизм выкидывния корзин.

Одним словом, у memcached куча недостатков. Я особенно против использования memcached в двух случаях:

1) использование его когда у нас только одна машина
2) использование memcached для данных, которые нельзя терять
Согласен с первым, хотя на первом этапе роста это совершенно нормально, лишь бы не навсегда. Хотя, если объем кэширования велик, то memcached работает быстрее, чем, например, кэш на файлах.

Но это всё очень относительно и зависит от конкретной задачи, «серебряной пули» здесь нет.

При масштабировании и росте числа frontend-ов для большинства задач кластер memcached — то, что надо.

Насчет второго — если «нельзя терять» воспринимать буквально, то да, тогда это не задача для memcached, а для ACID-БД на хорошем RAIDе с батарейкой, с бэкапами off-site, hot standy и т. п.
Кто говорит о кеше на файлах? Методов доступа к разделяемой памяти — миллион. И мне не кажется это нормальным. Пишешь абстрактную прослойку для работы с разделяемой памятью, а там что надо то и цепляешь.
Разделяемая память — да, это отличная штука, пока одна машина, один язык программирования и один код. Но дальше не масштабируется. А так согласен, пошустрее будет.
Вы дочитайте мою фразу до конца. Memcached, кстати, не спасает от «много языков», спасают биндинги, а их можно делать к чему угодно.
Если несколько языков программирования, например, даже в рамках одного физического сервера, ваять «свою» разделяемую память смысла нет, лучше сразу использовать то, для чего есть биндинги — например, memcached.
Бидингов для более нормальных способов доступа в разделяемую память — завались. Наберите «shared memory» в Google и смотрите.
Кажется, что диалог тут уже вышел из конструктивной области. Чтобы подытожить, скажу, что я ничего против разделяемой памяти не имею :)

Но статья про memcached, и он для случая вылезания из рамок одного сервера.
1) ну да, тут уместнее использовать Shared memory. Мы не теряем время на подключении к серверу мемкешеда. И если сайт будет расширятся с одной машины на много, и есть возможность в случае чего променять, например APC, на Memcached, то да для одной машины его можно и не юзать. Если такой возможности нет (нет абстрактного интерфейса доступа), то никуда не денешься от использования его на одном сервере.
2) зачастую «нельзя-терять» данные дублируются в БД. Имхо, без этого никак.
а когда так бывает, что абстрактного интерфейса нет? У нас магическим образом появился сервис уже с memcached? :) Memcached, кстати, тоже shared memory.
memcached — это distributed memory!
Если быть более точным, то shared memory — это память, к которой прямой доступ имеют несколько процессов, находящихся на одном физическом сервере.

Distributed memory — это память, которая распределена на нескольких физических хостах, и к ней имеют прозрачный доступ процессы с разных хостов.

Что такое 'distributed' 'shared', я не знаю.

Memcached не является 'memory' в точном смысле этого слова, т. к. доступ не прямой к памяти, а через некоторый API. Это типичный сетевой сервис, на самом деле, который можно рассматривать как 'distributed memory'.

Писал определения по памяти из классических университетских курсов, но, на всякий случай, дополню себя ссылками: en.wikipedia.org/wiki/Distributed_memory и en.wikipedia.org/wiki/Shared_memory.
Одно слово означает просто «разделяемый», второе — «распределённый». Больше никаких определений не надо.

Обычно понятие «shared memory» подразумевает какой-то API (например, man ipc), а не просто говорит о каком-то сферическом коне в вакууме.

Смысл моего выступления в том, что memcached используют просто как интерфейс доступа к разделяемой памяти, а не к разделяемой распределённой памяти.
Я думаю, определения для большинства читателей будут полезны. Потому что термины должны быть у всех одинаковы. Я привел классические и широко используемые определения этих терминов и пояснил, почему не бывает «разделяемый распределенный».

В остальном согласен — когда нужна исключительно разделямая память и повышенная производительность, memcached не нужен. Пример такой задачи — разделямая память в сервере PostgreSQL/Oracle, которые работают в многопроцессном режиме.
Чтоб восстанавливать сессию можно использовать автологин. Если не хранить в сессии данные которые должны существовать там между многими запросами и не добавляются при старте сессии, только тогда есть смысл беспокоиться об этом.
Капитан Очевидность.
Да, тут разные применения бывают: у кого-то в сессии лежит корзина интернет-магазина, а у кого-то только состояние авторизованности.
А чем страшно потерять сессию?
Будет повторный «чуть более долгий» пробой кукисов
Для юзера это выглядит как разлогинивание, особенно если нет автологина. Я бы, например, обиделся, если посреди написания гигантского поста на Хабр у меня бы слетела сессия, а я бы забыл это сохранить ;)
Ну а что мешает хранить данные корзины в тех же кукисах?
Ничего, если влезает. Это просто пример. Бывает, что недостаточно. Есть еще куча способов клиентского хранения — flash-куки и т. п.
Раз уж топик про кешед — разьсните мне один момент.
Есть пачка сайтов.
И три сервера кешедов. Соединение — гигабит.
Нагрузка на кешед 333 запроса\57 килобайт в секунду
Фигня в общем

Смотрим время генерации страницы… иногда обижаемся… дебажим дебажим и получается что…

иногда fetch занимает много времени.
и это много — 0.20..0.23 секунды.
задержка почти что константна…
бывает 0-4 таких задержок за одно обращение…

вопрос на 5 — почему
Очень интересно, жду продолжения. Я пока с мемкешем работал в тестовом режиме, в продуктиве серверов с ним нет. По этому интересно узнать о том как объединить несколько мемкеш серверов в один кластер, а также можно ли реализовать прозрачное обращение приложения к кластеру мемкеша, то есть, например, есть 3 сервера, на каждом установлен мемкеш. Приложение делает set не указывая на какой их серверов, а затем, точно также не указывая к какому из серверов обращается, делает get и получает ответ от того, на котором был сделан set.
В общем и целом так и есть, всё прозрачно, выбор сервера осуществляется клиентом. Об этом будет следующий пост.
да было бы интересно узнать об это подробно с примерами
Это пожалуй лучший доклад про мемкеш, коих я слышал уже много на разных конфах(обычно все сводиться в ману+расказу насколько мемкеш крут). Автор молодец, правильный подход к изложению материалов.
Спасибо, значит, не зря готовился!
Итересно послушать как организуете все это на уровне кода. Просто я вот вижу что многие вещи типичны, в плане usecase-ов кеширования:
— списки
— составные объекты
— атомарные объекты

Интересны примеры кода? Или «послушать»? :)

Если не заботится об атомарности изменений — любой объект разумного размера можно положить в memcached просто через сериализацию.

Когда требуется атомарное изменение, списка, например, это уже становится довольно сложной задачей: можно использовать аналог блокировок (об этом будет позже в цикле статей) или другими подходами.

Если будет конкретный вопрос, постараюсь ответить.
Послушать подход. Код не проблема.
Если какой-то каркас классов?
Например, интефейсы или классы с общей логикой взаимождействия с кешем. Или все просто if(cache) else
Например, в яве кешированием можно управлять через аннотации, а там уж само создаются враперы…
Я думаю что управление кешем это задача исключительно фреймворка.
Если пхп не умеет понимать «умные» конструкции типа явовский анотаций — есно дело и кешед это никак не научиться.

В принципе для себя я выбрал два подхода
1- ручной if(!cache_start(«name»,ttl)){ code ;cache_end();}
2- документ-представление — если блок класса N смотрим таймаут на класс N
"«умные» конструкции типа явовский анотаций " — это можно реализовать средствами пхп, через рефлекшен
второй пункт сложно переварить
гугл ничего не сказал про «пхп рефлешен»
подскажите куда копать

(пункт 2 это «на усмотрение частной реализации частного фреймворда, те кто во что горазд)
Если говорить непосредтсвенно, про наш фреймворк — всё очень просто: практически все обращения идут через наш ORM, который и управляет кэшированием.

Если есть что-то кроме этого, есть простая функция вида:

getCachedResult($func, $arguments, $cache_name, $cache_timeout)

Которая либо делает $func($arguments) (если еще нет кэша), либо отдает результат из кэша.

На самом деле чуть сложнее, но суть эта. Включается/выключается кэш, конечно, централизованно, как и управляется политика доступа к нему.

Хранилище кэша (memcached, файлы, eAccelerator) отделено от логики кэширования интерфейсами.
Это больше про доступ к кешу.
Я больще хотел узнать про выделения стратегий кеширования. Например, что-то работает через теги, изменилось удалить/пересчитать все связи. Что-то пересчитывается через локи… Т. е. типичные поведения
'даже в самой оптимизированной системе один могут быть' — они?
Здравствуйте, Андрей. Возник вопрос. Какие есть решения для разделения данных по критичности? Следует ли хранить различные по критичности данные на разных серверах или есть какие-нибудь способы повлиять на то, каким образом удаляются ключи?
Управлять удалением по сути нет прямой возможности, т.е. сказать что данный ключ «важен». Есть MemcacheDB, который гарантирует сохранность данных. Можно брать несколько пулов серверов, если память не будет заканчиваться в «важном» пуле, то и удаления ключей не будет.
Sign up to leave a comment.

Articles