Tarantool — это СУБД с открытым исходным кодом. Кто угодно может скачать её с GitHub и использовать как в коммерческих приложениях, так и в некоммерческих. Сегодня технический директор Почта@Mail.ru Денис Аникин расскажет о примерах использования этой базы данных. Материал подготовлен по мотивам выступления на конференции FailOver Conference.
Tarantool разрабатывается в Mail.Ru Group уже больше семи лет. Эта СУБД рассчитана на высоконагруженные системы. Её основное отличие: это база данных, которая сочетает в себе свойства настоящей БД — транзакции, репликации, всё что касается надежности, — но при этом она такая же быстрая, как и кэши, например, Memcached или Redis.
В Mail.Ru Group добрая половина продуктов работает на Tarantool. Ему отдаётся предпочтение в тех случаях, когда от СУБД требуются свойства кэша, то есть она должна уметь делать 100 тыс. апдейтов в секунду, у нее должно быть очень хорошее latency — 1 мс или меньше — и так далее. Многие СУБД не удовлетворяют этим критериями. Если используется много шардов, то это не идёт на пользу: перестают работать транзакции, теряется целостность и возникают прочие проблемы. А кэши, в свою очередь, не обладают многими полезными свойствами БД: надежностью хранения данных на диске, транзакциями и так далее. Например, в кэшах обычно нет такой важной штуки, как хранимые процедуры. Они позволяют переносить логику на сторону хранилища данных.
БД + кэш = ?
Конечно, можно жить на высоконагруженных проектах и без Tarantool. Допустим, вам нужны свойства и базы, и кэша в одном флаконе. Тогда можно применить очень популярную схему: поместить кэш поверх БД. Тогда все запросы идут сначала в кэш, если в нём есть нужные данные, то они отдаются пользователю. Если их там нет, то запрос переадресуется в БД. Все обновления идут сразу и в БД, и в кэш, ведь мы не можем что-то хранить в кэше, не сохранив это в базе, иначе эти данные могут быть потеряны.
Такая схема позволяет получить часть свойств СУБД. Например, транзакций и хранения процедур уже не будет, потому что когда появляются две системы, особенно кэш, то ни о каких транзакциях речь не идёт. В каком-то смысле теряется и репликация, потому что данные в базе реплицируются, а в кэш — как бы не совсем. Также теряются хранимые процедуры и прочие свойства БД. Свойства кэша сохраняются тоже частично. Такая система работает быстрее, потому что увеличивается скорость обработки обращений на чтение, но при этом, например, обращения на запись быстрее не становится. Если база данных затормозила, потому что у нее происходит вакуум таблицы или что-то ещё, то система будет тормозить на запись, потому что без БД запись не работает.
В целом, это рабочая схема. Она позволяет получить часть свойств и базы, и кэша в одной системе. Если вам этого достаточно, то такую схему и надо использовать.
Правда, в этом случае возникают две частые проблемы — несогласованные данные и холодный старт. «Несогласованность» означает, что данные в кэше и базе могут оказаться разными, потому что кэш и база не являются репликой друг друга, это просто две отдельные сущности. «Холодный старт» — это ситуация, когда при старте кэша он ещё пустой, данных в нём нет, поэтому все запросы летят в базу, и производительность системы оставляет желать лучшего.
Если вас не смущают эти моменты, то схема «кэш поверх БД» — вполне рабочий вариант. В противном случае целесообразно обратить внимание на Tarantool, потому что в нём все эти проблемы решены изначально. Одна из причин его разработки и заключается в том, чтобы не городить такие сложные гетерогенные системы, состоящие из нескольких хранилищ, а спокойно обходиться одним и хранить в нём все горячие данные.
Движки
У Tarantool есть два движка хранения данных. Один из них — это in-memory движок. Устроен он так: все данные хранятся в памяти, копии данных есть на диске. На диск пишется каждая транзакция просто в loc, и время от времени на диск сбрасывается целиком snapshot всей базы. Сбрасывается асинхронно в фоновом режиме. Пока он сбрасывается, база работает, потому что все новые обновления идут в отдельные места. То есть все работает вообще без тормозов. Loc транзакций пишется всегда.
Второй движок дисковый. Он позволяет всё хранить на диске. Причем можно использовать как SSD, так и винчестеры. Этот движок вырос из гуглового LevelDB, который был оптимизирован.
Преимущества и недостатки
Tarantool присущи свойства, характерные для кэша:
- Горячие данные.
- Доступность 99,99%.
- Оптимальная работа при высокой параллельной нагрузке.
- Latency:
- 99% запросов < 1 мс
- 99,9% запросов < 3 мс
- Нагрузка на запись — до 1 миллиона транзакций в секунду на одном ядре ЦПУ.
- Не нужно много серверов.
- Оптимальное использование памяти.
- Система работает постоянно, не нужно делать перерыв на профилактические работы.
В основном здесь всё связано с высокой скоростью работы. Традиционные СУБД лишены этих свойств. При этом Tarantool обладает и свойствами классических СУБД:
- Персистентность (надёжность хранения данных на диске).
- Транзакции ACID.
- Репликация (master-slave и master-master).
- Хранимые процедуры.
- Неблокирующие серверные сценарии.
- Удобные бэкапы.
- Выполнение запросов Cursors, Range и Full scan.
- Первичные и вторичные индексы.
- Таблицы.
Опять же, у кэша этих свойств нет, а в Tarantool они присутствуют.
Одни современные БД нацелены на высокую надёжность работы, другие делают упор на скорость работы. Это два разных мира, которые, в основном, не пересекаются. Tarantool — это достаточно успешная попытка объединить оба мира в одном решении.
К недостаткам Tarantool можно отнести следующее:
- У него пока не очень большое сообщество. Прежде чем применять какую-то технологию, каждый человек всегда думает: «Что если она не будет работать? У кого я спрошу?». Разработчики Tarantool стараются быть и отвечать на вопросы везде: в Facebook, на Stack Overflow и так далее. Но с точки зрения ряда пользователей есть риск не получить ответ из-за немногочисленности сообщества.
- Отсутствует консистентный шардинг. Над этим сейчас ведётся работа, чтобы он уже из коробки был нормальный, с поддержкой транзакций.
- Проприетарный протокол.
Примеры использования Tarantool
Все примеры взяты из опыта работы проектов Mail.Ru Group. На самом деле их очень много, но мы рассмотрим только три: систему аутентификации, систему push-уведомлений и систему показа рекламы. Обычно они самые высоконагруженные.
Система аутентификации
Она должна обладать рядом, казалось бы, противоречивых требований.
- Высочайшая востребованность: аутентификация должна проверяться при каждом хите на веб-сайте или в мобильном приложении. Нужно проверить пароль, куки, токен, что угодно, ведь нельзя просто так впускать пользователя. На портале Mail.Ru и в мобильных приложениях количество запросов к системе аутентификации исчисляется миллионами в секунду.
- Latency — время между запросом и ответом от базы данных. Оно должно быть как можно меньше, иначе всё будет тормозить, в том числе и веб-сервер, использующий аутентификацию. Пока он ждёт ответа от БД, он занимает какой-нибудь поток или процесс, данные висят в памяти, и это тоже потребляет серверные ресурсы. То есть медленная система работы аутентификации может потащить за собой кучу проблем, поэтому она должна работать просто моментально.
- Высокая доступность. Если система аутентификации не будет работать в 1% случаев, то и весь сайт не будет работать в 1% случаев.
- Постоянные обращения к хранилищу. Каждый хит в системе аутентификации — это проверка сессии, пароля, токена.
- Защита от brute-force атак и мошенничества. Систему аутентификации постоянно пытаются сломать.
- Почти каждое обращение связано с выполнением транзакции, то есть с необходимостью изменения каких-то данных. Например, при выполнении аутентификации нужно проверить введённые данные, обновить место и время аутентификации, прочие параметры для системы защиты от brute-force. Всё это — прямая транзакция в БД. Эту запись нельзя терять.
- Много неизбежной лишней работы. Когда все пытаются сломать систему, то за кулисами происходит очень много обращений, которые генерируются не пользователями, а средствами взлома. Эти обращения не несут полезный трафик или прибыль. Это лишняя нагрузка. Но их приходится обрабатывать и проверять.
- Большой размер данных. Естественно, в системе аутентификации должна храниться вся пользовательская база.
- Наличие срока действия введённых пользователем данных (expiration). По соображениям безопасности, если пользователь не активен какое-то время, его сессия завершается. Для этого необходимо проверять время начала сессии и наличие активности.
- Надёжность хранения данных (persistence). Очевидно, что если система аутентификации «забудет» часть пользователей в результате потери учётных данных, то это прямой ущерб репутации.
В целом этот набор свойств может выглядеть противоречивым. Какие-то из них обычно реализуются кэшами, а какие-то — базами данных. Система аутентификации должна быть надёжная и долговечная как грузовик, но при этом такая же быстрая, как спортивная машина. И Tarantool пришёлся здесь как нельзя кстати.
Схема работы системы аутентификации Mail.Ru по логину и паролю:
Только при проверке логинов и паролей в Mail.Ru выполняется 50 тыс. транзакций в секунду. Защита от brute-force и система аутентификации каждый раз читают и пишут в Tarantool. Эта суммарная нагрузка достигает примерно миллиона запросов в секунду: от всего портала, от всех мобильных приложений, от всех Ajax- и неAjax-запросов.
При этом сессии обслуживает всего 4 сервера, а профили пользователей — 8 серверов. Не какие-то брендовые, специальные серверы, а самые обычные, с обычными процессорами. Ничего космического.
Система push-уведомлений
Как вы знаете, мобильные приложения любят присылать пользователям push-уведомления, чтобы они оставались в них подольше. То есть это такая хорошая и благодарная штука.
Как устроена система уведомлений в Mail.Ru?
Когда на сервере происходят какие-то события — пришло письмо, сообщение в мессенджер, появилась новость — нужно отправить уведомление на мобильные телефоны конечных пользователей. Напрямую это сделать невозможно. Поэтому Apple и Google предоставляют API для iOS и Android, посредством которых можно дергать мобильные приложения.
Но обращаться к этим API напрямую с сервера нельзя. Почему — об этом чуть ниже. Кроме того, при каждом генерировании события нужно сходить в хранилище, чтобы понять, какому пользователю доставлять это событие. И не забыть прочитать токен, потому что API работают с токенами. И всё это нужно сделать очень быстро.
Также крайне важно сохранить очень низкое latency, поскольку события генерируются из большого количества разных контекстов и серверных окружений. Никогда нельзя тормозить на сервере, ждать секунду-две, потому что иначе все остальные участники процесса по цепочке начнут работать медленно. По этой причине мы к API не напрямую с сервера, а через очередь, тоже работающую на Tarantool. Эта СУБД может предоставлять и сервис очередей, причем персистентных и реплицируемых. То есть при падении машины, при выходе диска из строя, при перезагрузке сервера никто ничего не замечает.
Получается, что сервер работает напрямую только с быстрым хранилищем, а всё медленное расположено дальше, за очередью. Такая схема позволяет быстро всё обрабатывать: суммарное количество запросов в этой системе порядка 200 тыс. в секунду.
Система показа рекламы
Это, наверное, самый высоконагруженный вариант использования Tarantool, и это самая большая ферма, которая есть в Mail.Ru Group. Система отвечает за показ рекламы почти на всех страницах огромного портала, причём рекламных блоков на странице обычно не менее 10.
Чтобы показать каждый рекламный блок, нужно понять, что вообще нужно показывать пользователю. Для этого данные о нём собираются из нескольких разных источников. Всё это агрегируется и формируется результат. Всё это делается для каждого блока, и на это надо потратить меньше одной миллисекунды. Откуда такое требование? Потому что пользователи не захотят, чтобы сервис тормозил из-за рекламы, она и так всех раздражает, но является необходимым злом.
Нагрузка на систему показа рекламы — порядка 3 млн запросов в секунду. Причем 1 млн из них — это изменения, потому что показ рекламы часто приводит к обновлению профиля пользователя.
Краткий вывод
Если вам нужно сочетать свойства БД и кэша, — надежность и скорость, — и если какими-то простыми методами, которыми вы обычно это делаете, не получается этого добиться, то присмотритесь к Tarantool. Скорее всего, он эту проблему решит.
Автор: 1С-Битрикс