Как обрабатывать миллиарды событий в секунду и не обвалить задержки
Представьте ситуацию: вам нужно проверять банковские транзакции на мошенничество прямо в момент платежа. Время на решение ограничено несколькими миллисекунд. Apache Kafka сыплет событиями без остановки, но для каждого из них нужно подтянуть историю клиента из базы данных. Если при обработке каждого сообщения выполнять запрос к традиционной PostgreSQL или MySQL, система моментально ляжет под нагрузкой.
В такой тупик часто попадают инженеры при проектировании высоконагруженных систем. Обычный кэш вроде Redis помогает ускорить чтение отдельных ключей, но при выстраивании сложной бизнес-логики и аналитики поверх потока данных его возможностей начинает не хватать. Приходится связывать воедино кэши, брокеры сообщений и сторонние движки обработки. В этот момент логично посмотреть на Hazelcast.
Hazelcast объединяет распределенную оперативную память и движок потоковой обработки событий в одной системе. Вместо сборки конструкции из трех различных сервисов вы получаете единую платформу, способную принимать, обогащать и анализировать данные на лету.
Что происходит внутри платформы
Сердцем платформы выступает движок Jet. Он отвечает за построение конвейеров обработки данных. Причем Jet умеет одинаково хорошо работать с непрерывными стримами и со статичными массивами информации, например, бакетами в Amazon S3 или таблицами в реляционной базе.
Показатели производительности здесь интересные. Один узел Hazelcast способен агрегировать 10 миллионов событий в секунду, удерживая задержку в пределах 10 миллисекунд. Если же объединить серверы в кластер, пропускная способность масштабируется до миллиарда событий в секунду.
Чтобы писать запросы к потокам данных, не обязательно погружаться в низкоуровневый Java API. Платформа поддерживает стандартный SQL. Вы можете написать привычный SELECT к поступающему потоку данных, объединить его с таблицей в памяти и сразу направить результат в нужный сервис.
Вот как выглядит подключение внешних источников. Из коробки доступен набор коннекторов:
- Apache Kafka и JMS для работы с очередями
- Hadoop и Amazon S3 для обращения к файловым хранилищам
- Реляционные базы данных через стандартный JDBC
- Python-модели для запуска машинного обучения прямо внутри конвейера
Распределенная память и координация
Если убрать из уравнения потоковую аналитику, Hazelcast останется распределенным Key-Value хранилищем. Данные размазываются по узлам кластера в виде партиций. Разработчику доступны знакомые по Java структуры (IMap, IQueue, ITopic) с той лишь разницей, что они распределены по сети. Точечный поиск по ключу занимает микросекунды.
Для работы с базой данных поддерживаются классические шаблоны кэширования: read-through, write-through и write-behind. При использовании write-behind приложение сохраняет данные исключительно в оперативку Hazelcast, а платформа сама асинхронно сбрасывает их на диск в основную БД. Если реляционная СУБД временно упадет, ваше приложение продолжит принимать запросы без сбоев.
Отдельная функция — координация микросервисов. Hazelcast умеет рулить распределенными блокировками, выдавать уникальные последовательности ID и держать общие счетчики. За счет этого отпадает необходимость разворачивать и поддерживать отдельный кластер Apache ZooKeeper для банальных задач синхронизации.
Как собрать и запустить проект
Исходный код проекта написан на Java. Для самостоятельной сборки потребуется JDK 17 или более свежая версия. Самый простой способ собрать проект — воспользоваться штатным скриптом Maven Wrapper:
git pull origin master
./mvnw clean package -DskipTests
Процесс сборки со всеми проверками может затянуться. Если вам нужно просто быстро проверить локальные изменения, передайте флаг -Dquick:
./mvnw clean package -DskipTests -Dquick
Этот параметр отключает генерацию Javadoc, прогон Checkstyle и сборку второстепенных модулей.
С тестами ситуация интересная. В репозитории тысячи тестов, которые делятся на три профиля:
- Стандартный
./mvnw testпрогоняет быстрые интеграционные тесты. - Ночной
./mvnw test -P nightly-buildвключает медленные тесты, которые нельзя выполнять параллельно. - Полный
./mvnw test -P all-testsпоследовательно выполняет абсолютно все проверки с использованием сети.
Часть тестов завязана на Docker. Если на рабочей машине Docker не установлен, тесты упадут. Чтобы отключить их, используйте параметр -Dhazelcast.disable.docker.tests. При создании Pull Request полный прогон берет на себя CI-сервер проекта, поэтому локально достаточно запустить только тесты своего модуля.
Писать клиенты можно не только на Java. Сообщество и компания поддерживают официальные библиотеки под Python, Node.js, .NET, C++ и Go.
Лицензия и пара практических нюансов
Код в репозитории разделен на две части. Основное ядро распространяется под свободной лицензией Apache License 2.0. Однако некоторые энтерпрайз-фичи и модули защищены Hazelcast Community License. Она запрещает использовать код для создания платных управляемых сервисов (Cloud Service Provider), конкурирующих с оригинальным облачным продуктом компании.
Второй момент — требование к ресурсам. Так как все горячие данные находятся в RAM, для работы с большими объемами потребуется закупить солидный объем оперативной памяти. Также в Java-среде стоит внимательно относиться к настройкам сборщика мусора (Garbage Collector), чтобы избежать пауз при очистке гигабайтов памяти. Впрочем, инженеры Hazelcast нивелируют эту проблему с помощью off-heap хранения, вынося данные за пределы кучи Java.
Кому стоит присмотреться к Hazelcast
Платформа хорошо показывает себя там, где важна реакция на события в реальном времени:
- Противодействие мошенничеству и скоринг в финтехе
- Обработка телеметрии и IoT-сигналов с высокой частотой
- Расчет цен и скидок в e-commerce прямо в момент клика покупателя
- Синхронизация данных между распределенными дата-центрами (WAN replication)
Если вам нужен лишь простой кэш для пары эндпоинтов, Hazelcast станет стрельбой из пушки по воробьям: с этой задачей справится и более простой Redis. Но если проект вырос до масштабов, где потоковая аналитика должна пересекаться с распределенной памятью без постоянных хождений в дисковое хранилище, Hazelcast сэкономит месяцы разработки.
