<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Apache Kafka - DataTalks.RU. Data Engineering / DWH / Data Pipeline</title>
	<atom:link href="https://datatalks.ru/category/apache-kafka/feed/" rel="self" type="application/rss+xml" />
	<link>https://datatalks.ru/category/apache-kafka/</link>
	<description>RoadMap для инженера данных. Дорожная карта по инструментам Data Engineer</description>
	<lastBuildDate>Mon, 27 Oct 2025 18:30:05 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://datatalks.ru/wp-content/uploads/2024/12/cropped-logo_datatalks-32x32.png</url>
	<title>Apache Kafka - DataTalks.RU. Data Engineering / DWH / Data Pipeline</title>
	<link>https://datatalks.ru/category/apache-kafka/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Apache Kafka Tutorial 101: Архитектура, Consumer, Producer, Topic</title>
		<link>https://datatalks.ru/apache-kafka-tutorial-101-consumer-producer-topic/</link>
					<comments>https://datatalks.ru/apache-kafka-tutorial-101-consumer-producer-topic/#respond</comments>
		
		<dc:creator><![CDATA[Data Engineer (Admin)]]></dc:creator>
		<pubDate>Wed, 22 Oct 2025 12:41:04 +0000</pubDate>
				<category><![CDATA[Apache Kafka]]></category>
		<category><![CDATA[commit offset]]></category>
		<category><![CDATA[Consumer]]></category>
		<category><![CDATA[Consumer Group]]></category>
		<category><![CDATA[Kafka]]></category>
		<category><![CDATA[Kafka Connect]]></category>
		<category><![CDATA[Kafka Streams]]></category>
		<category><![CDATA[kafka-tutorial]]></category>
		<category><![CDATA[ksqlDB]]></category>
		<category><![CDATA[Message Queue]]></category>
		<category><![CDATA[offset]]></category>
		<category><![CDATA[Point-to-Point]]></category>
		<category><![CDATA[Producer]]></category>
		<category><![CDATA[Publish-Subscribe]]></category>
		<category><![CDATA[ZooKeeper]]></category>
		<category><![CDATA[Потоковая обработка данных]]></category>
		<guid isPermaLink="false">https://datatalks.ru/?p=942</guid>

					<description><![CDATA[<p>Введение в Apache Kafka Что такое Apache Kafka? Apache Kafka — это распределённая платформа для обработки потоков данных в реальном времени, которая позволяет приложениям публиковать, хранить и обрабатывать данные в режиме потоков событий. Она обеспечивает высокую пропускную способность, масштабируемость и отказоустойчивость, что делает её популярной для создания событийно-ориентированных архитектур, аналитики в реальном времени и управления [&#8230;]</p>
<p>Сообщение <a href="https://datatalks.ru/apache-kafka-tutorial-101-consumer-producer-topic/">Apache Kafka Tutorial 101: Архитектура, Consumer, Producer, Topic</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Введение в Apache Kafka</h1>
<h2>Что такое Apache Kafka?</h2>
<p><strong>Apache Kafka</strong> — это распределённая платформа для обработки потоков данных в реальном времени, которая позволяет приложениям публиковать, хранить и обрабатывать данные в режиме потоков событий. Она обеспечивает высокую пропускную способность, масштабируемость и отказоустойчивость, что делает её популярной для создания событийно-ориентированных архитектур, аналитики в реальном времени и управления большими объёмами данных.</p>
<h2>Подборка материалов по Kafka</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=hbseyn-CfXY" target="_blank" rel="noopener"><strong>YouTube</strong>: Лучший Гайд по Kafka для Начинающих За 1 Час (Vlad Mishustin)</a> &#8212; классный видос по Kafka</li>
<li><a href="https://www.youtube.com/watch?v=r2QiU0o5kWs" target="_blank" rel="noopener"><strong>YouTube</strong>: 5 Применений Kafka в Реальных Приложениях</a> &#8212; дополнительное видео для понимания использования Kafka в приложениях</li>
<li><a href="https://www.youtube.com/watch?v=UNOkvk_fMmM" target="_blank" rel="noopener"><strong>YouTube</strong>: Kafka и RabbitMQ &#8212; БРОКЕРЫ СООБЩЕНИЙ Простым языком на понятном примере</a></li>
<li><a href="https://www.youtube.com/playlist?list=PLt91xr-Pp57Q50WsXz9r-zmxy5ceu_hp_" target="_blank" rel="noopener"><strong>YouTube</strong>: Playlist Apache Kafka</a> &#8212; большой курс по Kafka от JavaGuru</li>
<li><a href="https://www.youtube.com/watch?v=-AZOi3kP9Js" target="_blank" rel="noopener"><strong>YouTube</strong>: Про Kafka (основы)</a></li>
<li><a href="https://www.youtube.com/playlist?list=PL8D2P0ruohOC5FXjzqVRaTsglQ57iKCCe" target="_blank" rel="noopener"><strong>YouTube</strong>: Kafka со Слёрмом</a></li>
<li><a href="https://www.youtube.com/watch?v=R2yGsEfPKS4" target="_blank" rel="noopener"><strong>YouTube</strong>: Kafka в 2025 для дата-инженера: Полный разбор на практике с Python, S3 и ClickHouse</a></li>
<li><strong><a href="https://softwaremill.com/kafka-visualisation/" target="_blank" rel="noopener">Kafka Visualization</a></strong> &#8212; онлайн симулятор работы Kafka, можно сконфигурировать (ограничено) работу Kafka и посмотреть на &#171;конвейер сообщений&#187; между продюсерами и потребителями данных. Статья на <strong>habr</strong> <a href="https://habr.com/ru/articles/865120/" target="_blank" rel="noopener"><strong>&#171;Симулятор брокера Apache Kafka: Kafka Visualization от компании SoftwareMill&#187;</strong></a> про этот симулятор</li>
<li>Статья на <strong>habr</strong> <a href="https://habr.com/ru/companies/piter/articles/352978/" target="_blank" rel="noopener">&#171;Apache Kafka: обзор&#187;</a></li>
<li><a href="https://datatalks.ru/wp-content/uploads/2025/10/shpargalka_Kafka.pdf">Шпаргалка по Kafka.pdf</a></li>
<li><strong>YouTube</strong>: <a href="https://www.youtube.com/watch?v=FGETRVOPdiA" target="_blank" rel="noopener">Типичные ошибки при работе с Apache Kafka — Виктор Корейша (Ozon)</a></li>
<li><strong>YouTube</strong>: <a href="https://www.youtube.com/@HighLoadChannel/search?query=Kafka" target="_blank" rel="noopener">HighLoadChannel &#171;Kafka&#187;</a></li>
<li><strong>YouTube</strong>: <a href="https://www.youtube.com/watch?v=b42gkdta_6s" target="_blank" rel="noopener">Алексей Кашин — Надежно отправляем события в Apache Kafka. От CDC до паттерна Transactional Outbox</a></li>
<li><strong>YouTube</strong>: <a href="https://www.youtube.com/watch?v=V5t_3RxBals" target="_blank" rel="noopener">Apache Kafka: погружение на 45 минут. Григорий Кошелев, Контур, ведущий разработчик</a></li>
</ul>
<h2>Основная логика работы Kafka</h2>
<p><strong>Kafka</strong> — это распределённая система журналов (distributed commit log). Она состоит из нескольких <strong>брокеров</strong> (серверов), которые вместе образуют <strong>кластер</strong>. Кластер хранит <strong>топики</strong>, которые разделены на <strong>партиции</strong> (partitions). Каждая партиция — это упорядоченный, неизменяемый лог событий.</p>
<p><strong>Producer (Продюсер)</strong> соединяется с кластером и узнаёт, на каком брокере хранится нужный топик и его партиции. Для каждой записи продюсер выбирает <strong>партицию</strong> (по ключу, по хешу или случайно). <strong>Событие сериализуется</strong> (обычно Avro, JSON, Protobuf) и отправляется на брокер. Брокер записывает сообщение <strong>в конец партиции</strong> — фактически в лог-файл на диске. Каждому сообщению присваивается <strong>смещение (offset)</strong> — уникальный порядковый номер. Kafka не переписывает данные, а только добавляет новые в конец файла &#8212; поэтому она очень быстрая.</p>
<p><strong>Consumer (Консюмер)</strong> подключается к брокеру через <strong>Consumer Group Coordinator</strong>. Консюмер читает сообщения по порядку <strong>offset-ов</strong> и может сохранять своё текущее <strong>смещение (commit offset)</strong> в Kafka <strong>(__consumer_offsets)</strong>. Таким образом Kafka знает, до какого места консюмер дочитал поток.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2.png"><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-2448" src="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2.png" alt="" width="933" height="621" srcset="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2.png 933w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2-300x200.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2-768x511.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2-450x300.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_common_schema_v2-780x519.png 780w" sizes="(max-width: 933px) 100vw, 933px" /></a></p>
<p><strong>Kafka</strong> хранит данные на диске — в виде логов, а не в памяти. Каждая партиция — это директория на диске брокера, содержащая:</p><pre class="urvanov-syntax-highlighter-plain-tag">00000000000000000000.log
00000000000000001000.log
...</pre><p>Каждый <strong>.log файл</strong> — это блок записей. Когда достигается <strong>лимит по размеру (segment.bytes)</strong> или <strong>времени (segment.ms)</strong>, создаётся новый сегмент. Kafka не удаляет сообщения сразу после чтения.</p>
<p><strong>Партиция</strong> сохраняется на диске как каталог сегментов. <strong>Сегменты</strong> — это физические фрагменты одной партиции, а не отдельные логические сущности.</p>
<p><strong>Topic -&gt; Log -&gt; Segment:</strong></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment.png"><img decoding="async" class="aligncenter size-full wp-image-2340" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment.png" alt="" width="1502" height="752" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment.png 1502w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment-300x150.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment-1024x513.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment-768x385.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment-450x225.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_topic_partition_segment-780x391.png 780w" sizes="(max-width: 1502px) 100vw, 1502px" /></a></p>
<p>Сообщения хранятся до истечения <strong>retention policy</strong>:</p>
<ul>
<li>по времени (retention.ms),</li>
<li>по размеру (retention.bytes),</li>
<li>или в режиме compaction — сохраняется только последнее сообщение для каждого ключа.</li>
</ul>
<h2>Глоссарий Apache Kafka</h2>
<p><strong>Основные определения Apache Kafka:</strong></p>
<ul>
<li><strong>Apache Kafka</strong> &#8212; Распределённая платформа потоковой передачи событий (<strong>event streaming platform</strong>), предназначенная для обработки и хранения потоков данных в реальном времени. Используется для построения real-time пайплайнов и стриминговых приложений.</li>
<li><strong>Event / Message / Record (Событие / Сообщение / Запись)</strong> &#8212; Представление факта изменения состояния системы — «что-то произошло». Включает ключ, значение, метку времени и необязательные заголовки. События в Kafka неизменяемы (<strong>immutable</strong>).</li>
<li><strong>Topic (Топик)</strong> &#8212; Логическая категория/канал данных, куда продюсеры публикуют события. Топики делятся на <strong>partitions</strong> (разделы) и могут быть реплицированы.</li>
<li><strong>Partition (Раздел)</strong> &#8212; Физическая часть топика, хранящая события в порядке записи. Базовая единица параллелизма Kafka. Каждая партиция — упорядоченная, неизменяемая последовательность событий, которая записывается в лог. События в партиции строго упорядочены и идентифицируются <strong>offset</strong>-ом.</li>
<li><strong>Broker (Брокер)</strong> &#8212; Сервер Kafka, который принимает события от продюсеров (<strong>producers</strong>), хранит их в партициях и выдаёт консюмерам (<strong>consumers</strong>). Обычно Kafka-кластер состоит из нескольких брокеров.</li>
<li><strong>Producer (Продюсер)</strong> &#8212; Приложение (клиент), которое публикует (отправляет) события в Kafka-топики. Продюсер может определять, в какую партицию топика записать сообщение.</li>
<li><strong>Consumer (Консюмер)</strong> &#8212; Приложение (клиент), которое подписывается на один или несколько топиков и обрабатывает поступающие события. Читает сообщения из партиций в порядке их <strong>offset</strong>-ов.</li>
<li><strong>Consumer Group (Группа Потребителей)</strong> &#8212; Набор консюмеров, совместно обрабатывающих события из одного или нескольких топиков. Каждая партиция назначается только одному консюмеру внутри группы → масштабирование без дублирования.</li>
<li><strong>Offset (Смещение)</strong> &#8212; Уникальный порядковый номер события в пределах партиции. Определяет позицию консюмера и обеспечивает контроль обработки сообщений.</li>
<li><strong>Replication (Репликация)</strong> &#8212; Механизм копирования партиций на несколько брокеров. Обеспечить отказоустойчивость и сохранность данных. Replication factor определяет количество копий каждой партиции.</li>
<li><strong>Leader (Лидер)</strong> &#8212; Основная реплика партиции, которая обрабатывает все операции чтения и записи.</li>
<li><strong>Follower (Фолловер)</strong> &#8212; Реплика, синхронизирующаяся с лидером путём копирования его журнала событий. При отказе лидера фолловер может быть выбран новым лидером.</li>
<li><strong>In-Sync Replica (ISR, Синхронная Реплика)</strong> &#8212; Набор реплик (включая лидера), которые полностью синхронизированы с лидером. Обеспечивает надёжную запись — продюсер может ждать подтверждений от всех ISR.</li>
<li><strong>ZooKeeper</strong> &#8212; распределённая система координации, традиционно использовавшаяся Kafka для хранения метаданных, выборов лидера и конфигурации. KRaft (Kafka Raft) &#8212; новый встроенный протокол консенсуса, заменяющий ZooKeeper в современных версиях Kafka.</li>
<li><strong>Kafka Connect</strong> &#8212; Фреймворк для интеграции Kafka с внешними системами (базы, очереди, хранилища и т. д.). <strong>Source Connectors</strong> (загрузка данных в Kafka) и <strong>Sink Connectors</strong> (выгрузка из Kafka).</li>
<li><strong>Kafka Streams</strong> &#8212; Клиентская библиотека, которая позволяет прямо из приложений читать данные из топиков, обрабатывать их (фильтровать, агрегировать, объединять) и писать результат обратно в другие топики. Это “потоковая логика поверх Kafka”.</li>
</ul>
<h2>Пример сценария использования Apache Kafka</h2>
<p>Здесь разберем небольшой пример, чтобы на нем описать основную логику работы системы.</p>
<p>Допустим, у нас есть крупный интернет-магазин, где ежедневно создаются тысячи заказов. Каждый заказ запускает целую цепочку бизнес-процессов: уведомления клиенту, резервирование товара, доставка, обновление аналитики и многое другое.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example.jpg"><img decoding="async" class="aligncenter size-full wp-image-2302" src="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example.jpg" alt="" width="845" height="167" srcset="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example.jpg 845w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example-300x59.jpg 300w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example-768x152.jpg 768w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example-450x89.jpg 450w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_example-780x154.jpg 780w" sizes="(max-width: 845px) 100vw, 845px" /></a></p>
<p>Представим, что мы хотим построить эту систему так, чтобы она была масштабируемой, отказоустойчивой и позволяла добавлять новые микросервисы без необходимости переписывать старые. Именно здесь на сцену выходит <strong>Apache Kafka</strong> — платформа, которая превращает поток событий в единое, надёжное “сердце” всей e-commerce-инфраструктуры.</p>
<h3>Шаг 1. Создание заказа</h3>
<p>Всё начинается с того, что пользователь оформляет заказ на сайте. На уровне архитектуры это делает сервис, который мы назовём <strong>Order Service</strong>. Он отвечает за валидацию данных, проверку наличия товаров и создание записи в базе данных. Когда заказ успешно создан, сервис публикует событие <code>OrderCreated</code> в <strong>Kafka</strong> — в специальный топик под названием <strong>orders</strong>.</p>
<p><strong>Выглядит это, как простое сообщение в формате JSON, например:</strong></p><pre class="urvanov-syntax-highlighter-plain-tag">{
  "order_id": 12345,
  "customer_email": "user1@ecom.ru",
  "total": 199.90,
  "items": [
    {"sku": "AB-123", "qty": 2},
    {"sku": "CD-456", "qty": 1}
  ],
  "created_at": "2025-10-22T10:30:00Z"
}</pre><p><strong>Продюсер (Order Service)</strong> обращается к брокеру <strong>Kafka</strong> и помещает событие в конец журнала (partition) топика orders. С этого момента <strong>Kafka</strong> становится источником истины: все сервисы, которым нужно знать о новых заказах, будут читать именно этот поток.</p>
<h3>Шаг 2. Сервис уведомлений</h3>
<p>После того, как событие появляется в Kafka, его получает первый потребитель — <strong>Notification Service</strong>. Это отдельное приложение, которое подписано на тот же топик orders, но принадлежит своей consumer group (например, <strong>notification_group</strong>). Kafka гарантирует, что каждый потребитель внутри группы получает уникальный набор партиций — то есть события распределяются равномерно, а не дублируются.</p>
<p>В данном случае сервис уведомлений получает все события, потому что он один в группе.</p>
<p>Получив сообщение <code>OrderCreated</code>, сервис выполняет простое действие: он берёт адрес электронной почты клиента, формирует письмо и отправляет уведомление:</p><pre class="urvanov-syntax-highlighter-plain-tag">“Ваш заказ №12345 успешно создан! Мы приступаем к обработке.”</pre><p>Kafka здесь выступает как надёжный посредник.</p>
<p>Если сервис уведомлений временно недоступен — ничего страшного. Kafka продолжает хранить сообщения в топике orders. Когда сервис вернётся в строй, он просто дочитает поток с того места, где остановился — по сохранённому offset-у. Таким образом, ни одно уведомление не потеряется, даже если в системе временно что-то пошло не так.</p>
<h3>Шаг 3. Сервис логистики</h3>
<p>Параллельно с Notification Service в системе работает другой потребитель — <strong>Logistics Service</strong>. Он также слушает топик orders, но уже со своей consumer group, например <strong>logistics_group</strong>. Это значит, что Kafka отдаёт ему тот же поток событий, что и сервису уведомлений, но независимо. Каждый сервис получает свои копии событий — и каждый может реагировать по-своему.</p>
<p>Когда Logistics Service получает сообщение <strong>OrderCreated</strong>, он делает совсем другие вещи: резервирует товар на складе, создаёт задачу для курьера, обновляет статус заказа в системе доставки. Таким образом, одно событие запускает два (и потенциально десятки) разных бизнес-процессов — и всё это асинхронно и безопасно.</p>
<h3>Потоковая интеграция вместо хрупких связей через API</h3>
<p>Если бы мы строили такую систему без Kafka, то <strong>Order Service</strong> должен был бы сам вызывать API уведомлений, API логистики и, возможно, ещё десяток других сервисов. Такой подход создаёт сильную связанность: ошибка одного из сервисов может замедлить или остановить весь процесс. Kafka решает эту проблему, превращая коммуникацию в поток событий, где каждый сервис просто подписывается на интересующие его данные.</p>
<p>Теперь <strong>Order Service</strong> не знает, кто именно реагирует на событие <strong>OrderCreated</strong>. Может, только логистика. Может, логистика и уведомления. А может, ещё и аналитика, CRM, биллинг — без разницы.</p>
<p>Он просто публикует факт: “Заказ создан.” И любой другой сервис может использовать эту информацию, не нарушая независимость архитектуры.</p>
<h3>Надёжность и гибкость</h3>
<p>Kafka гарантирует, что ни одно событие не потеряется:</p>
<ul>
<li>Все сообщения хранятся на диске и могут быть реплицированы на несколько брокеров.</li>
<li>Каждый потребитель знает, до какого сообщения он дочитал (<strong>offset</strong>).</li>
<li>Можно “перемотать” поток назад и перечитать историю заказов — например, если в сервисе логистики произошла ошибка и нужно пересоздать статусы.</li>
</ul>
<p>Благодаря этому, система становится не просто асинхронной, а воспроизводимой: каждый бизнес-процесс можно “переиграть”, восстановить данные или проанализировать прошлые заказы.</p>
<p><strong>Kafka</strong> — это не просто брокер сообщений, а фундаментальный слой событийной архитектуры, на котором можно построить всё: от аналитики и уведомлений до машинного обучения и мониторинга.</p>
<h2>Партиционирование (Partitioning)</h2>
<p>В контексте Apache Kafka <strong>партиционирование (partitioning)</strong> — это метод разделения топика на более мелкие, независимые сегменты, называемые разделами (partitions). Каждый раздел представляет собой лог, в котором сообщения хранятся в порядке их поступления. Партиционирование позволяет Kafka параллелизировать обработку данных, что даёт возможность нескольким потребителям (consumers) одновременно читать данные из разных разделов.</p>
<hr />
<blockquote><p>Данные в разделе хранятся последовательно (append-only log) на диске. Это позволяет эффективно писать и читать сообщения с высокой пропускной способностью.</p></blockquote>
<hr />
<p>Стратегия партиционирования Apache Kafka направлена на достижение нескольких целей: высокая доступность, устойчивость к сбоям, балансировка нагрузки и масштабируемость.</p>
<p>Kafka разбивает топики на разделы, и каждый раздел является независимой единицей данных, которую можно реплицировать между несколькими брокерами.</p>
<p>Партиционирование — это основа горизонтального масштабирования Kafka (единица масштабирования). При добавлении новых разделов система может обрабатывать больший объём данных и поддерживать более высокую параллельность потребителей (больше разделов &#8212; больше параллелизма потребителей).</p>
<p>Кроме того, сообщения внутри одного раздела всегда сохраняют порядок, что важно для приложений, где требуется строгая последовательность событий (<strong>offsets</strong> управляются для каждой <strong>consumer group</strong>, что даёт отказоустойчивое параллельное потребление).</p>
<hr />
<blockquote><p><strong>ВАЖНО</strong></p>
<p>Consumer group = логическая группа потребителей, которые совместно читают данные из одного или нескольких топиков, деля между собой партиции. Это значит, что каждая партиция топика обрабатывается только одним потребителем внутри группы. То есть, в одной consumer group обычно находятся все экземпляры одного сервиса, которые выполняют одну и ту же задачу. Kafka отслеживает смещения (offsets) отдельно для каждой группы, чтобы гарантировать, что одно сообщение не будет прочитано двумя потребителями из одной группы.</p></blockquote>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2332" src="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group.png" alt="" width="1222" height="611" srcset="https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group.png 1222w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group-300x150.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group-1024x512.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group-768x384.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group-450x225.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/apache_kafka_partition_consumer_group-780x390.png 780w" sizes="(max-width: 1222px) 100vw, 1222px" /></a></p>
<hr />
<p>Тема разбивается на несколько разделов, что позволяет параллелить чтение/запись и распределять нагрузку по брокерам. Каждому разделу присваивается смещение (<strong>offset</strong>) для каждого сообщения.</p>
<p>Разделы могут быть реплицированы, один из реплик становится лидером (<strong>leader</strong>), остальные — <strong>followers</strong>. Это обеспечивает отказоустойчивость и доступность.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2316" src="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals.png" alt="" width="2382" height="1067" srcset="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals.png 2382w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-300x134.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-1024x459.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-768x344.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-1536x688.png 1536w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-2048x917.png 2048w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-450x202.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-780x349.png 780w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Internals-1600x717.png 1600w" sizes="(max-width: 2382px) 100vw, 2382px" /></a></p>
<p>Описание схемы (схема демонстрирует базовый принцип устойчивости Kafka: запись — только через лидера, чтение — обычно из лидера, а синхронизация поддерживается через фолловеров):</p>
<ul>
<li><strong>Производитель (Producer)</strong> всегда записывает сообщения в лидера раздела (partition).</li>
<li><strong>Фолловеры (Followers)</strong> автоматически реплицируют данные с лидера, чтобы поддерживать копии лога в актуальном состоянии.</li>
<li><strong>Потребители (Consumers)</strong> из группы потребителей (Consumer Group) обычно читают данные с лидера, чтобы получать подтверждённые сообщения.</li>
</ul>
<p><strong>Внизу показан список ISR (In-Sync Replicas)</strong> — это набор брокеров, чьи копии данных синхронизированы с лидером (в примере ISR = [101, 102, 103]).</p>
<h2>Транзакции и целостность данных</h2>
<p>Kafka поддерживает транзакции, что позволяет атомарно записывать сообщения в несколько разделов/тем и одновременно фиксировать смещения потребителя. Это важно для гарантии <strong>exactly-once</strong> (или ближе к этому) обработки.</p>
<p>При чтении можно выбирать уровень изоляции: <strong>«read_uncommitted» &#8212; читать все подряд</strong> или <strong>«read_committed» &#8212; читать только закоммиченные сообщения</strong> (т.е. получать только завершённые транзакции).</p>
<ul>
<li><strong>Transaction Coordinator</strong> — модуль в брокере Kafka, который управляет транзакциями и отслеживает их состояние.</li>
<li><strong>Transaction Log</strong> — внутренний топик, куда записывается состояние транзакций (например: “начата”, “готова к коммиту”, “завершена”).</li>
<li>Когда продюсер начинает новую транзакцию, он регистрирует свой <code>transactional.id</code> у коорд. После этого он начинает отправлять сообщения обычным образом, но в рамках транзакции. Когда приходит время — либо <code>commitTransaction()</code>, либо <code>abortTransaction()</code>. При коммите Kafka пишет <strong>“маркер”</strong> транзакции в каждую участвующую партицию и фиксирует, что сообщения этой транзакции видимы.</li>
<li>Потребитель, настроенный в режиме <code>isolation.level=read_committed</code>, будет видеть только те записи, которые относятся к <strong>завершённым (committed) транзакциям</strong>, и игнорировать те, что от <strong>незавершённых</strong> или <strong>aborted</strong>.</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2343" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions.png" alt="" width="1676" height="1135" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions.png 1676w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-300x203.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-1024x693.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-768x520.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-1536x1040.png 1536w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-370x250.png 370w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-740x500.png 740w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-450x305.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-780x528.png 780w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_transactions-1600x1084.png 1600w" sizes="(max-width: 1676px) 100vw, 1676px" /></a></p>
<h2>2 модели обмена сообщениями (очередь сообщений и модель публикации-подписки)</h2>
<p><strong>При наличии только одной группы получателей Kafka функционирует как традиционная система очереди сообщений.</strong> Однако, если на тему подписано несколько групп получателей, Kafka ведёт себя как модель публикации/подписки, когда сообщения получают несколько получателей.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_model.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2326" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_model.png" alt="" width="643" height="309" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_model.png 643w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_model-300x144.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_model-450x216.png 450w" sizes="(max-width: 643px) 100vw, 643px" /></a></p>
<p><strong>1. Очередь сообщений (Message Queue / Point-to-Point)</strong> &#8212; каждое сообщение обрабатывается ровно одним потребителем:</p>
<ul>
<li>Сообщения распределяются по разделам (partitions) темы.</li>
<li>Внутри группы потребителей (Consumer Group) Kafka гарантирует, что каждый раздел назначен только одному потребителю.</li>
<li>Таким образом, сообщения из одного раздела не дублируются между потребителями группы.</li>
<li>Это обеспечивает горизонтальное масштабирование обработки — больше потребителей в группе &#8212; больше параллелизма.</li>
</ul>
<p><strong>Пример:</strong></p>
<ul>
<li>Тема orders с 3 разделами.</li>
<li>Группа потребителей order-service из 3 экземпляров.</li>
</ul>
<p>Каждый экземпляр обрабатывает свой раздел &#8212; каждое сообщение читается только один раз в рамках группы.</p>
<p><strong>2. Публикация-подписка (Publish-Subscribe)</strong> &#8212; одно сообщение может быть прочитано множеством независимых потребителей:</p>
<ul>
<li>Разные группы потребителей могут подписываться на одну и ту же тему.</li>
<li>Каждая группа обрабатывает поток независимо от других — <strong>Kafka</strong> хранит смещения (<strong>offsets</strong>) для каждой группы.</li>
<li>Это позволяет нескольким приложениям читать один и тот же поток событий параллельно, не мешая друг другу.</li>
</ul>
<p><strong>Пример: </strong>Тема user-activity.</p>
<p><strong>Группы:</strong></p>
<ul>
<li><strong>analytics-service</strong> (для анализа поведения),</li>
<li><strong>monitoring-service</strong> (для алертов).</li>
</ul>
<p>Обе группы читают одинаковые события, но Kafka ведёт отдельные смещения для каждой.</p>
<h2>Schema Registry (Реестр схем)</h2>
<p>Как только приложения начнут активно отправлять сообщения в Kafka и получать сообщения из него, произойдут два события.</p>
<ul>
<li>Во-первых, появятся новые потребители существующих топиков. Это будут совершенно новые приложения — возможно, написанные той же командой, которая создала исходный продюсер сообщений, а возможно, и другой командой, — и им потребуется понимать формат сообщений в топике.</li>
<li>Во-вторых, формат этих сообщений будет меняться по мере развития бизнеса. Объекты заказов получат новое поле статуса, имена пользователей будут разделены на имя и фамилию вместо полного имени и так далее.</li>
</ul>
<p><strong>Схема наших объектов предметной области</strong> — это постоянно меняющаяся цель, и нам необходимо найти способ согласовать схему сообщений в любом топике.</p>
<p><strong>Schema Registry</strong> предоставляет централизованный репозиторий для управления и проверки схем данных сообщений топиков, а также для сериализации и десериализации данных по сети. Производители и потребители топиков Kafka могут использовать схемы для обеспечения согласованности и совместимости данных по мере развития схем. <strong>Schema Registry</strong> — ключевой компонент управления данными, помогающий обеспечивать качество данных, соответствие стандартам, прозрачность происхождения данных, возможности аудита, совместную работу между командами, эффективные протоколы разработки приложений и производительность системы.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_schema_registry.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2346" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_schema_registry.jpg" alt="" width="651" height="343" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_schema_registry.jpg 651w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_schema_registry-300x158.jpg 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_schema_registry-450x237.jpg 450w" sizes="(max-width: 651px) 100vw, 651px" /></a></p>
<p>Schema Registry работает с:</p>
<ul>
<li><strong>Avro</strong> (классика Kafka-мира, бинарный, компактный)</li>
<li><strong>Protobuf</strong> (Google Protocol Buffers)</li>
<li><strong>JSON Schema</strong> (читаемый, но больше размер сообщений)</li>
</ul>
<p>Реестр схем не включен в Kafka, но существует несколько его вариантов с открытым исходным кодом. Например, <strong><a href="https://github.com/confluentinc/schema-registry" target="_blank" rel="noopener">Реестр Confluent Schema</a></strong>.</p>
<h2>Гарантии доставки сообщений в Kafka</h2>
<p><strong>Под семантической гарантией</strong> понимается <strong>соглашение</strong> между продюсером, брокером и потребителем — как именно сообщения передаются и обрабатываются.</p>
<p>Kafka поддерживает три типа семантики доставки:</p>
<ul>
<li><strong>At most once (не более одного раза)</strong> &#8212; Сообщения доставляются один раз, но при сбое системы часть сообщений может быть потеряна и не будет переотправлена. Минимальная задержка, но есть риск потерь.</li>
<li><strong>At least once (как минимум один раз)</strong> &#8212; Сообщения доставляются один или несколько раз. При сбое система гарантирует, что сообщение не потеряется, но возможны дубликаты. Без потерь, но может потребоваться обработка повторов.</li>
<li><strong>Exactly once (ровно один раз)</strong> &#8212; Каждый сообщение доставляется строго один раз. Оно не теряется и не читается повторно, даже если часть системы выходит из строя. Максимальная надёжность, но выше задержка и сложнее настройка.</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2353" src="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees.jpeg" alt="" width="1565" height="939" srcset="https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees.jpeg 1565w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-300x180.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-1024x614.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-768x461.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-1536x922.jpeg 1536w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-450x270.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/10/Kafka_Message_Delivery_Guarantees-780x468.jpeg 780w" sizes="(max-width: 1565px) 100vw, 1565px" /></a></p>
<p>Эти три подхода отражают компромисс между задержкой и надёжностью. Выбор зависит от требований вашего приложения.</p>
<p><strong>Важно:</strong> многие системы заявляют о поддержке exactly-once, но на деле они не учитывают сбои компонентов за пределами самой системы (например, внешнего продюсера или потребителя).</p>
<p><strong>Kafka же реализует эти гарантии на уровне журнала (log):</strong> как только сообщение записано и подтверждено, оно считается зафиксированным (<strong>committed</strong>). После этого оно не потеряется, пока хотя бы один брокер с репликой этого раздела остаётся «живым».</p>
<h3><strong>Доставка сообщений от продюсера</strong></h3>
<ul>
<li><strong>At most once</strong> &#8212; Для минимальной задержки продюсер может отправлять сообщения асинхронно (“fire and forget”) — то есть не ожидая подтверждения от брокера. Можно также дождаться подтверждения от ведущего брокера (leader broker), чтобы снизить риск потери, но увеличить задержку.<br />
В обоих случаях сообщения доставляются один раз, а при сбое — могут быть потеряны и не будут переотправлены.</li>
<li><strong>At least once</strong> &#8212; В этом режиме, если продюсер не получил подтверждение, что сообщение было зафиксировано, он переотправит его. Это гарантирует доставку как минимум один раз, но при этом одно и то же сообщение может попасть в лог дважды, если первый запрос всё-таки был успешным.<br />
Режим идемпотентного продюсера (idempotent producer) гарантирует, что повторная отправка не создаст дубликатов, а порядок сообщений в журнале сохранится. Для этого брокер присваивает продюсеру уникальный ID и использует порядковый номер (sequence number) для каждого сообщения, чтобы исключить повторную запись одного и того же события.</li>
<li><strong>Exactly once</strong> &#8212; продюсеры могут использовать транзакционную доставку (transactional delivery). В этом режиме продюсер получает подтверждение, что сообщения приняты и реплицированы, при повторной отправке сообщение записывается идемпотентно — существующие данные перезаписываются, а не дублируются. Это добавляет задержку и требует больших ресурсов, но обеспечивает наивысший уровень надёжности.<br />
Чтобы реализовать транзакционные гарантии “exactly once”, потребители также должны быть соответственно сконфигурированы (например, использовать <code>isolation.level=read_committed</code>).</li>
</ul>
<h3><strong>Получение сообщений потребителем (Consumer Receipt)</strong></h3>
<p>Каждое сообщение в разделе (partition) топика имеет последовательный идентификатор — offset.<br />
Все реплики одного раздела содержат одинаковый журнал логов с теми же offset’ами, а потребитель сам управляет своей позицией в этом логе — то есть знает, с какого offset’а продолжать чтение.<br />
Если потребитель выходит из строя, и его работу должен перенять другой потребитель, тот должен знать, с какого offset’а начать читать.</p>
<ul>
<li><strong>At most once — «не более одного раза»</strong> &#8212; Потребитель читает группу сообщений. Сначала сохраняет своё положение (offset). Затем обрабатывает сообщения. Если потребитель завалится после сохранения offset, но до завершения обработки,<br />
новый потребитель начнёт читать с сохранённого offset’а, и уже прочитанные, но не обработанные сообщения будут потеряны. Это семантика “at most once” — в случае сбоя часть сообщений может не обработаться вообще.</li>
<li><strong>At least once — «как минимум один раз»</strong> &#8212; Потребитель сначала обрабатывает сообщения и только потом сохраняет offset. Если сбой произойдёт между обработкой и сохранением offset, новый потребитель, который возьмёт на себя задачу,<br />
прочитает те же сообщения повторно. Таким образом, некоторые сообщения могут быть обработаны дважды, но ни одно не будет потеряно.<br />
Чтобы избежать проблем от повторной обработки, можно использовать идемпотентную запись — например, задавать каждой записи первичный ключ (primary key), чтобы повторное получение просто перезаписало старую запись без дубликатов.</li>
</ul>
<ul>
<li><strong>Exactly once — «ровно один раз»</strong> &#8212; Когда Kafka используется для чтения из одного топика и записи в другой (например, в приложениях Kafka Streams), Kafka реализует exactly-once семантику с помощью транзакций.<br />
Позиция потребителя (offset) сохраняется в виде сообщения в специальном топике Kafka. Эти данные об offset’ах записываются в одной транзакции вместе с результатами обработки, отправляемыми в выходные топики.<br />
Если транзакция откатывается (aborted), то и offset возвращается к предыдущему значению. Таким образом, система возвращается в полностью согласованное состояние.<strong>Какие сообщения видны потребителям:</strong></p>
<ul>
<li><code>isolation.level=read_uncommitted</code> — потребитель видит все сообщения, включая из незавершённых транзакций.</li>
<li><code>isolation.level=read_committed</code> — потребитель читает только сообщения из завершённых транзакций (используется по умолчанию в режиме exactly-once).</li>
</ul>
</li>
</ul>
<h3><strong>Как работает механизм подтверждений (ACK) в Kafka?</strong></h3>
<p><strong>ack (acknowledgement) в Kafka</strong> — это механизм, который позволяет производителю (producer) получать подтверждение от брокера о том, что сообщение было успешно отправлено и обработано. Этот параметр, настраиваемый в конфигурации продюсера, влияет на баланс между надежностью (риском потери данных) и производительностью.</p>
<p>Kafka предлагает три уровня подтверждений, каждый из которых балансирует между надежностью и скоростью. Рассмотрим каждый из них:</p>
<p><strong>acks=0 (Производитель не ждет подтверждения)</strong></p>
<ul>
<li>Fire-and-forget: отправил и забыл</li>
<li>Молниеносная пропускная способность</li>
<li>Сообщения могут потеряться</li>
<li>Подходит для метрик или логов, где потеря нескольких данных не критична</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2365" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0.png" alt="" width="1174" height="630" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0.png 1174w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0-300x161.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0-1024x550.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0-768x412.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0-450x241.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_0-780x419.png 780w" sizes="(max-width: 1174px) 100vw, 1174px" /></a></p>
<p><strong>acks=1 (Продюсер ждет подтверждения от лидера партиции/leader partition)</strong></p>
<ul>
<li>Ожидает подтверждения от лидера</li>
<li>Хорошая скорость при базовой надежности</li>
<li>Есть риск потери сообщений, если лидер выйдет из строя</li>
<li>Подходит для большинства повседневных сценариев использования</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2366" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1.png" alt="" width="1187" height="726" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1.png 1187w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1-300x183.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1-1024x626.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1-768x470.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1-450x275.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_1-780x477.png 780w" sizes="(max-width: 1187px) 100vw, 1187px" /></a></p>
<p><strong>acks=-1 или all (Продюсер ждет подтверждения от всех реплик в синхронизации/In-Sync Replicas, ISR)</strong></p>
<ul>
<li>Ожидает подтверждений от всех реплик</li>
<li>Медленнее, но максимально надежно</li>
<li>Максимальная устойчивость</li>
<li>Идеально подходит для финансовых транзакций</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2367" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all.png" alt="" width="1194" height="822" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all.png 1194w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all-300x207.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all-1024x705.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all-768x529.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all-450x310.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_acks_all-780x537.png 780w" sizes="(max-width: 1194px) 100vw, 1194px" /></a></p>
<p><strong>Сравнительная таблица настроек ACKs</strong></p>
<table>
<thead>
<tr>
<th><strong>Характеристика</strong></th>
<th><strong>acks=0</strong></th>
<th><strong>acks=1</strong></th>
<th><strong>acks=all</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Надёжность сообщений</strong></td>
<td>Низкая</td>
<td>Средняя</td>
<td>Высокая</td>
</tr>
<tr>
<td><strong>Задержка отклика</strong></td>
<td>Минимальная</td>
<td>Средняя</td>
<td>Наибольшая</td>
</tr>
<tr>
<td><strong>Пропускная способность</strong></td>
<td>Максимальная</td>
<td>Средняя</td>
<td>Минимальная</td>
</tr>
<tr>
<td><strong>Риск потери сообщений</strong></td>
<td>Возможна потеря сообщений</td>
<td>Потеря возможна только при сбое лидера</td>
<td>Сообщения не теряются</td>
</tr>
<tr>
<td><strong>Сценарии использования</strong></td>
<td>Метрики и логированиеМониторинг производительности</td>
<td>Регулярные обновленияПотоки аналитики</td>
<td>ПлатежиКритически важные данные</td>
</tr>
<tr>
<td><strong>Нагрузка на CPU</strong></td>
<td>Минимальная</td>
<td>Средняя</td>
<td>Наибольшая</td>
</tr>
<tr>
<td><strong>Сетевые накладные расходы</strong></td>
<td>Минимальные</td>
<td>Средние</td>
<td>Наибольшие</td>
</tr>
</tbody>
</table>
<h3><strong>Повторные попытки отправки сообщений (Retry Kafka)</strong></h3>
<p><strong>Retry</strong> — это механизм повторных попыток отправки или обработки сообщений в Apache Kafka. Он помогает обеспечить надежность, повторно отправляя сообщения в случае временных сбоев, вместо того, чтобы терять их. Существуют два основных подхода: <strong>блокирующие</strong> (когда обработчик замирает в ожидании) и <strong>неблокирующие</strong> (когда сообщение перенаправляется в отдельный топик, чтобы освободить основной поток).</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2375" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism.png" alt="" width="1741" height="1766" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism.png 1741w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-296x300.png 296w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-1010x1024.png 1010w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-768x779.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-1514x1536.png 1514w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-450x456.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-780x791.png 780w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_producer_retry_mechanism-1600x1623.png 1600w" sizes="(max-width: 1741px) 100vw, 1741px" /></a>Может реализоваться 2 сценария, когда ретраи требуются:</p>
<p><strong>Сбой сети:</strong></p><pre class="urvanov-syntax-highlighter-plain-tag">Отправка сообщения → <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2716.png" alt="✖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Сбой сети  
↓  
Ожидание 100 мс и попытка снова  
↓  
Успешная повторная попытка <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Сообщение доставлено</pre><p><strong>Сбой в лидере партиции:</strong></p><pre class="urvanov-syntax-highlighter-plain-tag">Отправка сообщения → <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2716.png" alt="✖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Лидер недоступен  
↓  
Ожидание 100 мс (идёт выбор нового лидера)  
↓  
Повторная отправка <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Новый лидер на линии, сообщение доставлено</pre><p><strong>Ключевые параметры конфигурации retry:</strong></p><pre class="urvanov-syntax-highlighter-plain-tag"># Количество попыток отправки
retries=3                   # Повторить 3 раза

# Интервал между повторными попытками
retry.backoff.ms=100        # Базовый интервал 100 мс

# Общий тайм-аут доставки сообщения
delivery.timeout.ms=120000  # Ожидание до 2 минут

# Включить идемпотентность, чтобы предотвратить дубликаты сообщений при retry
enable.idempotence=true</pre><p></p>
<h2>Анатомия сообщения Kafka</h2>
<p>Сообщение Kafka состоит из следующих элементов:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2361" src="https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure.png" alt="" width="1212" height="852" srcset="https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure.png 1212w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure-300x211.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure-1024x720.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure-768x540.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure-450x316.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/kafka_message_structure-780x548.png 780w" sizes="(max-width: 1212px) 100vw, 1212px" /></a></p>
<p>Структура сообщения Kafka:</p>
<ul>
<li><strong>Key (Ключ).</strong> Ключ является необязательным элементом в сообщении <strong>Kafka</strong> и может быть равен null. Ключ может быть строкой, числом или любым объектом, после чего он сериализуется в бинарный формат.</li>
<li><strong>Value (Значение).</strong> Значение представляет содержимое сообщения и также может быть <code>null</code>. Формат значения произвольный и также сериализуется в бинарный формат.</li>
<li><strong>Compression Type (Тип сжатия).</strong> Сообщения Kafka могут быть сжаты. Тип сжатия можно указать как часть сообщения. Доступные варианты: <code>none</code>, <code>gzip</code>, <code>lz4</code>, <code>snappy</code> и <code>zstd</code>.</li>
<li><strong>Headers (Заголовки).</strong> Может быть список необязательных заголовков сообщения Kafka в виде пар ключ-значение. Обычно заголовки добавляют для указания метаданных о сообщении, особенно для трассировки.</li>
<li><strong>Partition + Offset (Раздел + Смещение).</strong> После того как сообщение отправлено в топик Kafka, ему присваиваются номер раздела и идентификатор смещения (<strong>offset</strong>). Комбинация <strong>topic</strong>+<strong>partition</strong>+<strong>offset</strong> уникально идентифицирует сообщение.</li>
<li><strong>Timestamp (Временная метка).</strong> Временная метка добавляется либо пользователем, либо системой в сообщение.</li>
</ul>
<h2>API Kafka</h2>
<p>Apache Kafka предоставляет пять основных API Java для управления кластерами и клиентами.</p>
<ul>
<li><strong>Producer API</strong> &#8212; позволяет приложениям публиковать (записывать) потоки событий в одну или несколько тем Kafka, предоставляя настройки для подтверждений отправки и сжатия сообщений.</li>
<li><strong>Consumer API</strong> &#8212; позволяет приложениям подписываться на темы и читать поток событий, управляя положением чтения (offset) и количеством извлекаемых данных за один цикл.</li>
<li><strong>Admin Client API</strong> &#8212; предоставляет методы для программного управления кластером Kafka — создания, удаления, описания и изменения ресурсов вроде тем, брокеров и ACL.</li>
<li><strong>Connect API</strong> &#8212; служит фреймворком для встраивания источников и приёмников данных: позволяет перемещать потоки событий между Kafka и внешними системами (СУБД, хранилища, приложения).</li>
<li><strong>Kafka Streams API</strong> &#8212; библиотека для построения приложений и микросервисов, которые читают данные из тем Kafka, преобразуют их (фильтрация, агрегация, join) и записывают результаты обратно в темы.</li>
</ul>
<h1>GitHub проект &#171;kafka-tutorial&#187; &#8212; для понимания основ</h1>
<p>Для статьи я создал отдельный <a href="https://github.com/ivanshamaev/kafka-tutorial" target="_blank" rel="noopener"><strong>тестовый проект &#171;kafka-tutorial&#187; на GitHub</strong></a> для локального развертывания <strong>Kafka</strong> и <strong>Zookeeper</strong> с примерами <strong>producer</strong> и <strong>consumer</strong> на <strong>Python</strong>. Предназначен для изучения и отладки взаимодействия с Kafka.</p>
<h2>Краткое описание библиотеки kafka-python</h2>
<p>Как работает обмен сообщениями между продьюсером и консюмером в библиотеке kafka‑python (клиент для Apache Kafka на Python).</p>
<ul>
<li><strong>Продьюсер:</strong> настраиваем, сериализуем, буферизируем, отправляем через TCP к брокеру-лидеру.</li>
<li><strong>Консюмер:</strong> подключаемся, подписываемся/назначаем партиции, выполняем Fetch запросы, десериализуем, возвращаем сообщения.</li>
<li>Всё взаимодействие реализовано через сетевой протокол <strong>Kafka (TCP)</strong>, библиотека сама строит запросы (Metadata, Produce, Fetch и др), парсит ответы.</li>
</ul>
<h3>Отправка сообщения (Producer)</h3>
<p>Создаётся объект:</p><pre class="urvanov-syntax-highlighter-plain-tag">from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers='localhost:9092',
                          key_serializer=…,
                          value_serializer=…)</pre><p>Здесь библиотека соединяется с брокерами Kafka, получает метаданные (какие топики, какие партиции, какие брокеры лидеры) через Metadata API.</p>
<p>Когда вызывается <code>producer.send(topic, key=…, value=…)</code> процесс выглядит следующим образом:</p>
<ul>
<li>Сериализуется ключ и/или значение через переданные <code>key_serializer/value_serializer</code>.</li>
<li>Сообщение помещается в буфер (в память) для соответствующей партиции. Продусер внутренне ведёт накопитель (<code>RecordAccumulator</code>) и фоновый поток I/O (<code>Sender thread</code>) которые группируют (<code>batch</code>) сообщения и отправляют партиями.</li>
<li>В зависимости от <strong>настроек</strong> (<code>linger_ms</code>, <code>batch_size</code>) может быть задержка прежде чем буфер будет отправлен, чтобы накопить больше сообщений.</li>
<li>Когда пакет сообщений отправляется, используется <strong>бинарный протокол Kafka</strong> (через <strong>TCP</strong>) — библиотека вручную формирует запрос <code>ProduceRequest</code>, посылает его брокеру-лидеру партиции. (Это скрыто в коде, но логика за этим есть: <code>метаданные → выбор партиции → сетевой запрос</code>)Ответ (<code>ProduceResponse</code>) возвращается, и если <code>acks</code> настроено (например <code>acks='all'</code>), продьюсер может ждать подтверждения (или получить ошибку/ретрай) от брокера.</li>
<li>Вы можете получить <code>future = producer.send(...)</code> и дальше <code>future.get(timeout=…)</code> чтобы ждать результата.</li>
<li>Необходимо вызвать <code>producer.flush()</code> перед завершением, чтобы дождаться отправки всех накопленных сообщений (иначе программа может завершиться раньше и сообщения не будут отправлены).</li>
</ul>
<p><strong>Резюме:</strong> Python-код → <code>KafkaProducer.send()</code> → буфер → сетевой запрос к брокеру Kafka → сообщение попадает в соответствующую тему/партицию.</p>
<h3>Получение сообщения (Consumer)</h3>
<p>Создаётся объект:</p><pre class="urvanov-syntax-highlighter-plain-tag">from kafka import KafkaConsumer
consumer = KafkaConsumer('some_topic',
                         bootstrap_servers='localhost:9092',
                         group_id='my_group',
                         key_deserializer=…,
                         value_deserializer=…,
                         auto_offset_reset='earliest')</pre><p>Библиотека подключается к брокерам, получает метаданные, подписывается на топик(и), либо явно назначает партиции (<strong>assign</strong>) или через <strong>subscribe</strong> получает назначение в составе группы потребителей.</p>
<p>После подписки (или назначения) потребитель выполняет цикл <code>for msg in consumer:</code> или вызывает <code>consumer.poll()</code> и получает сообщения:</p>
<ul>
<li>Он делает <code>FetchRequest</code> к брокерам для каждой назначенной партиции, ожидая данные. Конфигурации вроде <code>fetch_min_bytes</code>, <code>fetch_max_wait_ms</code> влияют на задержку/объём.</li>
<li>Когда данные приходят, они десериализуются с помощью <code>key_deserializer/value_deserializer</code>.</li>
<li>В сообщении вы получаете объект <code>ConsumerRecord</code>, у которого есть <code>topic</code>, <code>partition</code>, <code>offset</code>, <code>key</code>, <code>value</code>.</li>
<li>Если используется группа (<code>group_id</code> задана), то библиотека взаимодействует с координатором группы (<code>GroupCoordinator</code>) для ребалансировки, назначений партиций и фиксации смещений (<code>offsets</code>) либо вручную либо автоматически (если <code>enable_auto_commit=True</code>).</li>
</ul>
<p>Например:</p><pre class="urvanov-syntax-highlighter-plain-tag">for msg in consumer:
    print(msg.topic, msg.partition, msg.offset, msg.key, msg.value)</pre><p><strong>Резюме:</strong> Python-код → KafkaConsumer опрос брокеров → получает сообщения из Kafka → возвращает вам десериализованные объекты.</p>
<h1>Обработка потоков (Stream processing) с Kafka Streams</h1>
<p><strong>Kafka Streams</strong> — это клиентская Java-библиотека, которая читает данные из Kafka топиков (источников), выполняет преобразования, агрегации, join’ы, оконные операции, и записывает результаты обратно в Kafka (или во внешние хранилища). И все это происходит в реальном времени.</p>
<p><strong>Приложение на Kafka Streams</strong> — это просто обычный сервис (JVM-программа), без отдельного «кластера стримов». Kafka сама масштабирует обработку через партиции и consumer groups.</p>
<p>В Data Engineering Kafka Streams применяют для:</p>
<ul>
<li>очистки и обогащения данных «на лету» перед записью в DWH;</li>
<li>real-time агрегаций (например, “средний чек за последние 10 минут”);</li>
<li>вычислений метрик и алертов в реальном времени;</li>
<li>построения CDC пайплайнов (Change Data Capture).</li>
</ul>
<h2>Подборка материалов по Kafka Streams</h2>
<ul>
<li><a href="https://kafka.apache.org/documentation/streams/" target="_blank" rel="noopener">Официальная документация на английском (видео)</a> + небольшая документация на английском <a href="https://kafka.apache.org/41/documentation/streams/core-concepts" target="_blank" rel="noopener">Core Concepts</a></li>
<li>Статья <a href="https://zh-efimenko.github.io/demo-kafka-streams/" target="_blank" rel="noopener">&#171;Введение в Kafka Streams&#187;</a> + GitHub <a href="https://github.com/zh-efimenko/demo-kafka-streams" target="_blank" rel="noopener">demo-kafka-streams</a></li>
<li>Статья Habr: <a href="https://habr.com/ru/articles/747658/" target="_blank" rel="noopener">&#171;Потоковая обработка данных с помощью Kafka Streams: архитектура и ключевые концепции&#187;</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=uaT_AJujPnw" target="_blank" rel="noopener">Kafka Streams (На примере OUTBOX pattern, Kafka Connect, Debezium)</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=3dFr9IgQSik" target="_blank" rel="noopener">Kafka Streams // Демо-занятие курса «Apache Kafka»</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=4pWAgB4wzhU" target="_blank" rel="noopener">Kafka Streams: лекция 1 2022-10-10</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=wJeaFLgVd7Q" target="_blank" rel="noopener">Запись вебинара &#171;Kafka Streams: для чего еще можно использовать Kafka</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=5e1oFijrKEM" target="_blank" rel="noopener">Создание потоковых приложений с использованием Kafka Streams // «Java Developer. Professional»</a></li>
<li>YouTube ENG: PlayList <a href="https://www.youtube.com/playlist?list=PLa7VYi0yPIH35IrbJ7Y0U2YLrR9u4QO-s" target="_blank" rel="noopener">&#171;Kafka Streams Tutorials | Kafka Streams 101 (2023)&#187;</a> &#8212; и еще куча других видео на канале <a href="https://www.youtube.com/@Confluent/playlists" target="_blank" rel="noopener">@Confluent/playlists</a></li>
<li>YouTube ENG: PlayList <a href="https://www.youtube.com/playlist?list=PL7dZNxCsTH8fCJwRiWKyED-CLKDtZl08-" target="_blank" rel="noopener">&#171;Kafka Streams: Zero to Hero&#187;</a></li>
<li>YouTube ENG: <a href="https://www.youtube.com/watch?v=jItIQ-UvFI4" target="_blank" rel="noopener">Build a Reactive Data Streaming App with Python and Apache Kafka | Coding In Motion</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=OWI6nvIMIH4" target="_blank" rel="noopener">python kafka spark streaming</a></li>
<li>Статья <a href="https://wiki.programstore.ru/kafka-streams-java/" target="_blank" rel="noopener">&#171;Kafka Streams для начинающих. Потоковая обработка данных в мире Java&#187;</a></li>
<li>YouTube: <a href="https://www.youtube.com/watch?v=3f9UmLO6HtY" target="_blank" rel="noopener">Мощь Kafka Streams. Когда использовать? | Александр Кузнецов | Синимекс</a></li>
<li>Статья Habr: <a href="https://habr.com/ru/articles/451160/" target="_blank" rel="noopener">Apache Kafka и потоковая обработка данных с помощью Spark Streaming</a></li>
</ul>
<h2>Что такое Kafka Streams: основные абстракции – KStream, KTable, топология</h2>
<p>Kafka Streams — это библиотека потоковой обработки данных, встроенная в Apache Kafka. Она позволяет создавать приложения, которые обрабатывают данные в реальном времени непосредственно из Kafka-топиков и записывают результаты обратно в Kafka или во внешние системы. В отличие от фреймворков, требующих отдельного кластера (например, Apache Flink или Spark Streaming), Kafka Streams работает как часть обычного клиентского приложения и масштабируется за счёт механизма партиционирования Kafka.</p>
<p>Основной моделью данных в Kafka Streams является поток событий — непрерывная последовательность записей (пар «ключ–значение»), поступающих из Kafka-топика. Для работы с такими потоками библиотека предоставляет две ключевые абстракции: KStream и KTable.</p>
<p><strong>KStream</strong> представляет собой неизменяемый поток событий, где каждая запись рассматривается как отдельное событие. Поток можно фильтровать, преобразовывать, объединять с другими потоками, группировать или агрегировать. Каждая новая запись в топике немедленно обрабатывается, что делает KStream подходящей моделью для событийных данных — например, логов, кликов, заказов или транзакций.</p>
<p><strong>KTable</strong>, напротив, представляет собой табличное представление данных, отражающее их текущее состояние (последнее состояние для каждого ключа). Каждое новое сообщение с тем же ключом обновляет существующую запись, а не добавляет новую. Таким образом, <strong>KTable можно воспринимать как материализованное состояние</strong>, построенное из потока событий. Эта абстракция используется для агрегаций, подсчётов, хранения текущего состояния или выполнения операций объединения (join) между потоками и таблицами.</p>
<p>Связующим элементом между этими абстракциями является <strong>топология (Topology)</strong> — направленный граф, описывающий последовательность операций обработки данных.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2420" src="https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology.jpg" alt="" width="1080" height="1291" srcset="https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology.jpg 1080w, https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology-251x300.jpg 251w, https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology-857x1024.jpg 857w, https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology-768x918.jpg 768w, https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology-450x538.jpg 450w, https://datatalks.ru/wp-content/uploads/2025/10/streams_architecture_topology-780x932.jpg 780w" sizes="(max-width: 1080px) 100vw, 1080px" /></a></p>
<p>Топология определяет, какие потоки данных читаются, какие преобразования применяются, где сохраняется промежуточное состояние и в какие топики отправляются результаты. Каждая вершина топологии соответствует операции (например, фильтрации, группировке или объединению), а каждое ребро представляет поток данных между этими операциями.</p>
<p><strong>Kafka Streams, таким образом, объединяет концепции потоков и таблиц в единую модель обработки событий</strong>, где данные могут рассматриваться как непрерывный поток изменений или как текущее состояние системы. Это делает библиотеку удобным инструментом для построения реактивных, устойчивых и масштабируемых систем обработки данных в реальном времени.</p>
<h2>Почему и когда использовать: трансформации, фильтрации, агрегаты, соединения потоков</h2>
<p><strong>Kafka Streams стоит рассматривать</strong> не просто как инструмент для обработки событий, а <strong>как логическое продолжение самой Kafka</strong> — средство, которое превращает поток данных в поток знаний.</p>
<p>Главный вопрос, который задаёт себе инженер данных, — зачем использовать Kafka Streams, если уже есть Kafka и, возможно, Spark? Ответ в архитектурной философии: <strong>Kafka Streams — это «ближе к данным», чем большинство других систем.</strong> Она позволяет обрабатывать события там же, где они рождаются, без тяжёлой инфраструктуры и внешних движков. Приложение на Kafka Streams становится умным клиентом Kafka, который не просто читает и пишет сообщения, а выполняет вычисления над ними в реальном времени, сохраняя при этом согласованность состояния и способность к восстановлению.</p>
<p>Использовать Kafka Streams стоит там, где нужны реактивные сценарии обработки: например, <strong>при построении витрин для real-time аналитики, обнаружении аномалий, расчёте метрик на лету, обработке транзакций, обновлении состояния пользователей или формировании рекомендаций.</strong> Она особенно эффективна, когда важна низкая задержка, надёжная обработка каждого события и возможность масштабирования через Kafka partitions, а не через сторонние кластеры.</p>
<p><strong>Когда речь идёт о трансформациях, Kafka Streams превращается в конвейер данных.</strong> С помощью операций <code>map</code>, <code>flatMap</code> и <code>selectKey</code> можно изменять структуру, тип и ключ событий, формируя новые потоки. Это позволяет реализовывать бизнес-логику прямо в коде, а не на уровне ETL-инструментов. Каждое преобразование становится узлом в топологии, и поток данных, проходя через них, постепенно приобретает форму, нужную системе <strong>downstream</strong>.</p>
<p>Фильтрация (<code>filter</code>, <code>filterNot</code>) даёт возможность отсекать ненужные события ещё на раннем этапе. Это особенно важно при работе с большими объёмами данных, где стоимость дальнейшей обработки может быть высока. Потоки становятся чище, а вычисления — экономнее.</p>
<p><strong>Агрегации делают Kafka Streams</strong> мощным инструментом для анализа событий во времени. С помощью операций <code>groupByKey</code>, <code>aggregate</code>, <code>reduce</code> и <code>count</code> можно собирать статистику в реальном времени, отслеживать тренды или поддерживать счётчики. Агрегации в Kafka Streams связаны с концепцией окон — временных диапазонов, внутри которых события группируются. Это позволяет, например, считать количество кликов за последние пять минут или среднюю сумму заказов за день. Такие операции сохраняют состояние в <strong>локальном сторе (RocksDB)</strong>, что делает приложение самодостаточным и отказоустойчивым.</p>
<p>Одной из самых интересных возможностей Kafka Streams являются соединения (<code>joins</code>) — механизм, позволяющий объединять данные из разных потоков или таблиц. Сценарии могут быть разными: объединение двух KStream для корреляции событий из разных систем, соединение <strong>KStream</strong> и <strong>KTable</strong> для добавления справочной информации или <code>join</code> <strong>двух KTable</strong> для синхронизации состояний. При этом Kafka Streams обеспечивает согласованность и упорядоченность данных, что особенно критично для финансовых и аналитических систем.</p>
<p>Таким образом, Kafka Streams стоит использовать там, где данные должны не просто перемещаться, а жить — обновляться, объединяться, фильтроваться и агрегироваться в реальном времени. Это библиотека, которая позволяет думать о данных как о непрерывном процессе, а не о статичном снимке. И в этом её сила: она превращает поток событий в логическую модель, которую можно выразить кодом, а не инфраструктурой.</p>
<h2>Как запустить приложение Streams (конфигурация, запуск, топология)</h2>
<p>Когда речь заходит о запуске приложения Kafka Streams, всё начинается с понимания: мы не поднимаем кластер, мы пишем приложение, которое становится частью распределённой системы.</p>
<p><strong>Kafka Streams</strong> — это не сервис, а библиотека, встроенная в ваше Java-приложение. В этом и заключается её философия — обработка данных должна быть как можно ближе к месту, где выполняется бизнес-логика.</p>
<p>Первым шагом в создании любого приложения Streams является конфигурация. Она определяет, как приложение будет взаимодействовать с Kafka и управлять своим состоянием. Ключевые параметры задаются через объект <code>Properties</code>: <code>application.id</code>, <code>bootstrap.servers</code>, <code>default.key.serde</code>, <code>default.value.serde</code> и другие. Параметр <code>application.id</code> служит не просто идентификатором, а точкой согласования состояния: <strong>Kafka Streams</strong> использует его для хранения метаданных, контрольных точек и топологического состояния в специальных служебных топиках. Поэтому выбор <code>application.id</code> должен быть осознанным — он определяет, сможет ли приложение продолжить работу после перезапуска без потери данных.</p>
<p>Следующим этапом идёт построение топологии — логического графа обработки данных. Для этого используется <strong>StreamsBuilder</strong>, объект, через который определяются источники (<strong>stream</strong> и <strong>table</strong>), преобразования (<code>map</code>, <code>filter</code>, <code>join</code>, <code>aggregate</code>) и выходные точки (<code>to</code>). Каждый вызов метода добавляет новый узел в топологию, формируя конвейер обработки. <strong>Эта топология в итоге становится «дорожной картой» данных:</strong> Kafka Streams компилирует её в <strong>набор задач (tasks)</strong>, каждая из которых отвечает за обработку части данных из определённого раздела Kafka. Таким образом, масштабирование достигается естественным образом — за счёт распределения задач по инстансам приложения.</p>
<p>Когда топология определена, создаётся объект <code>KafkaStreams</code>. Именно он связывает логику обработки с реальной инфраструктурой Kafka. Запуск осуществляется вызовом метода <code>start()</code>, после чего приложение начинает читать сообщения из входных топиков, применять трансформации и записывать результаты в выходные топики. Под капотом Kafka Streams автоматически управляет состоянием: создаёт локальные сторы (например, RocksDB), периодически синхронизирует их с changelog-топиками и обрабатывает сбои с помощью механизма восстановления состояния.</p>
<p>Завершение работы должно быть таким же аккуратным, как и запуск. Метод <code>close()</code> позволяет корректно остановить приложение, завершить обработку текущих сообщений и синхронизировать состояние. В продакшене часто используется <strong>shutdown hook</strong>, чтобы при получении сигнала завершения (например, <code>SIGTERM</code>) приложение Streams успевало завершить все операции.</p>
<p><strong>Таким образом, запуск Kafka Streams можно описать как соединение трёх слоёв:</strong> конфигурация, определяющая контекст выполнения; топология, описывающая бизнес-логику обработки; и исполнение, связывающее код с Kafka и обеспечивающее надёжность, масштабирование и отказоустойчивость.</p>
<p><strong>Приложение Streams</strong> — это не просто потребитель и продюсер, а полноценный участник экосистемы Kafka, способный мыслить в терминах потоков, состояний и событий, превращая данные в реальном времени в управляемый и воспроизводимый процесс.</p>
<h2>Состояние и state stores, оконная обработка (windowing), exactly-once семантика</h2>
<p>Когда приложение Kafka Streams начинает работать с состоянием, оно выходит за рамки простой потоковой обработки и превращается в систему, способную помнить контекст. В этом и заключается фундаментальное отличие Kafka Streams от большинства других библиотек — она не просто реагирует на события, а хранит знание о прошлом, делая возможным агрегаты, join-операции и анализ во времени.</p>
<p><strong>Состояние (state)</strong> — это локальные данные, которые приложение поддерживает между событиями. Когда выполняется агрегирование, подсчёт или обновление значения по ключу, Kafka Streams сохраняет промежуточный результат в специальном хранилище, называемом state store. Это может быть встроенная база RocksDB, in-memory store или кастомное решение. Каждый инстанс приложения хранит своё состояние локально, что позволяет ему работать автономно и с минимальной задержкой. Но, несмотря на локальность, надёжность обеспечивается через механизм changelog-топиков: каждое изменение состояния записывается в Kafka, что даёт возможность полностью восстановить state при сбое или перемещении задачи на другой узел.</p>
<p><strong>Kafka Streams делает состояние «живым».</strong> Это не просто кеш, а часть потокового вычисления. Приложение может напрямую обращаться к локальному стору, использовать интерактивные запросы и даже предоставлять доступ к состоянию внешним системам. Такая архитектура позволяет строить event-driven микросервисы, которые не только реагируют на поток данных, но и опираются на накопленные знания.</p>
<p>Другим ключевым элементом является <strong>оконная обработка (windowing).</strong> В потоковом мире данные бесконечны, и чтобы их агрегировать, необходимо ограничить время наблюдения. Kafka Streams вводит окна — логические границы, разделяющие поток событий на временные сегменты. Окна бывают скользящие, фиксированные и сдвигаемые. Например, можно подсчитывать количество покупок за каждые 10 минут или находить среднее значение температуры за последние 5 секунд.</p>
<p>Важный момент — окно не просто отсекает время, оно управляет тем, какие события считаются «совместимыми». Каждое событие имеет временную метку, и Streams использует её для определения, к какому окну оно относится. При этом предусмотрена гибкость: можно задавать допустимые задержки (grace period), чтобы учесть события, пришедшие с опозданием, но всё ещё относящиеся к нужному окну.</p>
<p>Работа с состоянием и окнами невозможна без гарантии корректности обработки. Здесь вступает в силу exactly-once семантика — одна из важнейших возможностей Kafka Streams. Она обеспечивает, что каждое сообщение будет обработано строго один раз, даже в случае сбоев, перезапусков или дублированных сообщений.</p>
<p><strong>Механизм exactly-once</strong> основан на транзакциях Kafka и согласованной записи в changelog-топики. Каждая операция, затрагивающая состояние и производящая выходные сообщения, выполняется в рамках атомарной транзакции. Если что-то идёт не так — транзакция откатывается, и состояние возвращается в согласованное состояние. Это гарантирует, что ни одно событие не будет потеряно и не будет обработано дважды.</p>
<p><strong>Именно комбинация state stores, окон и exactly-once семантики</strong> превращает Kafka Streams в полноценную платформу для построения детерминированных потоковых приложений. Здесь поток не просто обрабатывается — он управляется, обогащается и осмысляется.</p>
<p>Kafka Streams делает возможным создание систем, где каждое событие не просто проходит сквозь поток, а оставляет след — формируя устойчивую, воспроизводимую и надёжную модель данных во времени.</p>
<h2>Что такое ksqlDB?</h2>
<hr />
<p>YouTube: Курс по KsqlDB на английском <a href="https://www.youtube.com/playlist?list=PLa7VYi0yPIH3ulxsOf5g43_QiB-HOg5_Y" target="_blank" rel="noopener">&#171;ksqlDB and Stream Processing Tutorials | ksqlDB 101&#187;</a></p>
<hr />
<p><a href="https://github.com/confluentinc/ksql" target="_blank" rel="noopener"><strong>ksqlDB</strong></a> — это эволюция идей Kafka Streams, превращённая в полноценную потоковую базу данных. Если <strong>Kafka Streams</strong> — это библиотека для разработчиков, то ksqlDB — это инструмент для инженеров и аналитиков, позволяющий описывать потоковую обработку не в коде, а с помощью знакомого SQL. Она создана, чтобы сделать работу с потоками данных такой же естественной, как запросы к реляционным таблицам.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2423" src="https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka.png" alt="" width="1256" height="910" srcset="https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka.png 1256w, https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka-300x217.png 300w, https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka-1024x742.png 1024w, https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka-768x556.png 768w, https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka-450x326.png 450w, https://datatalks.ru/wp-content/uploads/2025/10/ksqldb_kafka-780x565.png 780w" sizes="(max-width: 1256px) 100vw, 1256px" /></a></p>
<p><strong>В своей сути ksqlDB строится поверх Kafka и Kafka Streams.</strong> Каждый запрос, который вы пишете в виде SQL-команды, компилируется в топологию Streams, выполняемую под капотом. Это значит, что вся надёжность, отказоустойчивость и масштабируемость Kafka Streams автоматически становятся частью вашего SQL-приложения.</p>
<p><strong>Главная идея ksqlDB</strong> — рассматривать потоки и таблицы как первоклассных граждан в SQL-мире. <strong>Потоки (STREAM)</strong> представляют собой последовательность событий, где каждое сообщение фиксирует факт: клик, транзакцию, лог, метрику. <strong>Таблицы (TABLE)</strong> отражают текущее состояние, агрегаты или материализованные результаты — именно как KTable в Streams. Взаимодействие между ними естественно: поток можно агрегировать в таблицу, а таблицу можно обновлять событиями из потока.</p>
<p>ksqlDB позволяет делать всё то же, что Kafka Streams, но декларативно: фильтровать данные (<code>WHERE</code>), преобразовывать (<code>SELECT</code>, <code>CAST</code>), агрегировать (<code>GROUP BY</code>, <code>COUNT</code>, <code>SUM</code>), соединять потоки (<code>JOIN</code>) и работать с окнами (<code>WINDOW</code>). При этом каждый запрос становится живым — он не возвращает статичный результат, а формирует непрерывный поток обновлений.</p>
<p>В отличие от традиционных баз данных, где запросы завершаются, в ksqlDB они живут во времени. Создавая поток или таблицу через SQL-запрос, вы фактически запускаете постоянное вычисление, которое обновляется с приходом новых данных в Kafka. Все результаты можно записывать обратно в топики, использовать для downstream-систем или даже делать запросы напрямую через <strong>REST API</strong>.</p>
<p>Кроме того, <strong>ksqlDB включает встроенное хранилище состояния.</strong> Это значит, что вы можете не только выполнять потоковые операции, но и сохранять результаты, а затем делать к ним запросы, словно к обычной базе данных. Таким образом, <strong>ksqlDB</strong> объединяет концепции потоковой обработки и транзакционного состояния в одном инструменте.</p>
<p>С точки зрения архитектуры, <strong>ksqlDB</strong> — это сервис, который подключается к вашему кластеру Kafka, управляет топологиями Streams и поддерживает API для работы с потоками данных. Вы можете запускать его как единый сервер или в распределённом режиме, масштабируя под нагрузку.</p>
<p><strong>ksqlDB</strong> — это шаг вперёд в эволюции Kafka: она делает потоковую обработку доступной не только программистам, но и аналитикам, DevOps-инженерам и архитекторам данных. Это SQL-язык, который разговаривает с событиями, а не с таблицами — язык, в котором время становится таким же измерением данных, как строки и столбцы.</p>
<p>С помощью ksqlDB поток превращается в понятную, управляемую и интерактивную структуру, где события живут, изменяются и взаимодействуют — а данные текут так же естественно, как запросы к ним.</p>
<p>Сообщение <a href="https://datatalks.ru/apache-kafka-tutorial-101-consumer-producer-topic/">Apache Kafka Tutorial 101: Архитектура, Consumer, Producer, Topic</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datatalks.ru/apache-kafka-tutorial-101-consumer-producer-topic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
