Веб-кластер - репликация, чтение со слейва, сессии и кэш
Разносим сайт на несколько серверов: разбираем репликацию базы, чтение со слейва, хранение сессий и распределённый кэш вместе с порядком запуска.
Механика
Кластер собирается штатным модулем и живёт в старших редакциях продукта. Он даёт репликацию базы с балансировкой чтения, распределённый кэш, хранение сессий вне файловой системы и вертикальный шардинг.
Репликация базы делит нагрузку по типу выполняемой операции. Запись всегда идёт в мастер, а чтение балансировщик отправляет на слейвы, пока данные не менялись.
После записи в мастер чтения того же запроса идут из мастера. Репликация отстаёт, и вернувшийся со слейва ответ мог бы не увидеть только что записанное.
Свои изменения данных оборачивают явным признаком работы только с мастером. Иначе одна запись в начале запроса переводит на мастер весь запрос целиком - это и называют срывом конвейера.
Порог допустимого отставания слейва задают явно в настройках. При превышении узел автоматически исключается из балансировки, и рассинхронизация не превращается в показ старых данных.
Сессии посетителей в кластере не могут жить в файловой системе. Запросы одного посетителя приходят на разные узлы, и файловая сессия теряется вместе с авторизацией.
Хранят сессии в базе, в памяти или привязывают посетителя к узлу. Память быстрее базы, а привязка на балансировщике дешевле обеих, но переживает не всякую перебалансировку.
Распределённый кэш кластера требует согласованного хеширования ключей. Без него отказ одного узла кэша перетасовывает ключи и превращается в массовый промах и всплеск нагрузки.
Адрес мастера в настройках указывают явным сетевым адресом узла. Локальный адрес на каждом сервере означает собственную базу вместо общей, и это ломает всё разом.
Добавление слейва к большой базе требует отдельной подготовки. Живой запуск репликации на нагруженном проекте останавливает его, поэтому узел поднимают из дампа.
Проектируют кластер от характера нагрузки, а вовсе не от числа серверов. Упор в процессор лечится узлами веб-сервера за балансировщиком, упор в базу - репликацией, а интенсивный кэш - памятью на каждом узле.
Отсюда и типовые схемы: полные узлы дают простую отказоустойчивость, раздельные узлы - гибкое масштабирование по слоям, а разнесение по площадкам добавляет устойчивость к падению целого дата-центра.
Шаги
- Определить, во что упирается площадка: в процессор, в базу или в кэш.
- Поднять слейв из дампа, а не включать репликацию на живой базе.
- Указать сетевой адрес мастера явно во всех настройках всех узлов.
- Задать порог отставания слейва и проверить его автоматическое отключение под нагрузкой.
- Перенести сессии из файлов в память или в базу в тихое окно.
- Настроить распределённый кэш с согласованным хешированием ключей на каждом узле.
- Закрыть служебные порты узлов кластера от внешней сети.
Код
Смотрим, куда идут запросы:
$conn = \Bitrix\Main\Application::getConnection();printf("узел=%s\n", $conn->getHost());// в кластере хост меняется в зависимости от типа операции// после первой записи в запросе чтения продолжаются с мастера// список узлов и их состояние видны в разделе веб-кластераПроверка показывает, какой узел обслуживает текущий запрос. На кластере это первое, что смотрят при жалобе «данные показываются старые».
Ограничиваем свои изменения мастером:
$conn->useMasterOnly(true);$conn->query('UPDATE b_vendor_counter SET HITS = HITS + 1 WHERE ID = 1');$conn->useMasterOnly(false);// без этой обёртки одна запись переводит на мастер весь запрос целиком// читать записанное сразу же не стоит: слейв ещё не догнал мастераПризнак работы только с мастером включают точечно вокруг записи. Служебная запись счётчика в начале страницы без такой обёртки лишает слейвы всей выборочной нагрузки этой страницы.
Смотрим отставание слейва со стороны базы:
mysql -h 10.0.0.9 -e "SHOW SLAVE STATUS\G" | grep -E 'Seconds_Behind_Master|Slave_(IO|SQL)_Running'# отставание в секундах и признаки работы обоих потоков репликации# растущее отставание означает, что слейв не успевает за мастеромОтставание смотрят и в административной части, и на самой базе. Первое говорит, что решила платформа, второе - что происходит на сервере, и расходятся они чаще, чем хотелось бы.
Переносим сессии в память:
'session' => ['value' => [ 'mode' => 'default', 'handlers' => ['general' => [ 'type' => 'redis', 'servers' => [['host' => '10.0.0.7', 'port' => '6379']], ]],]],// переключение режима хранения обнуляет все текущие сессииСмена хранилища сессий выкидывает всех текущих посетителей разом. Делают её в окно наименьшей активности и предупреждают тех, кто в это время работает в административной части.
Настраиваем распределённый кэш:
; php.ini на каждом узлеmemcache.hash_strategy = consistent; память наращивают шагами, а попадание в кэш держат близко к сотне процентовСогласованное хеширование ключей кэша по умолчанию выключено везде. Без него потеря одного узла кэша означает промах почти по всем ключам и мгновенный рост нагрузки на базу.
Снимаем блокировку сессии на страницах с частыми запросами:
define('BX_SECURITY_SESSION_READONLY', true); // сессия не блокируется// параллельные запросы перестают выстраиваться в очередь// в этом режиме изменения сессии не сохраняются в конце запросаОбработчик сессий блокирует её файл на время запроса. Страница с десятком одновременных обращений выстраивает их в очередь, и несколько посетителей занимают все процессы.
Закрываем служебные порты:
ss -lntp | grep -E '11211|30865|3306'# наружу открыты только 80 и 443 на балансировщике# прямой доступ к узлам, кэшу и базе закрывают правилами сетиУзлы кластера рассчитаны на работу в закрытой внутренней сети. Открытый наружу кэш или база - это не теоретический риск, а типовой способ потерять данные вместе с сессиями.
Ограничения
Кластер доступен далеко не во всех редакциях самого продукта. Полная схема с двумя мастерами живёт в старшей редакции, и планировать её стоит с учётом лицензии.
Горизонтального шардинга в самом продукте попросту нет. Доступен только вертикальный и только для двух модулей, а масштабирование остальных данных решается репликацией.
Производительность растёт не линейно. На больших объёмах данных каждый следующий узел даёт меньше прежнего, поэтому оборудование берут с запасом.
Кластер усложняет эксплуатацию. Выкладка, резервные копии и обмен с учётной системой становятся сложнее, и эту работу учитывают заранее.
Типичные проблемы
После входа на сайт посетителя выкидывает случайным образом.
Сессии остались в файловой системе, а запросы приходят на разные узлы. Сессию переносят в общее хранилище или жёстко привязывают посетителя к узлу.
Слейвы простаивают, вся нагрузка на мастере.
В начале запроса выполняется служебная запись без обёртки для работы с мастером. Одна такая запись переключает на мастер весь запрос страницы целиком.
Посетители видят устаревшие данные.
Слейв заметно отстал от мастера, а порог отставания в настройках не задан. С заданным порогом отставший узел исключается из балансировки чтения полностью автоматически.
После отказа одного узла кэша нагрузка выросла в разы.
Не включено согласованное хеширование. При отказе одного узла ключи перетасовываются, и кэш промахивается почти целиком.
Проект встал при добавлении второго узла базы.
Репликацию включали прямо на живой и нагруженной базе. Слейв поднимают из готового дампа и добавляют в кластер уже подготовленным.
Частые вопросы
Нужен ли кластер, если сайт тормозит?
Сначала выясняют причину: чаще это запросы и кэш, а не нехватка серверов. Кластер на неоптимальном коде повторяет проблему на каждом узле.
Где хранить сессии в кластере?
В памяти на выделенном узле или в базе. Файлы не годятся, а привязка к узлу на балансировщике решает задачу проще, но переживает не всякое изменение состава узлов.
Почему после записи чтение идёт с мастера?
Репликация всегда отстаёт, и чтение со слейва вернуло бы данные до записи. Платформа переключает такой запрос на мастер намеренно.
Можно ли балансировать чтение без кластера?
Нет, распределением занимается именно модуль кластера. Своя балансировка мимо него ломает согласованность данных при записи.
Как проверить, что кластер работает?
По состоянию узлов в административной части и по нагрузке на серверах. Мастер под записью и слейвы под чтением дают заметно разные показатели.
Смежное
- BitrixVM и веб-окружение - оглавление подтемы
- Вынос базы и кэша на отдельные машины: когда и как - первый шаг перед кластером
- Кэш и сессии в памяти: memcached, Redis, проверка и отказ - настройка хранилищ
- Нагрузочное тестирование: сценарий, расчёт, чтение результатов - проверка перед масштабированием
- Сайт тормозит: разбор причин по убыванию частоты - что чинят до покупки серверов
- Мониторинг сервера: что смотреть до того, как сайт упадёт - наблюдение за узлами
- Веб-кластер 1С-Битрикс: репликация, memcached, сессии - устройство модуля целиком
- Инфраструктура и хостинг - устройство площадки целиком
- Сайт на нескольких веб-узлах: балансировщик и общие файлы - файловая и сетевая половина кластера