Подтвердить что ты не робот

Memcached для PHP и перехода на другой ресурс

Мы развертываем memcached для нашего приложения, и я хотел бы сделать его как можно более стойким.

Мы планируем использовать расширение memcacheD.

Одна вещь, которую я не полностью понял, - это то, что произойдет, если один из серверов погибнет. По крайней мере, похоже, что клиент memcached просто "отказывается" на этом сервере и ничего не хранит в нем.

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

Так как это не происходит автоматически; Я предполагаю, что единственный способ подойти к этой проблеме - заставить внешнюю систему выполнять проверки работоспособности в системах memcached и соответствующим образом обновлять список серверов.

Но если есть список из 10 серверов, и, скажем, пятый умирает.. даже с хетами Ketama казалось бы, что это вызовет большое перераспределение ключей (это просто основано на здравом смысле).

В идеале я просто хотел бы, чтобы расширение PHP выясняло, что сервер выключен, отметьте его в течение указанного количества времени (10 минут), и в течение этих 10 минут отходят на другие серверы (красиво распределенные) для устанавливает и получает.

Как другие люди решают это?

Изменить: уточнение моей точки libketama.

Скажем, у нас есть 10 серверов:

1,2,3,4,5,6,7,8,9,10

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

1,2,3,4,inactive,6,7,8,9,10

НО: если мы предоставляем и управляем этим списком вручную, это не так:

1,2,3,4,6,7,8,9,10 // There are now 9 servers!

6 получит 5 предыдущих ключей, 7 - 6. 8 получит 7, 9 получит 8 и 10 получит 9 очков. Все хиты, которые использовали 10-й сервер, не будут распределены между остальными. Результатом является высокая вероятность того, что почти 50% всех ключей будут отправлены на новые серверы.

4b9b3361

Ответ 1

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

Я бы избегал использовать новое расширение PHP или пытаться добавить новое программное обеспечение в стек развертывания. Вероятно, вы уже используете что-то для мониторинга (nagios?). При вызове простого PHP script на каждом из ваших веб-серверов, чтобы настроить список в памяти, кажется лучшим выбором.

Стоит отметить, что в системе хеширования Ketama удаление сервера от вращения приведет к тому, что его ключи будут повторно удалены в другом месте на кольце (континуум), другие серверы не будут видеть свои ключи, назначенные в другом месте. Визуализируйте его как круг, каждому серверу назначено несколько точек на круге (100-200). Ключи хэшируются по кругу и продолжаются по часовой стрелке до тех пор, пока они не найдут сервер. Удаление сервера с ринга приводит к тому, что эти значения продолжают немного дальше, чтобы найти новый сервер. Если повезет, распределение значений равномерно удалит остальные серверы.

Демонстрация системы хэширования:

<?php


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);


$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

$key = uniqid(); //You may change this to md5(uniqid()); if you'd like to see a greater variation in keys. I don't think it necessary.
$m->set($key, $key, 5);


var_dump($m->get($key));

unset($m);


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//one server removed. If assignment to the continuum is dependent based on add order, we would expect the get call here to fail 90% of the time, as there will only be a success if the value was stored on the first server. If the assignment is based on some hash of the server details we'd expect success 90% of the time. 
$m->addServer('localhost', 11211);
//$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//2 servers removed
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
//$m->addServer('localhost', 11213);
//$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//Out of order
$m->addServer('localhost', 11210);
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11213);

var_dump($m->get($key));

unset($m);

Если система хэширования заботится о порядке или опускаемых серверах, мы ожидаем получить bool(false) на большинстве вторичных примеров, поскольку ранний сервер был удален и т.д. Однако, основываясь на моих быстрых, совершенно ненаучных тестах, я только получайте bool false в любом конкретном слоте один раз в 10. Я, очевидно, только что запустил 10 серверов на своем тестовом поле. Предоставляя каждому из них только 4 мб барана

Ответ 2

Возможно, вы захотите попробовать константу параметра Memcached::OPT_AUTO_EJECT_HOSTS для PHP. Он не задокументирован, но есть комментарий здесь, называя его.

(Я не пробовал, поэтому не могу сказать, будет ли это работать или нет)

Ответ 3

Основываясь на ответе на комментарии, я бы предложил следующее:

Вам нужно будет создать класс кэширования.

Этот класс будет содержать следующую информацию:

  • Список серверов кешей

    • Статус для онлайн или офлайн
    • Количество запросов на этот сервер
  • Список сохраненных ключей и на каком сервере он находится

Далее вам понадобятся стандартные функции для добавления, обновления и удаления ключей.

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

Если это не на сервере, выберите сервер с наименьшими запросами, чтобы сохранить его после получения фактического значения DB.

Если какая-либо из этих функций возвращает ошибку с кеш-сервера, я бы пометил этот сервер как offline, reset счетчик и удалил все ключи из списка, расположенного на этом сервере.

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

Ответ 4

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

  • Как вы определяете, какой сервер жив и кто умер? вы должны каким-то образом синхронизировать между всеми вашими модулями HA, работающими с серверами веб-приложений и приложений.
  • Как вы публикуете эту информацию между серверами веб-приложений/приложений
  • У вас будет оркестр?

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

Что касается других вопросов, которые обсуждались здесь:

  • Когда вы теряете node, вы теряете 1/N ваших ключей, где N - количество узлов, которые вы изначально имели, то есть включая сбой node. Вот как работает Ketama.
  • Хранение ключей на клиенте Memcached с использованием нового класса Memcached, безусловно, не способ (IMO): (1_, где вы собираетесь сохранять все эти ключи?) (2) как вы синхронизируете между своими веб-узлами/приложениями? (3), сколько времени вам потребуется, чтобы получить доступ к этим структурам данных, чтобы понять, на каком этапе node проживает каждая клавиша? - вот почему Memcached полностью основан на хеш-функции, чтобы сделать ее быстрой и простой.

И последнее, но не менее важное: я бы посоветовал вам также проверить решения Memcached as-a-service. Например, мы в Garantia Data уже решили проблемы HA Memcached.

Раскрытие информации: я являюсь соучредителем и техническим директором данных Garantia.