<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Блог Андрея Смирнова (производительность)</title><link>http://www.smira.ru/</link><description></description><language>ru</language><lastBuildDate>Sun, 11 Jan 2015 19:24:25 GMT</lastBuildDate><generator>http://getnikola.com/</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Web, кеширование и memcached: часть 1</title><link>http://www.smira.ru/posts/20080622web-cache-memcached-1.html</link><dc:creator>Andrey</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;p&gt;Все сегодня знают, что нагруженный веб-проект не может постоянно обращаться к БД с запросами, знают, что БД не выдержит. Все знают, что надо кешировать результаты. Можно кешировать сгенерированный HTML-контент, но лучше кешировать данные (результаты запросов), т.к. одни и те же данные могут отображаться разными способами (разные блоки, ответы по API, JSON, что-то еще).&lt;/p&gt;
&lt;p&gt;Итак, мы договорились кешировать результаты запросов. Самый простой вариант - кешировать в файлах, однако если проект имеет кластерную (распределенную) архитектуру, кеши дублируются локальными для каждой вебморды (что приводит к большему числу запросов и к проблеме когерентности одного и того же кеша на разных мордах). Поэтому вместо файлового кеша в таких ситуациях используют замечательный продукт &lt;a href="http://www.danga.com/memcached/"&gt;memcached&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ну вот, мы всё замечательно закешировали, однако проблемы всё равно остались. Какие бывают проблемы и как с ними можно бороться? В серии постов на эту тему постараемся с этим разобраться.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;Проблема №1. Именование кеша&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Как назвать ключ в мемкеше, под которым мы сохраним закешированный результат выборки? У нас есть ORM-прослойка, и параметры выборки, которые представляют из себя ассоциативный массив, мы превращаем в ключ так:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Что работает достаточно неплохо, т.к. при любом изменении параметров выборки меняется её результат, и меняется кеш. Всё хорошо.&lt;/p&gt;
&lt;p&gt;Проблема №2. Сброс кеша&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Если данные в БД поменялись, надо сбросить соответствующий кеш (удалить ключ из мемкеша), чтобы пользователи увидели актуальную информацию. Знаем параметры выборки, строим ключ, удаляем его, при следующем обращении к кешу будет произведена выборка и построен новый кеш.&lt;/p&gt;
&lt;p&gt;Однако, этого не всегда достаточно. Например, у нас изменился объект XXX. Однако этот объект может являться частью большего числа выборок, например, входит в отдельную выборку объекта XXX (такой кеш легко очистить), а также может входить в различные списки, которые также закешированы. Сбрасывать все такие списки невозможно или даже неразумно. Было бы классно, если бы мемкеш мог "теггировать" ключи некоторыми метками и сбрасывать ключи с указанным набором меток, но эта операция вряд ли будет иметь сложность O(1), как другие его операции. В таких ситуациях сбросить кеш оказывается сложно, можно выставить таким кешам достаточно небольшое время жизни, чтобы неактуальная информация надолго не задерживалась.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description><category>memcached</category><category>php</category><category>smotri.com</category><category>кэширование</category><category>производительность</category><category>разработка</category><guid>http://www.smira.ru/posts/20080622web-cache-memcached-1.html</guid><pubDate>Sun, 22 Jun 2008 19:52:25 GMT</pubDate></item></channel></rss>