Лабораторная работа 4. Apache Kafka 4.3.1, KRaft Запуск: docker compose up -d docker compose ps Создание топика: docker compose exec kafka-1 /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server kafka-1:19092 \ --create --topic orders --partitions 3 --replication-factor 3 \ --config min.insync.replicas=2 Описание партиций и поиск лидеров: docker compose exec kafka-1 /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server kafka-1:19092 --describe --topic orders Отправка сообщений с ключами и acks=all: docker compose exec kafka-1 /opt/kafka/bin/kafka-console-producer.sh \ --bootstrap-server kafka-1:19092 --topic orders \ --reader-property parse.key=true --reader-property key.separator=: \ --command-property acks=all Пример строки: order-17:created При отправке без ключа стандартный producer использует sticky-партицию до заполнения или отправки пакета. Поэтому короткая серия может остаться в одной партиции. Для контролируемого распределения по кругу запустите producer без parse.key и с явным partitioner: docker compose exec kafka-1 /opt/kafka/bin/kafka-console-producer.sh \ --bootstrap-server kafka-1:19092 --topic orders \ --command-property acks=all \ --command-property \ partitioner.class=org.apache.kafka.clients.producer.RoundRobinPartitioner Даже если короткое чтение случайно показывает возрастающие номера, Kafka гарантирует порядок только внутри каждой партиции. В отчёте опирайтесь прежде всего на распределение событий одного заказа по партициям. Чтение ключей, партиций и оффсетов: docker compose exec kafka-1 /opt/kafka/bin/kafka-console-consumer.sh \ --bootstrap-server kafka-1:19092 --topic orders --from-beginning \ --formatter-property print.key=true --formatter-property print.partition=true \ --formatter-property print.offset=true Остановить нужно именно лидера исследуемой партиции, найденного командой --describe. Например: docker compose kill kafka-2 docker compose start kafka-2 Для опыта с acks=1 используйте программный producer с enable.idempotence=false: он должен записывать номер в журнал только после успешного завершения send, чтобы момент подтверждения был наблюдаемым. Убейте лидера сразу после заранее выбранного подтверждения. Локальные реплики могут успеть скопировать весь хвост до kill, поэтому ноль потерянных сообщений — корректный результат отдельного запуска. Повторите опыт и зафиксируйте точные условия; если применяете сетевую задержку репликации, не разрывайте контроллерный кворум. Не заменяйте наблюдение заранее обещанным числом потерь. При остановке двух узлов из трёх запись перестаёт успешно завершаться. В этом компактном стенде узлы совмещают роли broker и controller, поэтому одновременно теряются большинство ISR и кворум KRaft. Клиент может получить NOT_ENOUGH_REPLICAS, отсутствие лидера или TimeoutException — запишите фактический результат, не ожидая обязательного кода ошибки. Удаление стенда вместе с учебными данными: docker compose down -v