Memcached — стратегия кеширования

    Хочу поприветствовать хабросообщество. Из приятных впечатлении при регистрации на Хабре — так это атмосфера сказочности, которая бывает только в старых добрых сказках из советского Кинофильма.
    Итак, слезы умиления прошли, приступаем. Ниже топик, который привел к инвайту на Хабр.

    Memcached применяется для кеширования данных. Это делается для того, чтобы избежать лишних обращений к базе данных, т.е. в Memcached сохраняют результаты запросов. Это ускоряет работу сайта и уменьшают время выдачи страниц.
    Кеш кроме преимуществ имеет свои недостатки. Одна из проблем кеша — это его актуальность. В режиме работы «только чтение» трудностей не возникает. Если же мы имеем дело с данными, которые изменяются, или изменяются часто, то эффективность кеширования резко падает. Чем чаще данные меняются, тем менее эффективен кеш. Обычно кеш сбрасывается после первого же изменения. Причем происходит сброс сразу всех закешированных данных. После сброса запросы идут к базе данных и по-новой происходит наполнение кеша. Если еще одно изменение — то кеш снова сбрасывается. Часто оказывается, что такая хорошая вещь как memcached не приносит никакой пользы для производительности сервера, и к тому же влечет за собой еще дополнительные расходы на память, процессорное время.
    Один из методов решения данной проблемы — это логическое разделение кеша на независимые части. Если сброс кеша происходит, то только для той части, которая изменилась.

    Рассмотрим один из таких подходов в связке Memcached — БД

    Если мы будем делать логическое разделение по запросам, то встает вопрос о том, как и что разделять, насколько часто обновлять. Здесь необходимо давать подсказки по каждому запросу, поскольку назначение запросов разное и непонятно какие запросы обновлять и при каких событиях. Это требует больших усилий для внедрения — и мне, как ленивому программисту, это не интересно.

    Давайте разделим все обращения к базе по таблицам.

    Допустим есть у нас запрос с обращением к нескольким таблицам. Мы берем запрос, анализируем какие в нем таблицы, смотрим, изменились ли в таблице данные. Если данные изменились, то кеш для запроса тоже обновляем. Звучит немного сложновато, возникают вопросы — каким образом это все делать, но в конечном счете реализация довольно простая.

    Приступим к наброскам:

    * Каждая таблица у нас будет иметь счетчик, который меняется каждый раз когда данные в таблице изменяются.
    * Когда мы выполняем удаление и вставку строк, когда записи изменяются — мы увеличиваем эти счетчики.
    * Перед выполнением запроса из него берется список затрагиваемых таблиц. По этим таблицам находим значения счетчика. Формируем эти значения в одну строку и добавляем как комментарий к запросу.

    Вот и все сложности с таким подходом. Чтобы перейти к новой политике кеширования нам достаточно внести небольшие изменения в код. Пример, демонстрирующий этот подход, предоставлен ниже. Этот пример полностью самостоятельный и может быть выполнен если у вас есть PHP с поддержкой расширений mysql и memcache.
    Такой подход увеличивает эффективность кеширования данных. При сбросе кеша удаляются только те данные, которые относятся к измененным таблицам. Если быть более конкретным, то слова «сброс кеша» теряют смысл, измененные данные становятся недоступными и продолжается наполнение кеша по новым ключам для тех же запросов. Если у вас есть «гадкая» таблица, из-за которой часто сбрасывается весь кеш, то теперь такая таблица не будет портить вам всю картину.

    Метод жизнеспособен, он был опробован на одном из сайтов(http://www.skachatreferat.ru). Опыт показал, что не следует пренебрегать другими методами кеширования. Что для данных, чья актуальность не критична при частоте обновления раз в 5 минут, лучше применять самое простое кеширование с установкой времени жизни кеша в заданный период, в данном случае это 5 минут.

    Возьмем habrahabr, который предоставляет доступ к статьям. Здесь каждая статья представляет собой текстовое поле и набор каких-то атрибутов. Текст меняется редко, в то время как атрибуты статьи меняются часто. По этой причине есть смысл поместить только текст статьи в кеш, а атрибуты независимо выбирать из таблиц. В результате скорость доступа к данным выростает на порядок.

    Чем меньше столбцов мы выбираем, тем лучше для производительности. MySQL работает со столбцами с данными простого типа на порядок быстрее, чем со столбцам типа TEXT(где у нас хранится текст статьи). За счет использования этих особенностей достигается значительный выигрыш в производительности.

    Ниже расположен скрипт для демонстрации метода разделения кеша по таблицам, исходник которого был вам обещан. Скрипт полностью самостоятельный и не требует каких-либо дополнительных модулей. Не забудьте указать данные для mysql и memcache в начале скрипта:
    1. <?
    2.  header('Content-type: text/html; charset=UTF-8');
    3.  $mysql_host='localhost';
    4.  $mysql_username='root';
    5.  $mysql_password='12345';
    6.  $mysql_database='test';
    7. //укажите имена двух таблиц, эти таблицы не изменяются в этом примере
    8.  $mysql_table1='table1';
    9.  $mysql_table2='table2';
    10.  $memcache_host='localhost';
    11.  $memcache_port=11211;
    12.  
    13.  $mysql=mysql_connect($mysql_host,$mysql_username,$mysql_password);
    14.  if(!$mysql)
    15.   die("Невозможно подсоединиться к MySQL: $mysql_username@$mysql_host/$mysql_password");
    16.  if(!mysql_select_db($mysql_database))
    17.   die("Невозможно подсоединиться к базе данных: $mysql_database");
    18.  $memcache = new Memcache;
    19.  if(!$memcache->pconnect($memcache_host,$memcache_port))
    20.   die("Memcached не доступен: $memcache_host:$memcache_port");
    21.  
    22.  function cacheGet($key)
    23.  {
    24.         global $memcache;
    25.         return $memcache->get($key);
    26.  }
    27.  function cacheSet($key,$data,$delay)
    28.  {
    29.         global $memcache;
    30.         return $memcache->set($key,$data,0,$delay);
    31.  }
    32.  
    33.  function sqlExtractTables(&$query)
    34.  {
    35.         preg_match_all("/\\<\\<([A-Za-z0-9\\_]+)\\>\\>/",$query,$tables);
    36.         if(!$tables[1])
    37.                 die("Запрос не содержит таблиц, доступные для распознавания вида '<<table_name>>': $query");
    38.         $query=preg_replace("/\\<\\<([A-Za-z0-9\\_]+)\\>\\>/","\\1",$query);
    39.         return $tables[1];
    40.  }
    41.  
    42.  function sqlQuery($query)
    43.  {
    44.         $resource=mysql_query($query);
    45.         if(!$resource)
    46.                 die("Неправильный запрос: $query <br> ".mysql_error());
    47.         echo "<b>Запрос был выполнен:</b> $query<br>";
    48.         return $resource;      
    49.  }
    50.  
    51.  function sqlSet($query)
    52.  {
    53.         $tables=sqlExtractTables($query);
    54.         foreach ($tables as $table)
    55.                 cacheSet($table,uniqid(time(),true),24*3600);
    56.         return sqlQuery($query);
    57.  }
    58.  function sqlGet($query)
    59.  {
    60.         $tables=sqlExtractTables($query);
    61.         foreach ($tables as $table)
    62.                 $appendix.=cacheGet($table);
    63.         $appendix="/*".md5($appendix)."*/";    
    64.         $query=$query.$appendix;
    65.         $cache_key=md5($query);
    66.         $result=cacheGet($cache_key);
    67.         if($result!==false)
    68.         {
    69.                 echo "<b>Попадание в кеш:</b> $query<br>";
    70.                 return $result;
    71.         }
    72.         else
    73.                 echo "<b>Кеш не сработал:</b> $query<br>";
    74.         $resource=sqlQuery($query);
    75.         $result=array();       
    76.         while ($row = mysql_fetch_assoc($resource))
    77.         {
    78.                 $result[]=$row;
    79.         }      
    80.         cacheSet($cache_key,$result,3600);
    81.         return $result;
    82.  }
    83.  ?>
    84.  <h2>Демонстрация. Разделение кешированных запросов по таблицам</h2>
    85.  <h3>Делаем 2 запроса</h3>
    86.  <?
    87.  sqlGet("select * from <<$mysql_table1>> limit 1");
    88.  //обычно это селекты вида "select * from <<$mysql_table1>> where id=1", здесь так дано чтобы не надо было привязываться к конкретным столбцам
    89.  ?><br><?
    90.  sqlGet("select * from <<$mysql_table2>> limit 1");
    91.  ?>
    92. <h3>Меняем одну из таблиц</h3>
    93.  <?
    94.  sqlSet("delete from <<$mysql_table2>> where 1=0");
    95.  ?>
    96. <h3>Выполняем те же запросы опять</h3>
    97.  <?
    98.  sqlGet("select * from <<$mysql_table1>> limit 1");
    99.  ?><br><?
    100.  sqlGet("select * from <<$mysql_table2>> limit 1");
    101.  ?>
    102. <h3>Результат: второй запрос должен быть выполнен снова, минуя кеш. Первый запрос продолжает браться из кеша</h3>



    исходник здесь: www.skachatreferat.ru/demo.txt

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 88

      0
      Спасибо, интересный подход. Только мне кажется, что использовать мемкеш для хранения структур данных — плохая практика. Если хотите кешировать данные из бд — лучше использовать специализированные базы, типа memcachedb. А мемкеш лучше использовать для хранения состояния системы в данный момент и быстрого доступа к данным, тяжело просчитываемым или труднодоступным, но в то же время требующим высокой скорости доступа.
        0
        Использовать мемкеш для хранения структур данных это вполне жизнеспособная и распространенная практика ). memcachedb это все тот же memcache, только данные он хранит не в памяти, а на диске, используя движок BDB.
        0
        Фактически вы предлагаете использовать две различных базы данных с одинаковым наполнением одновременно. При этом MySQL будет использоваться для групповой обработки данных, а Memcachedb для работы отдельными записями? Как быть если нам надо изменить множество записей в таблице? В MySQL это решается одним запросом.
          +1
          Для этого наверное лучше накатить патч, который добавляет в memcached теги, помечать тегами, например, названия таблиц в которых хранятся оригиналы данных. При поступлении запросов на групповую модификацию или удаление данных удалять данные из кеша с соответствующими тегами.
          Хотя зачем именно memcacheddb если и обычного хватит, не сильно понятно.
            0
            Нет, чаще всего в Memcachedb хранятся денормализованные поля и декартовы произведения таблиц. Нет смысла копировать базу в память. Но и не отдельные значения. Я говорю о том, что мемкэш нужен для хранения текущих значений некоторых параметров. Но хранить записи из базы там — черевато трудностями.
              0
              не знал о таких особенностях memcachedb.
              Была потребность в аналоге Memcache, но с возможностью долговременно хранить записи — думаю Memcachedb здесь подходит идеально.
              Как вы используйте Memcachedb и если можно с конкретными примерами, а еще лучше обсудить этот вопрос в вашем топике
                0
                Вот, кстати, да, я был не прав, конечно. Под Memcachedb я имел ввиду любую реляционную базу данных, способную хранить данные в памяти. Тот же MEMORY для mysql или TimesTen от oracle. Непосредственно Memcachedb сейчас сыроват, насколько я знаю. А статью я написать, к сожалению, не могу.
                  +5
                  «Под windows я имел в виду любую систему с окошками. Тот же KDE или Gnome»…
            +1
            Этот прием работает по той причине, что таблицы MyISAM в MySQL хранятся в виде набора столбцов. Выборка по столбцам осуществлятся независимо друг от друга.
            Пруфлинк пожалуйста
              0
              всегда считал что так и есть, но не смог найти подтверждения своим слова даже после часа гугления по вебу и mysql.com
              текст исправлен, спасибо за внимательность
              0
              Интересный подход.

              А Вы смотрели на HEAP Storage Engine?

              dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html
              The MEMORY storage engine creates tables with contents that are stored in memory. Formerly, these were known as HEAP tables. MEMORY is the preferred term, although HEAP remains supported for backward compatibility.</blockquote
                0
                знаком с такой возможностью, как вы предлагаете ее использовать?
                0
                Вообще кэш можно использовать не только как промежуточный этап для хранения результатов работы с базой данных, но и просто кэшировать куски страниц, которые достаточно редко меняются, либо некоторая задержка в обновлении этих блоков не играет роли.
                Например на главной странице сайта имеем список самых новых опубликованных статей(сайт не является новостным). То, что статьи будут появляться с задержкой в полчаса для редакторов сайта не играет большой роли. В таком случае, мы кэшируем просто блок с самыми новыми статьями и потом некоторое время берем из кэша. Когда блок будет удален по истечении времени жизни в кэше, мы этот блок полностью перегенерируем.
                Если же на странице имеется несколько таких блоков, то чтобы избежать пиковой нагрузки на базу данных в определенные интервалы времени мы данные помещаем в кэш на определенное время + случайный период времени. Таким образом регенерация данных блоков будет происходить не одновременно и резкого возрастания нагрузки на сервер не будет.
                  0
                  такой метод — супер, горазде эффективнее, чем просто кеширование запросов.
                  Smarty поддерживает такой подход, надо будет дойти до использования этой возможности www.smarty.net/manual/ru/caching.php
                  0
                  Насчет стратегии кэширования — можно добавить, что еще не следует кэшировать запросы, результат которых может изменяться вне зависимости от изменения исходных данных (те которые содержат RAND(), NOW(), FOUND_ROWS() и т.п. функции)
                    –2
                    интересно )
                      +16
                      Уважаемые новички вебдева! Ни в коем случае не используйте идеи данной статьи в реальных приложениях, т.к. они архитектурно безграмотные.

                      А теперь к делу. В самом начале статьи вы (автор) заявили, что эффективность кэша — главное. И чуть ниже сообщаете, что разделение кэша по запросам «требует больших усилий для внедрения — и мне, как ленивому программисту, это не интересно». Определитесь, пожалуйста, вы нам рассказываете как сделать действительно эффективно, или чтобы работало и вам, ленивому программисту, не пришлось головой думать?

                      «Давайте разделим все обращения к базе по таблицам.»
                      Т.е. вы предлагаете целиком выбрать всю таблицу и положить результаты выборки в мемкеш? Пытался разобраться по коду, но, извините, ваш говнокод не понял за 5 минут, на дальнейшее его исследование забил.

                      Ещё раз спрошу — вы что, целиком положите таблицу users с 10 миллионами (предположим) записей в мемкеш? Или даже хотя бы 10 миллионов записей, взяв из них два «простых» поля — в один ключ мемкеша?

                      «Текст меняется редко, в то время как атрибуты статьи меняются часто. По этой причине есть смысл поместить только текст статьи в кеш, а атрибуты независимо выбирать из таблиц. В результате скорость доступа к данным выростает на порядок.»
                      Т.е. текст положить в мемкеш, и ещё каждый раз делать выборку данных из таблички с миллионом рефератов?

                      «Чем меньше столбцов мы выбираем, тем лучше для производительности. MySQL работает со столбцами с данными простого типа на порядок быстрее, чем со столбцам типа TEXT(где у нас хранится текст статьи). За счет использования этих особенностей достигается значительный выигрыш в производительности»
                      Значительный — это 5-10%? Или во сколько вы его оцениваете? Почему?
                        –4
                        не вижу смысла отвечать вам на этом комментарий
                        если вы прочтете материал более менее внимательно и напишите грамотный и корректный комментарий, то с удовольствием продолжу нашу дискуссию
                          0
                          в статье не было сказано о том чтобы ложить записи всей таблицы в память

                          если закешированы некоторые запросы, то они будут считаться неактуальными сразу же, как только одна из учавствующих в запросах таблиц будет изменена, при этом никаких выгрузок таблиц и глобальных чтений не происходит.
                          Одной записи в кеш достаточно, чтобы пометить таблицу как измененную, а все связанные с ней результаты запросов как устаревшие
                            0
                            А Вы слышали про мускульный query cache?! Он делает тоже самое, и именно по этому его не эффективно использовать в проектах с большой нагрузкой. Ничего лично, но Ваше решение — это жесть.
                            +1
                            Подписываюсь почти под каждым словом.
                            Чем больше подобных статей, тем толще слой масла у нормальных разработчиков.
                            • НЛО прилетело и опубликовало эту надпись здесь
                              0
                              Ваш код ужасен. Вы в своем проекте тоже пользуетесь die().
                              Вы в каком веке живете?
                              Ваша проблема уже давно решена.
                                0
                                вы наверное говорите про проблему бессмертия, die больше нет?
                                  0
                                  есть exception
                                    0
                                    А вы не пробовали пользоватся фреймверками?
                                    Дайте угадаю.Вы фрилансер без опаты офисной работы.
                                0
                                такой метод — супер, горазде эффективнее, чем просто кеширование запросов.
                                Smarty поддерживает такой подход, надо будет дойти до использования этой возможности www.smarty.net/manual/ru/caching.php
                                  0
                                  просьба проигнорировать этот комментарий, он предназначался комментарию выше пользователя Chrome и был опубликован здесь по ошибке
                                  +3
                                  Как я понимаю, встроенный кеш для майскл делает нечто похожее — кеширует результаты запросов, а если таблицы запросов поменялись — сбрасывает кеш. Иногда достаточно просто памяти побольше на кеш майскл выделить.
                                    +1
                                    Именно. И результатов тестов нет.
                                    В ряде старых тестов чисто как хранилище кеш mysql даже обгонял memcached. А новых кажется никто не делал с тех пор.

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

                                    Еще меня убивает приверженность оптимизаторов к кешированию. Их унылые говносайты посещают только поисковые машины и причем индексируют от начала до конца. Кеш при этом полностью переполняется запросами, которые в ближайший месяц не будут востребованы.
                                      +1
                                      насчет поисковых машин и кеша — в самую точку
                                        0
                                        преждевременная оптимизация — враг.
                                    +4
                                    Первое
                                    В вашем подходе есть значительный минус — обновление кеша происходит при обращении фронтенда к бэкенду, а это в корне не правильный подход, который сниджает эфективность кеширования на 10-80%
                                    Если уж беретесь кешировать данные, то будьте добры — обеспечьте обновление данных где-то в фоне. Поясню: у вас получаеться так — юзер изменил данные, таблица пометилась как обновленная и все. Далее, другой юзер пытаеться обратить к этим данным и у вас идет перестроение кеша, что приводит к задержке выдачи.
                                    А нужно так: юзер изменил что-то, перестроился кеш (здесь нужно грамотно продумать как перестраивать, что бы у юзера не было задержек). При выборе данных юзер будет всегда получать данные из кеша. Только в этом случае кеш будет работать эффективно.

                                    Второе
                                    Ваш подход можно полностью переложить на плечи базы данных. Для всех данных, которые должны быть закешированы, создаються таблицы типа memory. Выборка происходит только из этих таблиц. За целостностью следят триггера. Для большей уверенность, можно повесить скприт на крон, который будет проветь целостность данных.

                                    Но в любом случае, нужно продумывать архитектуру проекта задолго до того, как браться за его реализацию.
                                      +1
                                      и еще, «Чем чаще данные меняются, тем менее эффективен кеш.» — это полнейшая глупость, которой оперируют от незнания теории кеширования. Прежде чем такое писать, было бы не плохо почитать про эту теорию и хорошо изучить мат часть.

                                      Эффективность кеша зависит от множества параметров, основными из которых являються:
                                      — частота обновления кеша
                                      — кол-во запросов, которые приходяться к кешу на время между обновлениями
                                      — скорость обновления кеша
                                      — критичность актуальности данных во время кешировани и обновления кеша
                                      вот когда вы учтете хотя бы эти параметры, тогда сможете говорить об актуальности и эффективности кеша.

                                      у меня на одном проекте кеш обновляеться в среднем 3 раза за 2 секунды, но за время между обновлениями к нему идет около 5500 обращений (т.е. в среднем около 16500 за 2 сек). я склонен считать что этот кеш эффективный, так как при обращениях к базе без кеша смог бы обработать примерно в 28 раз меньше запросов.
                                        0
                                        "«Чем чаще данные меняются, тем менее эффективен кеш.» — это полнейшая глупость" —
                                        при изменении данных рано или поздно происходит сброс кеша, что снижает его эффективность —
                                        это прописная истина
                                        а об остальном уже говорилось.

                                          +1
                                          когда это сброс кеша снижал эффективность?
                                          НЕГРАМОТНЫЙ сброс — да, снижает.
                                            +1
                                            бывает такая ситуация, когда два человека говорят об одном том же говорят, но почему-то происходит в виде спора
                                        0
                                        «обновление кеша происходит при обращении фронтенда к бэкенду, а это в корне не правильный подход, который сниджает эфективность кеширования на 10-80%» — если вы имеете в виду расположение memcached, то это никак не зависит от метода, который был описан
                                        memcached вы можете расположить где угодно. Лучше, конечно, на фронтенде, как вы и написали

                                        «Если уж беретесь кешировать данные, то будьте добры — обеспечьте обновление данных где-то в фоне.» — обновление данных происходит по мере выполнения запросов, наверное вас ввел в заблуждение комментарий пользователя Unechka

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

                                          на счет MySQL — таблица memory полностью располагаеться в памяти так же как и данные мемкеша. а если грамотно оттюнить MySQL то он может работать ооочень быстро и кешировать все запросы таким же методом как и у вас только вы избавитесь от еще одного велосипеда.
                                            0
                                            спасибо за разъяснение, я вас не правильно понял насчет фронтенд/бекенд, в таком случае, прошу прощения

                                            когда вы говорите о сторогом разделении бизнес логики от отображения, то имеете ввиду MVC, или что-то другое? если дизайн вынесен в Smarty, этого не достаточно? если я сильно туплю, то можно ссылку на соответсвующую статью, чтобы до меня наконец дошло

                                            обычно данные подготавливаются и передаются в Smarty шаблон, который это дело отображает, к тому же есть модификаторы и функции в Smarty для специфических случаев

                                            сайт в конкретном случае работает на одном сервере, а база данных расположена на другом.
                                            Помещая данные мемкешед мы экономим время на сетевых издержках, а так же на времени, которое MySQL тратит на разбор запросов.

                                            Что такое «очень быстро» в вашем понятии? можно конкретные цифры
                                              0
                                              MVC это не совсем то. я имею ввиду разделение логики при работе с данными.
                                              за примером пойдем к хабру — главная страница из статей с атрибутами. так вот, тут присутствует логика отображения и бизнес логика формирования исходных данных (т.е. текста и атрибутов).
                                              для достижения наименьшего времени которое пройдет меджу тем как сервер получит запрос от пользователя и отдаст ему первый байт, я бы закешировал полностью главную страницу в виде объекта и никогда не парился о проверке/изменениях аттрибутов при формировании результата пользователю. никаких проверок вообще.
                                              а вот во время изменения данных (кто-то плюсанул статью, к примеру) — формировал бы новый объект и помещал бы его в кеш. улавливаете мысль? не нужно кажды раз лезть в базу для того что бы получить данные. да, вы тоже не лезите если у вас закешированные данные, но вы проверяете их актуальность, а этого не должно быть в принципе при формировании контента пользователю. не нужно туда лезть вообще.
                                              где об этом почитать? погуглите на предмет архитектурирования многопользовательских высоконагруженных систем. посмотрите как устроен фликер, скайп, фейсбук. последние в прошлом году открыли часть своих кодов, много чего интересного есть.

                                              то что у вас сайт на одном, а база на другом сервере особой роли на коннекшенах не играет, если у вас там конечно не 10MBit. к мемкешу так же по TCP идут коннекты.
                                              MySQL не тратит время на повторные одинаковые запросы если у него хватает памяти. а время для вычисление MD5 от запроса, который вы используете для формирования ключа вполне можно сравнить с сетевыми издержками к базе.

                                              что такое очень быстро? это примерно как бжжж и все :)
                                              если серьезно, то на 0,5% медленне, чем кешировать данные в мемкеше. думаю этим можно принебречь. проверенно на собственных тестах и на живом игровом проекте под нагрузкой.
                                                0
                                                опять же есть особенности конкретной архитектуры и особенности проекта, универсального рецета нет

                                                фактически вы говорите что в ваших проектах вам кеш не нужен

                                                для битторрентов для повышения производительности пишется клиент, который держит сотни тысяч коннектов на обычном сервере, но это же не повод говорить всем что следует писать такие клиенты для каждого проекта
                                                0
                                                > Помещая данные мемкешед мы экономим время на сетевых издержках, а так же на времени, которое MySQL тратит на разбор запросов
                                                Сетевые издержки при общении с сервером memcache ничем не отличаются от таковых для сервера БД (tcp), а как вы думаете кто быстрее вычисляет хеш запроса php-скрипт или сервер БД (на сях написанный например) кроме того в идеальной и классической ситуации 1:1 если все кешируется то Ваш веб-сервер более загружен чем сервер кеша… на него переносить нужно максимум вычислений
                                                  0
                                                  согласен, при расположении мемкеш на отдельном сервере сетевые издержки присутствуют
                                                    0
                                                    открою секрет, даже при расположении на том-же сервере издержки присутствуют… так вывод будет какой-то?
                                                      0
                                                      вывод простой, пишем скрипт который наглядно сравнивает кеширование с помощью мемкешед, кеширование средствами мускула и голый SQL без кеширования на таблице с типами данных INT, TEXT, VARCHAR2
                                                        0
                                                        скрипт не поможет, нужно более-менее реальное приложение и имитировать запросы например с помощью siege, a можно не писать, я могу вам рассказать что будет
                                                          0
                                                          расскажите пожалуйста с описанием архитектуры, если можно
                                                            0
                                                            рассказать что будет?
                                                            1. голый SQL без кеша запросов — все понятно и прогнозируемо, «обычное» число коннектов. на выхлопе образно 100 запросов/сек
                                                            2. с кешем запросов — несколько быстрее, заметно упала нагрузка на дисковую систему, нагрузка на сервер БД упала в 2 раза (образно в процентах использования CPU — запросы не попавшие в кеш выполняются быстрее), чисто открытых tcp коннектов не изменилось, загрузка канала до БД не изменилась. — выхлоп 150 запросов/сек.
                                                            3. ваш вариант, добавился сервер мемкеш (заплатили), канал на него используется почти как в предыдущих вариантах канал к БД, канал к БД почти пустой, общее использование tcp соединений выросло образно в 2 раза, траффик tcp вырос процентов на 40 (100% в мемкеш выборки + флуш при изменении + вставки в БД), нагрузка на веб-сервер выросла дай бог что-б не в 1,5 раза (накладные расходы для кеширования в php — соединения, десереализация, сериализация, флуш кеша и т.п.) итого имеем 110 запросов/сек, лишние бабки которые можно было потратить на второй веб-сервер и кучу гемороя.
                                                              0
                                                              один вопрос, вы собирали статистику по запросам?
                                                                0
                                                                я не понял вопроса, о какой статистике идет речь?
                                                                  0
                                                                  статистику по SQL-запрсам к базе
                                                                    0
                                                                    ну вообще считается что для среднестатистического сайта не попадание в кеш — 1/10 (из 10 запросов 1 выполняется), у меня больше — около 1/5 поскольку много вставок — специфика проекта такая
                                                                  0
                                                                  вот статистика кеша с боевого сервера, приложение достаточно тяжелое с большим количеством вставок:
                                                                  mysql> SHOW STATUS LIKE 'Qcache%';
                                                                  +-------------------------+-----------+
                                                                  | Variable_name | Value |
                                                                  +-------------------------+-----------+
                                                                  | Qcache_free_blocks | 17779 |
                                                                  | Qcache_free_memory | 63136640 |
                                                                  | Qcache_hits | 276480402 |
                                                                  | Qcache_inserts | 45319306 |
                                                                  | Qcache_lowmem_prunes | 194340 |
                                                                  | Qcache_not_cached | 2166225 |
                                                                  | Qcache_queries_in_cache | 34735 |
                                                                  | Qcache_total_blocks | 87304 |
                                                                  +-------------------------+-----------+
                                                                  8 rows in set (0.00 sec)

                                                                  как видим 276 млн попаданий запросов в кеш при 2-х млн не попавших и 45 млн вставках (флушах)

                                                                  число соединений 2649984 — итого образно 100 запросов из кеша на соединение
                                                                    –1
                                                                    сначала надо собрать статистику по SQL запросам по базе. Надо знать по каждому запросу — сколько раз он выполнялся и сколько времени это заняло. Под запросом здесь понимается какой-то SQL-запрос не зависимо от параметров, которые него переданы.

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

                                                                    вы говорите о флушах в мемкеше — это то самое безобразие, против которого направлен описанный в статье метод

                                                                    могу помочь с оптимизацией, не бесплатно конечно, поскольку необходимые знания вам уже предоставлены
                                                                      +1
                                                                      :) извините, все я умываю руки
                                                                        0
                                                                        вот вот, поимели что хотели :)
                                                                          –1
                                                                          потом не забудьте похвастаться тем, что у вас получилось
                                                                        0
                                                                        я ступил, извиняюсь :)
                                                                        статистика выглядит хорошо для таких параметров,
                                                                        можно долго спорить, но в конечном случае все решается на конкретном примере. вы перепробовали несколько вариантов и имеете право на свое мнение, как и я — на свое
                                                +1
                                                автор, подсветите Ваш код, а то невозможно читать эту неотформатированную кашу.
                                                  0
                                                  код был успешно подсвечен, а каша — отформатирована
                                                  0
                                                  как и говорили выше, я не понял в чем преимущество кроме велосипедности и постоянного гоняния данных по tcp Вашего подхода перед кешированием запросов ВСТРОЕННЫМИ средствами самого мускуля? Автор ответит?

                                                  П.С. про масштабируемость с таким кодом чур не вспоминать.
                                                  П.П.С меня на хабр тоже привела статья про кеширование только рассматривалось практическое использование тегов и стеков кеша (а также их эмуляция) в сочетании с отложенными запросами в MVC — идея была прозрачно кешировать блоки по триггерам от модели… инвайт получил а статья чего-то пропала, повторно такой шедевр рожать не хочу.
                                                    0
                                                    видимо вы не сталкивались с ситуацией когда база данных отказывает от того, что к ней слишком много обращений и надо любыми средствами ограничить количество количество запросов к базе
                                                    если для вас все равно — миллисекунду или микросекунду выполняется запрос — то я вам ничего не могу ответить

                                                    используйте встроенные средства MySQL, если они вас устраивают и отвечают вашим тербованиям

                                                    а насчет масштабируемости немного непонятно, что вас не устраивает, поподробнее пожалуйста
                                                      0
                                                      эм… я не понял ответа, Вы написали статью претендующую на туториал для новичков значит несете некоторую ответственность в адекватности советов?, знаете как работает кеширование запросов мускуля (кстати по умочанию отключено) а работает именно так как у вас только без левых посредников и велосипедов, причем прозрачно разруливает и обновления массовые и вычисляемые функции и т.п., тут выше говорили что работает даже быстрее, я не проверял но поверю — отсутствие лишнего tcp коннекшена это позитив, как и отсутствие левых вычислений не быстрым php

                                                      webew.ru/articles/1041.webew

                                                      Если у Вас ситуация когда слишком много обращений к серверу БД при включенном и адекватно работающем кеше запросов то ваш код захлебнется не поднявшись, вариант сервер БД на очень медленной машине а мемкеш на быстрой не рассматриваем по причине надуманности.

                                                      относительно масштабирования — я имел в виду что сервера мемкеш масштабируются несколько проше чем сервера БД но имхо это не Ваш случай
                                                        0
                                                        есть какие-то трудности по масштабированию мемкеш в данном случае? не вижу трудности по применению
                                                        если можно, объясните, что вы имеете ввиду — видимо я не вижу какие-то очевидные проблемы
                                                          0
                                                          чет сглюкнул хабр, извиняюсь за дублирование коммента
                                                          относительно трудностей… как бы понимаете, прикручивать на телегу спортивные покрышки можно и просто, не сложнее чем в случае ламбо, но как-бы «не поможет» вот это и есть сложности… по вашему камменту я понимаю вы считаете что Ваш метод лучше нативного в мускуле? можете наконец написать чем?
                                                            0
                                                            если мы будем игнорировать взаимные вопросы/ответы, навряд ли наша дискуссия будет кому-либо интересна
                                                              0
                                                              оки… как уже сказали Вы переносите БД практически целиком в мемкеш, достаточно поисковику пройтись по вашему сайту и он вам набъет кеш «левыми» данными — мама не горюй, причем без балансировки фронтенда по серверам он в таком случае будет генерить такую лавину tcp траффика к серверу memcache что только то и будет делать что обслуживать левые коннекшены. в такой схеме Вам нужно иметь размер кеша = размеру БД, считаете это нормально? тогда предлагаю кешировать обращения к серверу мемкеш.
                                                                0
                                                                немного не понял насчет «предлагаю кешировать обращения к серверу мемкеш.»
                                                                  0
                                                                  Если включить кеширование запросов у Вашего сервера БД то Ваш метод кеширует кеширование, причем более быстрое более медленным, вот я и предлагаю еще один круг «для надежности»…
                                                                  Я на Ваш вопрос ответил? на мой ответите?
                                                                    0
                                                                    мемкеш использует механизм LRU, который позволяет обходить эту проблему Наименее используемые объекты выводятся в первую очередь
                                                      0
                                                      эм… я не понял ответа, Вы написали статью претендующую на туториал для новичков значит несете некоторую ответственность в адекватности советов?, знаете как работает кеширование запросов мускуля (кстати по умочанию отключено) а работает именно так как у вас только без левых посредников и велосипедов, причем прозрачно разруливает и обновления массовые и вычисляемые функции и т.п., тут выше говорили что работает даже быстрее, я не проверял но поверю — отсутствие лишнего tcp коннекшена это позитив, как и отсутствие левых вычислений не быстрым php

                                                      webew.ru/articles/1041.webew

                                                      Если у Вас ситуация когда слишком много обращений к серверу БД при включенном и адекватно работающем кеше запросов то ваш код захлебнется не поднявшись, вариант сервер БД на очень медленной машине а мемкеш на быстрой не рассматриваем по причине надуманности.

                                                      относительно масштабирования — я имел в виду что сервера мемкеш масштабируются несколько проше чем сервера БД но имхо это не Ваш случай
                                                        0
                                                        эм… я не понял ответа, Вы написали статью претендующую на туториал для новичков значит несете некоторую ответственность в адекватности советов?, знаете как работает кеширование запросов мускуля (кстати по умочанию отключено) а работает именно так как у вас только без левых посредников и велосипедов, причем прозрачно разруливает и обновления массовые и вычисляемые функции и т.п., тут выше говорили что работает даже быстрее, я не проверял но поверю — отсутствие лишнего tcp коннекшена это позитив, как и отсутствие левых вычислений не быстрым php

                                                        webew.ru/articles/1041.webew

                                                        Если у Вас ситуация когда слишком много обращений к серверу БД при включенном и адекватно работающем кеше запросов то ваш код захлебнется не поднявшись, вариант сервер БД на очень медленной машине а мемкеш на быстрой не рассматриваем по причине надуманности.

                                                        относительно масштабирования — я имел в виду что сервера мемкеш масштабируются несколько проше чем сервера БД но имхо это не Ваш случай
                                                      +1
                                                      ># if(!$memcache->pconnect($memcache_host,$memcache_port))
                                                      ># die(«Memcached не доступен: $memcache_host:$memcache_port»);

                                                      круто!
                                                      именно так надо писать серьзные приложения 24/7;)
                                                      понимаю, что демонстрация, но тем не менее надо создать метод класса, который среагирует нужным образом, а не будет умирать.
                                                      ведь Вас же могут читать дети;)
                                                      чему тут можно научиться?!
                                                        +2
                                                        Вы слишком усложняете задачу. Для этого существует система тагов для кеша. В Memcached она не встроена, нужно писать прослойку. При изменениях новости (к примеру) просто сбрасываете все ключи с соответствующим тагом. Почитайте смиру www.smira.ru/2008/10/16/web-caching-memcached-1/ и еще можно почитать про библиотеку Димы Котерова.
                                                          0
                                                          Полностью согласен с комментатором, у Андрея Смирнова всё очень хорошо расписано, и доклады просто замечательные.
                                                            0
                                                            Спасибо!

                                                            Если я правильно понял автора, то, что он предлагает является вырожденным случаем тэгирования кэшей. При этом некоторые утверждения в статье, как писали уже выше в комментариях, являются как минимум спорными.

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

                                                            Как раз задачи минимизации сброса кэшей является актуальной, кэши должны сбрасываться редко (они должны быть так устроены). Опять-таки, если я не путаюсь в мыслях автора, он предлагает перейти от сброса «всех вообще кэшей» при любом изменении к сбросу «всех кэшей, связанных с таблицей, при изменении таблицы». Ммм… это каменный век кэширования! Давайте двигаться вперед! :)
                                                              0
                                                              Smira, ваше восприятие статьи очень адекватное и справедливое. Видно что вы занимались этим вопросом очень подробно

                                                              В вашей статье www.smira.ru/2008/10/08/highload-plus-plus-2008/ просмотрел описание подхода «тегирование кеша» по отношению к которому мною описанный подход к кешированию является всего лишь частным случаем.

                                                              Я не претендую на новаторство в этом методе, как и вы не можете на него претендовать в своем. Единственное полезное дело что вы можете сделать — так это описать практические случаи применения, чтобы дать возможность читающим оценить его ценность и дать идеи для воплощения в своих проектах. Напишите статьи в Хабре и да при будет с вами Карма

                                                              PS: хотя вы и так уже 60-й в списке лидеров Хабра
                                                                0
                                                                Сергей, я не претендую на авторство в вопросе тэгирования. Скорее, это мы с Димой Котеровым почти независимо пришли. Я лишь хочу сказать, что надо пробовать что-то лучшее сегодня уже. Гораздо проще начинать с хорошего, когда оно уже опробовано кем-то и описано.

                                                                Так что, даешь новую статью про улучшенную Вами же Вашу систему кэширования!
                                                                  0
                                                                  какие пути улучшения вы видите.

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

                                                                  сначала использовался метод, когда при каждом изменении происходил полный flush кеша
                                                                    +1
                                                                    Сергей, может быть Вам подойдет и Ваша система. Наверное, она работает.

                                                                    Просто аудитория Хабра состоит в том числе и из тех, кто еще еще только собирается написать свою систему кэширования. И было бы лучше, если бы они учились на более правильных примерах, чем Ваш. Чтобы они не набивали свои собственные шишки, а воспользовались уже готовыми решениями.

                                                                    Как использовать более «правильные» подходы к кэшированию? Я бы советовал взять, например, библиотеку Котерова. Или посмотреть продвинутые frameworkи кэширования, например, в рельсах. Может, кто еще из Хабровчан расскажет о хороших примерах, я доступных примеров больше не знаю, к сожалению.
                                                                      0
                                                                      спасибо за ваши коментарии
                                                                0
                                                                Smira, ваше восприятие статьи очень адекватное и справедливое. Видно что вы занимались этим вопросом очень подробно

                                                                В вашей статье www.smira.ru/2008/10/08/highload-plus-plus-2008/ просмотрел описание подхода «тегирование кеша» по отношению к которому мною описанный подход к кешированию является всего лишь частным случаем.

                                                                Я не претендую на новаторство в этом методе, как и вы не можете на него претендовать в своем. Единственное полезное дело что вы можете сделать — так это описать практические случаи применения, чтобы дать возможность читающим оценить его ценность и дать идеи для воплощения в своих проектах. Напишите статьи в Хабре и да при будет с вами Карма

                                                                PS: хотя вы и так уже 60-й в списке лидеров Хабра
                                                            –1
                                                            А что делать с тем, что у мемкэша ограничен размер хранимых данных в одной записи?

                                                            И чем это лучше чем кэш MySQL… Хотя это уже спрашивали выше много раз.
                                                              0
                                                              Автору в обязательном порядке ознакомится с азами:
                                                              www.smira.ru/2008/10/08/highload-plus-plus-2008/

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

                                                              Самое читаемое