Эволюция Архитектуры: От Самописных Сервисов К Handlersocket



Эволюция архитектуры: от самописных сервисов к HandlerSocket

Сегодня мы поговорим о том, как Badoo изменила свой подход к проектированию нагруженных сервисов «ключ-значение».

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

что возникло.

Современные интернет-проекты активно используют внутренние сервисы, позволяющие получать доступ к значениям по ключу.

Это могут быть как готовые решения, так и собственные разработки.

С 2006 года специалисты Badoo создали ряд подобных сервисов, среди которых:

сервис, сообщающий местонахождение пользовательских данных по идентификатору пользователя; сервис, хранящий информацию о количестве посещений профиля пользователя; список интересов пользователя; несколько «геосервисов», позволяющих определить местоположение пользователя.

Несмотря на их разнообразие, был использован единый подход к проектированию, согласно которому сервис должен состоять из следующих компонентов: База данных репозитория, в которой хранится эталонная версия данных.

Быстрый демон на C или C++, который обрабатывает запросы на данные и обновляется вместе с базой данных репозитория.

Классы PHP, обеспечивающие работу с демоном и базой данных репозитория.

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

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

В конце 2010 года ОбработчикSocket Плагин MySQL, написанный Японский мастер , который обеспечивает интерфейс NoSQL для данных, хранящихся в MySQL. Уже весной 2011 года специалисты Badoo обратили внимание на новую технологию, надеясь с ее помощью упростить разработку и поддержку «ключевых» сервисов компании.



«Первая жертва»

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

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

Соответственно, вам необходимо где-то хранить настройки почты и предоставлять доступ к этим данным.

Более 99% запросов к ним — это запросы на чтение.

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

Сначала для хранения данных использовалась только база данных, но она уже не справлялась с постоянно растущим количеством запросов на чтение.

Чтобы разгрузить эту нагрузку, был создан специальный демон — EmailNotification.

Реализация услуги «старой школы»

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

Поначалу архитектура сервиса была достаточно простой и выглядела так:

Эволюция архитектуры: от самописных сервисов к HandlerSocket

Настройки постоянно хранились в базе данных на одном сервере БД, а C-демон запускался на другом.

При запуске демон выбрал все данные из базы данных и построил по ним индекс ( Джуди массивы ).

Процесс инициализации занял около 15 минут, но поскольку за все время существования сервиса данная операция требовалась всего несколько раз, это не было существенным недостатком.

В процессе работы клиенты (CLI-скрипты, веб- и другие сервисы) через специальный API обращались к демону, например, с вопросом, можно ли этому пользователю отправить это письмо или нет, и демон, используя встроенную логику, искал установил в свою память и дал ответ. «Клиенты-писатели» приказали демону изменить определенные настройки для конкретного пользователя.

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

Пока в 2007 году у Badoo не произошла «маленькая неприятность», а именно, появился второй дата-центр, географически удаленный от первого и предназначенный для обслуживания пользователей в Новом Свете.

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

Поскольку письма одному и тому же пользователю можно отправлять с обеих платформ, требуется, чтобы оба сервиса работали с одними и теми же данными.

К счастью, специально для таких случаев в компании существует система событий CPQ (CPQ — Cross Platform Queue, кроссплатформенные очереди.

— Прим.

автора), которая позволяет быстро, а главное — надежно и в заданной последовательности передавать информацию.

о событиях между сайтами.

В результате на двух площадках архитектура сервиса приняла следующий вид:

Эволюция архитектуры: от самописных сервисов к HandlerSocket

Теперь любые запросы на запись отправлялись не только в базу данных и C-демон локального сайта, но и в CPQ. CPQ перенес запрос в соседнюю очередь другого сайта, и эта очередь уже воспроизвела запрос на запись через API EmailNotification на том же сайте.

Система усложнилась, но тем не менее продолжала стабильно работать несколько лет. И все было бы хорошо, если бы на сайтах не было расхождений в данных.

Две базы доступных сайтов имели разное количество настроек.

И хотя разница составила менее 0,1%, ощущения «чистоты и безопасности» уже не было.

Более того, мы обнаружили, что разница проявляется не только между базами сайтов, но и между базой и C-демоном внутри одного сайта.

Пришлось думать о том, как сделать сервис более надежным.



Новый подход

Изначально к сервису EmailNotification предъявлялось два основных требования: во-первых, высокая скорость обработки запросов на чтение, с которой C-демон справлялся очень хорошо; второе — идентичность данных на обоих сайтах, с чем были проблемы.

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

Эволюция архитектуры: от самописных сервисов к HandlerSocket

Первым делом мы подключили плагин HandlerSocket к MySQL и научили наш API работать с базой данных через него.

Благодаря этому мы смогли отказаться от использования C-daemon. Затем, упростив API, мы удалили из схемы сервис CPQ, заменив его хорошо зарекомендовавшей себя репликацией «мастер-мастер» между площадками.

В результате мы получили очень простую и надежную схему, имеющую следующие преимущества:

  1. Репликация осуществляется прозрачно; нет необходимости писать код, работающий с внутренней службой CPQ. При этом задержка при передаче обновлений между сайтами сокращена с нескольких секунд до долей секунды.

  2. Атомарность записи данных (наконец-то!).

    Если запрос API EmailNotification на запись в HandlerSocket успешен, то задача выполнена, запись точно дублируется на другом сайте, и нам не нужно сообщать об этом никаким другим компонентам.

Были ли у нас проблемы с переходом на новую схему? Серьезных нет. AUTO_INCREMENT уже поддерживается плагином HandlerSocket, составные индексы работают, ENUM тоже, нам просто пришлось отказаться от значения CURRENT_TIMESTAMP по умолчанию для одного из полей метки времени.

Как известно, преимуществом HandlerSocket является не скорость работы — она скорее приемлемая, чем впечатляющая, а способность стабильно работать при большом количестве запросов в единицу времени.

Учитывая, что сервис на данный момент обслуживает всего 2 — 2,5 тысячи запросов в секунду на одном сайте, у нас есть большой запас прочности.

Но для особо интересующихся скоростью работы плагина HandlerSocket вот график со средним временем выполнения трёх команд: подключение к HandlerSocket, открытие индекса и получение из него данных (значения по оси Y в миллисекундах) :

Эволюция архитектуры: от самописных сервисов к HandlerSocket



Последнее слово

За последний год в Badoo появилась тенденция использовать HandlerSocket в качестве репозитория «ключ-значение» с постоянным хранилищем данных.

Это позволяет нам писать более простой и понятный код, освобождает программистов C от работы над тривиальными задачами и значительно упрощает поддержку.

И пока все говорит о том, что движение в этом направлении будет продолжаться.

Но не думайте, что использование HandlerSocket внутри Badoo ограничивается простыми задачами.

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

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

Спасибо! Теги: #badoo #badoo #MySQL #handlersocket #replication #master-master #replication #Высокая производительность #Разработка веб-сайтов

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.