<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Блог Андрея Смирнова &#187; кеш</title>
	<atom:link href="http://www.smira.ru/tag/%d0%ba%d0%b5%d1%88/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.smira.ru</link>
	<description></description>
	<lastBuildDate>Wed, 24 Aug 2011 05:09:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Web, кеширование и memcached: часть 2</title>
		<link>http://www.smira.ru/2008/06/23/web-cache-memcached-2/</link>
		<comments>http://www.smira.ru/2008/06/23/web-cache-memcached-2/#comments</comments>
		<pubDate>Sun, 22 Jun 2008 21:02:33 +0000</pubDate>
		<dc:creator>Андрей</dc:creator>
				<category><![CDATA[Smotri.Com]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[кеш]]></category>

		<guid isPermaLink="false">http://www.smira.ru/?p=64</guid>
		<description><![CDATA[Начало серии постов здесь. Продолжаем разбираться с этим вопросом. Проблема №3. Одного мемкеша мало Если сайт большой, данных много, кешей тоже много, в один memcached физически не умещаемся. Пожалуйста: создаем кластер мемкешовых серверов, хешируем ключи для определения номера сервера, на котором ключ должен храниться. Всё вроде бы хорошо до тех пор, пока эти сервера не [...]]]></description>
			<content:encoded><![CDATA[<p>Начало серии постов <a href="http://www.smira.ru/2008/06/22/web-cache-memcached-1/">здесь</a>. Продолжаем разбираться с этим вопросом.</p>

<h2>Проблема №3. Одного мемкеша мало</h2>

<p>Если сайт большой, данных много, кешей тоже много, в один memcached физически не умещаемся. Пожалуйста: создаем кластер мемкешовых серверов, хешируем ключи для определения номера сервера, на котором ключ должен храниться. Всё вроде бы хорошо до тех пор, пока эти сервера не начинают падать или с ними не начинает теряться сетевая connectivity (что легко происходит, т.к. архитекутра кластерная, место на площадках ограничено, сервера физически разнесены, каналы забиты, ненадежны и т.п.) </p>

<p><span id="more-64"></span></p>

<p>Самый простой алгоритм хеширования вида:</p>

<pre><code>$memcache_server_id = crc32($key) % count($memcache_servers);
</code></pre>

<p>начинает &laquo;веселиться&raquo;, когда обнаруживает, что сервер упал. Когда обнаруживается проблема сетевого доступа к серверу, <a href="http://pecl.php.net/package/memcache">драйвер memcachа</a> убирает его из списка $memcache<em>servers. При этом count($memcache</em>servers) изменяется, какая-то часть ключей &laquo;сдвигается&raquo; на другие сервера, при этом &laquo;пропадает&raquo; куча кешей (хорошо, если кешей, которые не так жалко потерять, а если речь идёт о сессиях пользователей?).</p>

<p>Необходимо отметить, что та же самая проблема будет, когда мы вводим в строй или выводим из пула сервера мемкеша. Интересная математическая задача: если раньше было N серверов мемкеша и схема распределения ключей по серверам взятием остатка от деления на N (как написано выше), а после каких-то событий стало K серверов, то какой процент ключей останется на том же сервере, на котором они были до изменения количества серверов?</p>

<p>Когда куча ключей теряется, резко начинают перестраиваться кеши, вырастает нагрузка на БД, и т.д., и т.п., то есть падение одного сервера мемкеша заваливает весь &laquo;отказоустойчивый&raquo; кластер.</p>

<p>Что делать? Есть <a href="http://www.lastfm.ru/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients">другие алгоритмы хеширования</a> ключей, устойчивые к удалению/добавлению серверов в пул. Для <a href="http://pecl.php.net/package/memcache">PHP-шного модуля Memcache</a> это:</p>

<pre><code>ini_set('memcache.hash_strategy', 'consistent');
</code></pre>

<h2>Проблема №4. Одновременное перестроение кеша несколькими мордами</h2>

<p>Если мы выставляем ключу (кешу) некоторое время жизни, рано или поздно, memcache скажет, что такого ключа на сервере нет. А если это &laquo;популярный&raquo; кеш, например, использующийся на главной странице, то такую ситуацию могут &laquo;обнаружить&raquo; одновременно несколько морд. И они все попытаются построить этот кеш, то есть они все одновременно отправят запрос в БД, то есть они отправят <em>много</em> запросов в БД, причём за короткий промежуток времени. Конечно, как только первый запрос завершится, морда запишет новое значение ключа и больше новых запросов за этой выборкой не будет. Но мы уже подвергли БД высокой нагрузке, хотя хотели этого избежать при помощи кеширования.</p>

<p>Напрашивается решение: пока одна морда строит кеш, все остальные должны её &laquo;подождать&raquo;. Как это реализовать? Например, с помощью блокировок в том же мемкеше. Перед тем, как начать строить кеш для ключа mykey, проверяем, не выставлен ли уже ключ mykey_lock, если он выставлен, засыпаем и ждём некоторое время, что ключ исчезнет, если он исчез &#8211; пробуем снова прочитать mykey, если он появился (другая морда его построила), то берем готовое значение. Не появился за какой-то разумный промежуток времени &#8211; начинаем строить сами (значит, никто другой не смог построить значение этого кеша). </p>

<p>Перед тем, как сами начинаем строить кеш (например, если блокировки не было обнаружено), обязательно создаем блокировку: выставляем ключ блокировки mykey_lock, например, на 10 секунд, тем самым не подпуская другие морды к построению такой же выборки. Как выборку построили &#8211; записываем её в мемкеш, ключ блокировки удаляем.</p>

<p>Такая схема позволяет избежать части коллизий, который возникают при одновременном построении кешей.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.smira.ru/2008/06/23/web-cache-memcached-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

