Кэширование и memcached

    Этим постом хочу открыть небольшую серию постов по материалам доклада на HighLoad++-2008. Впоследствии весь текст будет опубликован в виде одной большой PDF-ки.



    Введение


    Для начала, о названии серии постов: посты будут и о кэшировании в Web’е (в высоконагруженных Web-проектах), и о применении memcached для кэширования, и о других применениях memcached в Web-проектах. То есть все три составляющие названия в различных комбинациях будут освещены в этой серии постов.

    Кэширование сегодня является неотъемлемой частью любого Web-проекта, не обязательно высоконагруженного. Для каждого ресурса критичной для пользователя является такая характеристика, как время отклика сервера. Увеличение времени отклика сервера приводит к оттоку посетителей. Следовательно, необходимо минимизировать время отклика: для этого необходимо уменьшать время, требуемое на формирование ответа пользователю, а ответ пользователю требует получить данные из каких-то внешних ресурсов (backend). Этими ресурсами могут быть как базы данных, так и любые другие относительно медленные источники данных (например, удаленный файловый сервер, на котором мы уточняем количество свободного места). Для генерации одной страницы достаточно сложного ресурса нам может потребоваться совершить десятки подобных обращений. Многие из них будут быстрыми: 20 мс и меньше, однако всегда существует некоторое небольшое количество запросов, время вычисления которых может исчисляться секундами или минутами (даже в самой оптимизированной системе один могут быть, хотя их количество должно быть минимально). Если сложить всё то время, которое мы затратим на ожидание результатов запросов (если же мы будем выполнять запросы параллельно, то возьмем время вычисления самого долгого запроса), мы получим неудовлетворительное время отклика.

    Решением этой задачи является кэширование: мы помещаем результат вычислений в некоторое хранилище (например, memcached), которое обладает отличными характеристиками по времени доступа к информации. Теперь вместо обращений к медленным, сложным и тяжелым backend’ам нам достаточно выполнить запрос к быстрому кэшу.

    Memcached и кэширование


    Принцип локальности


    Кэш или подход кэширования мы встречаем повсюду в электронных устройствах, архитектуре программного обеспечения: кэш ЦП (первого и второго уровня), буферы жесткого диска, кэш операционной системы, буфер в автомагнитоле. Чем же определяется такой успех кэширования? Ответ лежит в принципе локальности: программе, устройству свойственно в определенный промежуток времени работать с некоторым подмножеством данных из общего набора. В случае оперативной памяти это означает, что если программа работает с данными, находящимися по адресу 100, то с большей степенью вероятности следующее обращение будет по адресу 101, 102 и т.п., а не по адресу 10000, например. То же самое с жестким диском: его буфер наполняется данными из областей, соседних по отношению к последним прочитанным секторам, если бы наши программы работали в один момент времени не с некоторым относительно небольшим набором файлов, а со всем содержимым жесткого диска, буферы были бы бессмысленны. Буфер автомагнитолы совершает упреждающее чтение с диска следующих минут музыки, потому что мы, скорее всего, будем слушать музыкальный файл последовательно, чем перескакивать по набору музыки и т.п.

    В случае web-проектов успех кэширования определяется тем, что на сайте есть всегда наиболее популярные страницы, некоторые данные используются на всех или почти на всех страницах, то есть существуют некоторые выборки, которые оказываются затребованы гораздо чаще других. Мы заменяем несколько обращений к backend’у на одно обращения для построения кэша, а затем все последующие обращения будет делать через быстро работающий кэш.

    Кэш всегда лучше, чем исходный источник данных: кэш ЦП на порядки быстрее оперативной памяти, однако мы не можем сделать оперативную память такой же быстрой, как кэш – это экономически неэффективно и технически сложно. Буфер жесткого диска удовлетворяет запросы за данными на порядки быстрее самого жесткого диска, однако буфер не обладает свойством запоминать данные при отключении питания – в этом смысле он хуже самого устройства. Аналогичная ситуация и с кэшированием в Web’е: кэш быстрее и эффективнее, чем backend, однако он обычно в случае перезапуска или падения сервера не может сохранить данные, а также не обладает логикой по вычислению каких-либо результатов: он умеет возвращать лишь то, что мы ранее в него положили.

    Memcached


    Memcached представляет собой огромную хэш-таблицу в оперативной памяти, доступную по сетевому протоколу. Он обеспечивает сервис по хранению значений, ассоциированных с ключами. Доступ к хэшу мы получаем через простой сетевой протокол, клиентом может выступать программа, написанная на произвольном языке программирования (существуют клиенты для C/C++, PHP, Perl, Java и т.п.).

    Самые простые операции – получить значение указанного ключа (get), установить значение ключа (set) и удалить ключ (del). Для реализации цепочки атомарных операций (при условии конкурентного доступа к memcached со стороны параллельных процессов) используются дополнительные операции: инкремент/декремент значения ключа (incr/decr), дописать данные к значению ключа в начало или в конец (append/prepend), атомарная связка получения/установки значения (gets/cas) и другие.

    Memcached был реализован Брэдом Фитцпатриком (Brad Fitzpatrick) в рамках работы над проектом ЖЖ (LiveJournal). Он использовался для разгрузки базы данных от запросов при отдаче контента страниц. Сегодня memcached нашел своё применение в ядре многих крупных проектов, например, Wikipedia, YouTube, Facebook и другие.

    Общая схема кэширования


    Общая схема кэширования

    В общем случае схема кэширования выглядит следующим образом: frontend’у (той части проекта, которая формирует ответ пользователю) требуется получить данные какой-то выборки. Frontend обращается к быстрому как гепард серверу memcached за кэшом выборки (get-запрос). Если соответствующий ключ будет обнаружен, работа на этом заканчивается. В противном случае следует обращение к тяжелому, неповоротливому, но мощному (как слон) backend’у, в роли которого чаще всего выступает база данных. Полученный результат сразу же записывается в memcached в качестве кэша (set-запрос). При этом обычно для ключа задается максимальное время жизни (срок годности), который соответствует моменту сброса кэша.

    Такая стандартная схема кэширования реализуется всегда. Вместо memcached в некоторых проектах могут использоваться локальные файлы, иные способы хранения (другая БД, кэш PHP-акселератора и т.п.) Однако, как будет показано далее, в высоконагруженном проекте данная схема может работать не самым эффективным образом. Тем не менее, в нашем дальнейшем рассказе мы будем опираться именно на эту схему.

    Архитектура memcached


    Каким же образом устроен memcached? Как ему удаётся работать настолько быстро, что даже десятки запросов к memcached, необходимых для обработки одной страницы сайта, не приводят к существенной задержке. При этом memcached крайне нетребователен к вычислительным ресурсам: на нагруженной инсталляции процессорное время, использованное им, редко превышает 10%.

    Во-первых, memcached спроектирован так, чтобы все его операции имели алгоритмическую сложность O(1), т.е. время выполнения любой операции не зависит от количества ключей, которые хранит memcached. Это означает, что некоторые операции (или возможности) будут отсутствовать в нём, если их реализация требует всего лишь линейного (O(n)) времени. Так, в memcached отсутствуют возможность объединения ключей «в папки», т.е. какой-либо группировки ключей, также мы не найдем групповых операций над ключами или их значениями.

    Основными оптимизированными операциями является выделение/освобождение блоков памяти под хранение ключей, определение политики самых неиспользуемых ключей (LRU) для очистки кэша при нехватке памяти. Поиск ключей происходит через хэширование, поэтому имеет сложность O(1).

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

    По сути, можно сказать, что время отклика сервера memcached определяется только сетевыми издержками и практически равно времени передачи пакета от frontend’а до сервера memcached (RTT). Такие характеристики позволяют использовать memcached в высоконагруженных web-проектов для решения различных задач, в том числе и для кэширования данных.

    Потеря ключей


    Memcached не является надежным хранилищем – возможна ситуация, когда ключ будет удален из кэша раньше окончания его срока жизни. Архитектура проекта должна быть готова к такой ситуации и должна гибко реагировать на потерю ключей. Можно выделить три основных причины потери ключей:

    1. Ключ был удален раньше окончания его срока годности в силу нехватки памяти под хранение значений других ключей. Memcached использует политику LRU, поэтому такая потеря означает, что данный ключ редко использовался и память кэша освобождается для хранения более популярных ключей.
    2. Ключ был удален, так как истекло его время жизни. Такая ситуация строго говоря не является потерей, так как мы сами ограничили время жизни ключа, но для клиентского по отношению к memcached кода такая потеря неотличима от других случаев – при обращении к memcached мы получаем ответ «такого ключа нет».
    3. Самой неприятной ситуацией является крах процесса memcached или сервера, на котором он расположен. В этой ситуации мы теряем все ключи, которые хранились в кэше. Несколько сгладить последствия позволяет кластерная организация: множество серверов memcached, по которым «размазаны» ключи проекта: так последствия краха одного кэша будут менее заметны.


    Все описанные ситуации необходимо иметь в виду при разработке программного обеспечения, работающего с memcached. Можно разделить данные, которые мы храним в memcached, по степени критичности их потери.

    «Можно потерять». К этой категории относятся кэши выборок из базы данных. Потеря таких ключей не так страшна, потому что мы можем легко восстановить их значения, обратившись заново к backend’у. Однако частые потери кэшей приводят к излишним обращениям к БД.

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

    «Совсем не должны терять». Memcached удобен для хранения сессий пользователей – все сессии равнодоступны со всех серверов, входящих в кластер frontend’ов. Так вот содержимое сессий не хотелось бы терять никогда – иначе пользователей на сайте будет «разлогинивать». Как попытаться избежать? Можно дублировать ключи сессий на нескольких серверах memcached из кластера, так вероятность потери снижается.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 72

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

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

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

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

                  print_r(memcache_get_extended_stats($memcache_obj));

                    0
                    Возможно, проблемы с сетью, у addServer есть последний параметр — failure_callback, через него советую попробовать настроить логгинг в файл, например. Каждая запись там будет сетевой проблемой с конкретным серверов.
                      0
                      ну дык — когда виснет понятно и видно
                      а почему — нет
                        0
                        Сетевые проблемы — потери пакетов, например. Недостаточность пропускной способности и т. п. Просто измерить ping и потери иногда бывает достаточно ;)
                          0
                          пинг нормально — гигабит соединение без участия свича. те прямой кабель
                          как измерить потери — не знаю даже :(
                            0
                            Тем же пингом можно, интервал поменьше, потери он покажет. Если честно, я совсем не админ, так что тут, возможно, нужен «админский глаз». Если я прав про сетевые проблемы, конечно.
                              0
                              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»);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                        Only users with full accounts can post comments. Log in, please.