ГоловнаСтатті

Apache Kafka та Архітектура, Орієнтована на Події: Чому Здатність Відтворювати Історичні Дані – Це Ключова Особливість

Як працює модель Kafka на основі логів, розподіл (partitioning) та групи споживачів (consumer groups), і чому здатність відтворювати історичні події є тим, що справді відрізняє її від традиційної черги повідомлень (message queue).

mysimulator teamОновлено — червень 2026≈ 5 хв читання▶ Відкрити симуляцію

Лог, а не черга

Традиційні черги повідомлень, такі як RabbitMQ або ActiveMQ, реалізують модель «спожива-і-видали»: повідомлення публікується, споживач його отримує, споживач підтверджує отримання, і черга видаляє його. Після споживання повідомлення зникає. Ця модель добре працює для класичного випадку розподілу робочих завдань для обробки точно один раз — завдання для фонової роботи є типовим прикладом — але структурно вона не може підтримувати наступного споживача, який пізніше приєднується і запитує все, що сталося, оскільки призначення черги полягає в тому, щоб повідомлення зникали після обробки.

Основне дизайнерське рішення Kafka полягає в моделюванні сховища повідомлень не як черги, а як лише додавання (append-only) незмінний лог, розділений на кластер брокерів, де повідомлення (Kafka називає їх записами) зберігаються протягом певного часу — зазвичай сім днів, але часто встановлюються тижні, місяці або безкінечно для критичних потоків подій — незалежно від того, чи прочитали їх споживачі. Споживачі не видаляють записи з логу при читанні; замість цього кожен споживач незалежно відстежує свою власну позицію читання (свій зміщення) в кожній секції та може повернути цю позицію назад, щоб перечитати історію, або швидко просунутися вперед, повністю незалежно від того, що роблять інші споживачі. Цей єдиний архітектурний вибір — розглядати сховище повідомлень як довговільний, відтворюваний лог, а не тимчасову чергу для роботи — є коренем майже всіх властивостей, які відрізняють Kafka від традиційного брокера повідомлень, і варто бути конкретним, що це справжній компроміс: модель Kafka вимагає більшого обсягу зберігання (ви зберігаєте дані, які інші системи викидають), і перекладає більше відповідальності за відстеження позиції читання на споживача, в обмін на можливості, яких не може запропонувати черга з видаленням при читанні.

Чому відтворення даних – ключова особливість

Практична вигода моделі на основі логів проявляється тоді, коли щось подальнє потребує історії, яку черга видалення при читанні вже знищила. Якщо нова команда аналітиків приєднується до компанії та хоче побудувати дашборд на основі шестимісячної послідовності подій замовлень, то Kafka-тема, яка зберігає цю історію, дозволяє їм просто запустити нову групу споживачів і читати з початку логу – не потрібно було передбачати існування цього споживача під час початкового виробництва подій. Якщо споживач подальшого даних має помилку, яка пошкоджує його похідні дані за останні три дні, то виправлення полягає у поверненні відстані (offset) групи споживачів назад на три дні та дозволі її повторного оброблення тих самих подій з логу, цього разу правильно, замість необхідності додати окремий механізм резервного копіювання та відтворення після. Якщо компанія хоче інтегрувати нову послугу – наприклад, модель виявлення шахрайства, яка потребує навчання та тестування на основі історичних транзакційних даних перед запуском, то ці події все ще зберігаються в лозі (або у довготривалому рівневому сховищі Kafka) і готові до споживання з будь-яким темпом, необхідним для нової послуги, повністю відокремленими від потокового трафіку виробництва, що все ще проходить через ту ж саму тему в реальному часі.

Це відтворюваність також робить Kafka природною основою для архітектур Event Sourcing, де лог подій розглядається як першоджерело істини, а будь-яка похідна база даних (поточна баланс клієнта, поточний статус замовлення) розуміється як проекція, яку можна в принципі завжди відтворити, відтворюючи лог подій з початку. Традиційна черга повідомлень не може підтримувати цей шаблон, оскільки до того часу, як ви усвідомите необхідність відтворення проекції, оригінальні повідомлення, що її побудували, вже втрачені.

Розділення та упорядкування: механізм, що лежить в основі пропускної здатності Kafka

Kafka досягає високої пропускної здатності завдяки розділенню кожної теми на кілька розділів, кожен з яких є незалежним, відсортованим логом, розподіленим по кластеру брокерів. Виробник, записуючи дані в тему, призначає кожен запис у розділ, зазвичай шляхом хешування ключа запису (наприклад, ідентифікатора клієнта або ідентифікатора замовлення), що гарантує, що всі записи з однаковим ключем завжди потрапляють у один і той же розділ і, відповідно, завжди читаються в порядку їх запису, відносно один одного. Це важливий та часто неправильно зрозумілий нюанс: Kafka гарантує упорядкування всередині розділу, а не між усією темою. Два записи з різними ключами, що потрапляють у різні розділи, не мають гарантії упорядкування відносно один одного, що є свідомим компромісом – повне упорядкування по всій темі вимагало б перенаправлення кожного запису через єдиний послідовний лог, що і є вузьким місцем пропускної здатності, яке існує для усунення.

Тому вибір ключа є одним з найважливіших дизайнерських рішень у системі на базі Kafka: вибір для ключових записів ідентифікатора клієнта гарантує, що кожен подія для певного клієнта обробляється в правильному відносному порядку відповідним споживачем, який обробляє цей розділ, тоді як поганий вибір ключа (або відсутність ключа, що призводить до випадкового розподілу розділів) жертвує гарантіями упорядкування, на які може покладатися додаток. З боку споживання, групи споживачів розширюють цю саму логіку розділення: кілька інстанцій споживача можуть приєднатися до групи, а Kafka автоматично розподіляє розділи теми між ними, тому тема з 12 розділами та група споживачів з 4 інстанціями дає кожній інстанції 3 розділи для незалежної та паралельної обробки, і це призначення динамічно перерозподіляється, якщо інстанція виходить з ладу або приєднується нова, забезпечуючи Kafka як горизонтальну масштабованість споживання, так і автоматичне резервне копіювання без будь-якої логіки координації на рівні додатку.

Де Kafka вписується, а де – ні

Ніяк цього не робить Kafka універсальною заміною для традиційних черг, і розуміння компромісу має значення при правильному виборі. Модель видалення елементів при споживанні черги простіша для розуміння для чистої роботи з розподілом завдань, де ніхто ніколи не потребуватиме історії та витрати на зберігання справді важливі, і традиційні черги зазвичай надають більш багаті можливості маршрутизації повідомлень на рівні окремого повідомлення (черги пріоритетності, складні правила маршрутизації на основі вмісту повідомлення), які пропонують Kafka’я простіша модель розділу та групи споживачів не надають безпосередньо. Kafka також вносить справжню операційну складність – керування та налаштування розподіленого, розділеного, відреplicated лог-кластеру є більш значним операційним зобов’язанням, ніж керування однією інстанцією RabbitMQ, і неправильний вибір кількості розділів, політик зберігання та стратегій ключів може призвести до проблем (занадто мало розділів обмежує паралелізм; занадто багато створює навантаження на брокера; поганий вибір ключа створює «гарячі розділи», де навантаження розподілено нерівномірно по кластеру), які важко виправити після того, як тема вже має значний обсяг виробничого трафіку.

Усвідомлений шаблон, що виник у більшості масштабних архітектур даних, полягає у використанні Kafka саме як міцну, відтворювану основу для з’єднання багатьох незалежних виробників і споживачів – нервову систему, через яку потік подій, дані про кліки, показники датчиків або потоки захоплення змін даних, щоб їх отримали всі системи, які їх потребують, включаючи безпосереднє живлення потокових фреймворків, таких як Kafka Streams або Flink для реального часу агрегації, та векторних баз даних, магазинів ознак і сховищ даних, що охоплюються в іншому типі інфраструктурного стеку – тоді як простіші черги повідомлень резервуються для вужчих, тимчасових завдань з розподілу завдань, де відтворення та багатоспоживачі розповсюдження не потребувалися б взагалі.

Часті запитання

Чи гарантує Kafka, що всі повідомлення в темі обробляються в порядку їх надсилання?

Лише всередині однієї розділи. Записи з однаковим ключем завжди потрапляють у ту ж розділ і читаються в порядку, але Kafka не робить жодних гарантій щодо порядку обробки між різними розділами тієї самої теми, що є свідомим компромісом дизайну, який дозволяє йому забезпечувати паралельну пропускну здатність.

Як довго Kafka зберігає повідомлення після їх споживання?

За замовчуванням, на основі налаштованої політики збереження за часом (зазвичай сім днів) або обмеження розміру, незалежно від того, чи прочитали споживачі повідомлення. Споживання не видаляє записи, що дозволяє кільком незалежним споживачам читати одну й ту ж історію в різний час.

Що відбувається, якщо споживач у групі споживачів виходить з ладу?

Kafka автоматично перерозподіляє групу, повторно призначаючи розділи, які були належали збанкрутілому споживачу, решті активним споживачам у групі, щоб обробка продовжувалася без ручного втручання та відновлювалася з останнього комітованого зміщення кожного розділу.

Чи є Kafka базою даних?

Ні, в традиційному розумінні, хоча ця межа розмита завдяки таким функціям, як сховища стану Kafka Streams і багатошарове зберігання для дуже тривалого збереження. Kafka найкраще розуміється як міцний, упорядкований, відтворюваний журнал для даних подій, який використовують у багатьох архітектурах як джерело правди, з якого будуються бази даних та інші похідні перегляди.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте the simulation і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію the simulation

Що ви знайшли?

Додати кроки відтворення (опційно)