Сегодня я забил на вопросы про ForkJoinPool и решил показать, где заканчивается обычная Java-многопоточность.
Все эти споры про synchronized, volatile и размер пула потоков в Spring актуальны ровно до тех пор, пока ваше приложение работает с базой данных под привычной нагрузкой.
Но как только бизнес говорит: «Нужно считать миллион событий в час» — классическая архитектура начинает сыпаться.
Именно здесь начинается Apache Flink. Я сейчас дописываю главу об этом в книгу по Highload и хочу подсветить.
Flink — это способ заставить JVM работать как In-Memory Data Grid с гарантией транзакционности.
Нам не нужны костыли вида:
1. Событие пришло, мы записали его в Kafka.
2. Другая задача прочитала и обновила Redis (тут молимся, чтобы не было race condition).
3. Третья задача прочитала и дернула базу.
На третьем шаге данные почти всегда разъедутся или база ляжет от частоты запросов.
Что делает Flink? Он держит состояние внутри себя. Это буквально кусок памяти воркера, где живет наш агрегат.
Даже если сервер упадет посреди записи, после перезагрузки цифра в отчете сойдется до копейки. Никакого HyperLog, никаких потерь при ретраях.
Код выглядит так же, как обычные стримы:
clicks.keyBy(click -> click.getUserId())
.window(TumblingEventTimeWindows.of(Time.minutes(1)))
.process(new MyCounter()); // обычный Java код
А масштабируется это всё автоматически на десятки машин.
🛑 Главная ловушка
Не нужно хранить гигабайты состояния в Heap.
Garbage Collector уничтожит задержки realtime.
Тут идеально подходит RocksDB State Backend — это встроенная NoSQL-база прямо в воркере, которая прячет старые данные на SSD, оставляя память чистой.
❓ Вопрос:
Вы бы внедрили Flink для подсчета лайков и просмотров в своем проекте, или считаете, что одного хорошего ClickHouse Materialized View достаточно?