Как правильно построить отказоустойчивый кластер memcached для хранения сессий PHP?
Есть много статей о том, как хорошо хранить сессии PHP в memcached. Именно к этому мы и идем.
Но я так и не нашел вменяемого ответа на следующий вопрос: Как правильно организовать инфраструктуру, чтобы она была отказоустойчивой, в случае падения одного из серверов, на котором крутится memcached?
Очевидно, что мы должны иметь как минимум два memcached сервера. Давайте сразу усложним задачу — мы их настроим 5 штук.
Предположим, что в сессии хранится ID залогиненного клиента. Если сессия умирает/пропадает/стирается — клиент сервером не опознается, т.е. клиент разлогинивается и ему приходится повторно авторизоваться.
Цель (напоминаю, что у нас 5 memcached серверов): в случае выхода из строя до 4-х серверов memcached клиенты не должны испытывать сложностей с авторизацией.
Сейчас я изложу ход моих мыслей, а вы, пожалуйста, меня поправьте и направьте на путь истинный :)
Т.к. система должна продолжать функционировать даже когда работает только один (любой из 5-ти) memcached серверов, то это означает, что хранимые в них данные должны быть задублированы.
Вопрос: Как этого добиться?
Покопался с memcached и нашел интересные ключи:
-x <ip_addr> hostname or IP address of peer repcached
-X <num:num> TCP port number for replication. <listen:connect> (default: 11212)
Таким образом я даже настроил два memcached сервера. -x настроил, чтобы они указывали друг на друга. И действительно — можно записать ключ на один сервер, а получить значение уже с другого. Не тестировал насколько быстро происходит репликация, но она действительно работает.
Таким образом задача для двух серверов решается просто.
А что делать, если серверов больше двух? Строить цепочку? Первый указывает на второй, второй на третий и т.п. Но ведь если второй упадет, то первый о третьем ничего не узнает?
Вот в этом месте я и застрял :)
Может быть я вообще копаю не в ту сторону?
Напомню, что цель следующая: хранить сессии PHP на нескольких memcached серверах, чтобы, даже если остался жив только один из них, ни одна сессия не потерялась.
Handlersocket для MySQL работает быстрее, чем memcache. Используем Galera Cluster for MySQL для репликации данных и получаем искомый производительный отказоустойчивый кластер.
Никак, кроме как дублировать данные на разные серверы на прикладном уровне.
Либо использовать другой продукт (благо, альтернатив море).
Почитайте здесь.
«Совсем не должны терять». Memcached удобен для хранения сессий пользователей – все сессии равнодоступны со всех серверов, входящих в кластер frontend’ов. Так вот содержимое сессий не хотелось бы терять никогда – иначе пользователей на сайте будет «разлогинивать». Как попытаться избежать? Можно дублировать ключи сессий на нескольких серверах memcached из кластера, так вероятность потери снижается.
Вот я и хочу дублировать ключи сессий на нескольких серверах memcached из кластера… Но в статье не рассказано, как это правильно делать?
Как вариант — это написать свой session handler и все сессии писать на все доступные memcached сервера.
Хорошо, запишем.
Но я совершенно забыл о дальнейшей судьбе сессий — с какого севера их читать? Если часть memcached будет недоступна, то нужно автоматически выбирать доступный. Т.е. нужен как-нибудь балансировщик. Тут вроде проще, haproxy или nginx должны помочь.
А теперь подумаем дальше. Если сессии мы пишем на все memcached сервера, но если один из них на время выйдет из игры, то он будет рассинхронизирован по отношению к остальным. Т.о. очередной вопрос — как его снова полностью синхронизировать с остальными?
Да никак, как то memcached не очень для таких вещей. Используйте альтернативные решения с репликацией из коробки, это выйдет дешевле чем написать кучу скриптов для отказоустойчивого memcache
Mika Wow: не коробочное решение , а любое решение которое поддерживает отказоустойчивость из коробки, редисы, монги, мускулы, в крайнем случае даже сетевая файловая система не так уж плоха.