Comments 42
Возможно не в тему вопрос.
Не могли бы вы порекомендовать книги (или какие-либо другие ресурсы) по highload-у для начинающих?
Не уверен, что есть такие книги, ибо каких-то специфических знаний для работы с highload обычно не требуется. Намного более важную роль играет квалификация разработчика и опыт работы. Ну а опыт работы сложно чем-то заменить, ИМХО.
Это да, но не помешал бы place to start — набор каких-то базовых принципов. Ну например проверка целостности данных при highload-е невозможна средствами СУБД, т.к. сами данные разнесены по нескольким серверам. Разбиение данных по спотам и т.п. Насколько я понимаю это базовые принципы построения горизонтально масштабированных систем, но в первый раз они могут показаться совсем неочевидными
Я к примеру прочитал множество разрозненной информации в блоках, документации, просмотрел видео с конференций, но все равно осталось чувство, что я возможно что-то упустил
Тот же Badoo часто проводит на различных конференциях мастер-классы по хай-лоад. Проводит Алексей Рыбак. Я был в этом году на PHPConf, превосходный семинар (на весь день почти). Очень рекомендую посетить при возможности — не пожалеете нисколько. На самом деле крутая инфа, разжёванно и понятно.
highload — это на 90% масштабирование, то есть возможность ускорить приложение, добавив больше серверов.
Например есть у тебя сервер с тормозящей базой данных. Ты ставишь рядом вторую, переносишь часть данных (шардинг) или делаешь полную копию данных (репликация) на втором сервере — и твоя систем начинает работать быстрее.
Или например есть у тебя тормозящий сервер обрабатывающий HTTP-запросы юзеров — ставишь рядом второй такой же и пускаешь туда половину юзеров — и твоя система ускоряется.
В книге такое сложно описать потому что сложно придумать какую-то универсальную систему и дьявол скрывается в деталях
Да, скорее всего поэтому мне и не удалось найти подобной книги.
Не могли бы вы ответить на два вопроса:
1) Каким образом у пользователей отображается количество непрочитанных сообщений? При посылке нового сообщения увеличивается соответствующий счетчик у пользователя, которому оно отправляется или кол-во каким-то образом высчитывается на лету?
2) В статьях рассматриваются варианты хранения сессии пользователя. В основном предлагается выделить под нее отдельный сервер. Не будет ли этот сервер SPOF (single point of failure) и общим узким местом в системе (ведь данные из него потребуются всем остальным серверам)? Как у вас решается такой вопрос?
1. да, счетчик в базе
2. ну конечно же серверов можно (и нужно) ставить несколько. Например завести 5-10 серверов с memcache или redis или mysql handler socket или что-то похожее и рапределять все сессии между этими серверами.
Если я правильно понял, то данные о сессиях хранятся не на всех серверах сразу, а распределены по ним. Как сервер, которому понадобилась информация о сессии, узнает к какому серверу сессии ему обращаться? Есть некоторая настроечная информация о связке {пользователь-сервер} и она хранится на всех серверах?
Что будет если один из этих серверов упадет? Данные о сессиях потеряются или они дублируются в базе?

Заранее спасибо за ответы

На твои вопросы нет однозначных ответов. Есть варианты из которых надо выбирать
Например некоторые стартапы настраивают свои лоад-балансеры так чтобы один и тот же юзер всегда попадал на один и тот же сервер и сессии хранят прямо на этом сервере в памяти приложения (особенно это любят java/scala разработчики)
> Как сервер, которому понадобилась информация о сессии, узнает к какому серверу сессии ему обращаться?
можно закодировать id сервера в session_id
>Что будет если один из этих серверов упадет? Данные о сессиях потеряются или они дублируются в базе?Зависит от того что выберете и как напишите. Если сессии в памяти хрянились (мемкеш) — то юзерам прийдется заново авторизоваться. Если redis / mysql — то ждать пока они перезапустятся. В mysql можно настроить репликацию
Вобщем вариантов много
>> один и тот же юзер всегда попадал на один и тот же сервер
И при падении этого сервера некоторый % пользователей 100% не смогут попасть на сайт пока балансер не выкинет упавший backend?
При равномерном распределении хотя бы" животворящий F5" сможет хоть как-то на это время разгрести затруднительную ситуацию.

А вот по сессиям, хранящимся в репликации, интересный вопрос появляется, когда сервера находятся в разных датацентрах в разных странах и появляется неприятное отставание.
И при падении этого сервера некоторый % пользователей 100% не смогут попасть на сайт пока балансер не выкинет упавший backend?

Это одна из причин для нас так не делать :).

А вот по сессиям, хранящимся в репликации, интересный вопрос появляется, когда сервера находятся в разных датацентрах в разных странах и появляется неприятное отставание.

Что касается Badoo, то датацентр, в который попадает пользователь, у нас однозначно определяется из его IP (по стране).

То есть, если (не дай бог) один из наших двух датацентров «ляжет», то для половины пользователей ничего не будет показываться. Но репликация данных в другой датацентр у нас есть, поэтому данные потеряны будут только те, которые ещё не успели отреплицироваться.
На мастер-классе Алексея Рыбака об этом рассказывается более подробно :). Я пересказывать всё не хочу и не могу, но смысл в том, что у нас своя репликация для БД. Она сделана очередях на простых SQL-запросах и PHP-скриптах, которые по крону перегоняют записи в другой ДЦ.
Насколько я знаю, когда это писалось (году этак в 2006), не было никакого «коробочного решения» :).
И при падении этого сервера некоторый % пользователей 100% не смогут попасть на сайт пока балансер не выкинет упавший backend?
Я не пробовал этот метод на практике. Скорее всего да.
А вот по сессиям, хранящимся в репликации, интересный вопрос появляется, когда сервера находятся в разных датацентрах в разных странах и появляется неприятное отставание.

Если речь идет именно о сессии, то она нужно только в том датацентре, которым сейчас пользуется данный юзер. В других датацентрах она попросту не нужна. Бывают редкие случаи, когда юзера на средиректить в другой датацентр. В этом случае после редиректа можно запросить один раз сессию из старого датацентра и сохранить в новом. Запрос в другой датацентр — операция конечно медденная, но не смертельно. Тем более что ситуация такая возникает у малого кол-ва людей
>И при падении этого сервера некоторый % пользователей 100% не смогут попасть на сайт пока балансер не выкинет упавший backend?

У Badoo, может быть, теряются такие запросы, но вообще nginx позволяет при получении ошибки с апстрима обратиться к следующему.
nginx.org/ru/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
backend-ы падают по-разному
Если backend не принимает запросы, то тут все просто — выбираем следующий backend
Если же backend принял запрос, но ответил ошибкой, то не факт что запрос можно отправить на следующий backend. Например backend принял запрос на отсылку сообщения пользователю, сохранил сообщение в базе, но потом по какой-то причине упал например в core dump уже после коммита в базу. Если такой запрос переадресовать на следующий бекенд — в базу сохраняться 2 сообщения.
Вообще говоря, это вопрос выбора: либо мы допускаем потерю пользовательских запросов (что для всяких ajax'ов может быть болезненно), либо теоретическую возможность удвоения некритичных запросов. При этом первый трудно обнулить на уровне приложения, а последний вполне реально.

В вашем примере, скорее всего, отсылка сообщения идёт отложенно или через внешний для fpm-а сервис. В обоих случаях после всяческих проверок будет простая отсылка сообщения в 1 сервис, сразу после которой выдача ответа клиенту. Так что вероятность ошибки в промежутке между сохранением и отдачей ответа пренебрежимо мала, тогда как вероятность проблем при старте, работе с внешними сервисами итп вполне осязаема.
Я привет гипотетический пример который может случиться. Возможно что его и можно решить на уровне приложения, но в условиях дедлайна мало кто будет писать _php_-код из расчета на то что php-процесс может умереть в любой момент.
PHP — не самый качественный язык. Иногда php-процессы падают в корку в самых разных местах (eacellerator, debug_backtrace, array_map, различные экстеншены не входящие в стандартный php)
У нас даже небольшой скрипт написали который собирает корки со всех машин и в веб-интерфейсе показывает trace из gdb :)
Но в целом согласен — это вопрос выбора.
По-моему много воды в статье, вроде начинали про код, закончили всем остальными узлами хайлоада, а каждый вопрос требует большой отдельной статьи если писать для новичков, а статья видимо на них направлена.

Какой-то интересной конкретики не увидел.
Не волнуйтесь, отдельные статьи тоже будут, со временем :). Считайте это вводной статьей.
Код должен быть надежным, потому что должен быть хорошим. Хорошим он должен быть, чтобы быть надежным. Ошибки надо видеть и исправлять. Небо синее, вода мокрая, зима холодная.

:) А по существу что-нибудь?
Я согласен, этот список рекомендаций абсолютно очевиден для любого человека с опытом работы в более-менее большом проекте :). Но такой опыт есть не у всех, поэтому, я надеюсь, статья кому-то была полезна.

В следующих статьях будут подробности, я гарантирую это :).
к сожалению, для тех, у кого нет опыта — это и не будет полезным, т.к. пока не пощупаешь эти проблемы руками, не поймешь зачем же это все делается.
Статья про «Fragile Code», который на хайлоад проекте может привести к отказу в обслуживании.
Надо бы добавить про требования, пренебрежение которыми и приводит к написанию хрупкого кода, который всегда ломается.
Это все конечно хорошо, но было бы отлично с примерами и ближе к продакшну так сказать. Какие то вещи, по типу последнего с rm -rf добавьте в следующей статье, если таковая будет. Тем более мы все знаем, что у вас хорошо получаются технические статьи по вашему сервису;)
Очередная вводная статья. Если реально много практического опыта — вот он будет интересен, вдруг что новое проскочит.
Статья очень содержательная: ловите и фиксите ошибки, следите за таймаутами внешних запросов. Пример про число строк надуман. Рекомендация про контрольные суммы при дедуплицировании не требует отдельного внимание программистов: либо хранилища имеют явную зависимость (например, БД и кеш) и поддержка идёт на уровне базового кода проекта, либо консистентность должно поддерживать используемое ПО и немногочисленные сервисные скрипты. О самой мякотке надёжного распределённо исполняемого кода хайлоада — локах, транзакциях итп — ни слова.

Кстати, у вас вроде при вашем надёжном коде на этих выходных не работала авторизация через Facebook. :)
О самой мякотке надёжного распределённо исполняемого кода хайлоада — локах, транзакциях итп — ни слова.

Как уже говорили выше, об этом всём на многих конференциях рассказывает Алексей Рыбак в виде мастер-класса на целый день (около 8 часов). Как вы сами понимаете, в рамках одной статьи я об этом рассказать даже при всём желании бы не смог :).

Про авторизацию через Facebook, к сожалению, не могу ничего сказать — исходя из наших графиков, на выходных всё было в пределах нормы. Скорее всего это не из-за ненадежного кода, а каких-то особенностей, связанных с вашим конкретным профилем, которые у нас не учтены. Помимо этого, вполне возможно, что испытываемые вами проблемы с авторизацией были по вине Facebook ;).
А мне вот интересна оптимизация SQL запросов. Мало где об этом пишут. Можно легко составить вложенный запрос со множеством join условий и сортировок. Но как и что там можно оптимизировать?! Было бы интересно почитать об этом.
На этот вопрос ответ очень простой: в веб-части мы не используем сложные SQL-запросы. Вложенные запросы запрещены, обычно встречается не более, чем 2-3 джойна. Если и эти запросы тормозят, то ставятся простые индексы, если и это не помогает, то EXPLAIN и несколько других методик :). Об оптимизации одного из таких запросов у нас есть статья.
Я бы еще добавил две техники, сервисы должны быть по возможности независимы и gracefull degradation которые когда-то подсмотрел у NetFlix. Вы можете упустить при выкатке новой версии медленный скрипт, или проблемы с оборудованием возникнут, нужно иметь возможность отключить затронутые проблемой службы. Еще эта техника полезна для неожиданных пиковых нагрузок, когда можно отключить все менее приоритетные службы чтобы сайт не лег под нагрузкой.
мы обычно включаем новые услуги сначало в какой-то одной/нескольких странах. Смотрим статистику, реакцию юзера на новую фичу, дорабатываем, оптимизируем и постепенно добавляем страны. Выкатывать новую фичу сразу везде — безумие
Only those users with full accounts are able to leave comments. Log in, please.

Information

Founded
2006
Location
Россия
Website
badoo.com
Employees
501–1,000 employees
Registered

Habr blog