Как происходит репликация данных в Apache Kafka?

Ответ

Репликация в Kafka — это ключевой механизм для обеспечения отказоустойчивости и долговечности данных. Она работает на уровне партиций топика.

Модель Лидер-Последователь (Leader-Follower)

  1. Лидер (Leader): Для каждой партиции один из брокеров выбирается лидером. Только лидер обрабатывает все запросы на запись и чтение для этой партиции.
  2. Последователи (Followers): Остальные брокеры, на которых размещены копии партиции, становятся последователями. Их единственная задача — асинхронно копировать данные с лидера.

In-Sync Replicas (ISR)

ISR — это множество реплик (включая лидера), которые не сильно отстают от лидера. Реплика считается "in-sync", если она успевает запрашивать у лидера новые сообщения в пределах времени, заданного параметром replica.lag.time.max.ms (по умолчанию 30 секунд).

Процесс записи и подтверждения (acks)

Надежность записи напрямую зависит от настройки acks у продюсера:

  • acks=0: Продюсер не ждет подтверждения от брокера. Максимальная производительность, но возможна потеря данных.
  • acks=1 (по умолчанию): Продюсер ждет подтверждения только от лидера. Запись считается успешной, как только лидер записал сообщение в свой лог. Данные могут быть потеряны, если лидер упадет до того, как последователи скопируют сообщение.
  • acks=all (или -1): Продюсер ждет подтверждения от лидера после того, как все реплики из ISR скопировали сообщение. Это обеспечивает максимальную гарантию сохранности данных, но с более высокой задержкой.

Отказоустойчивость

Если брокер-лидер падает, Kafka Controller выбирает нового лидера из числа реплик, находящихся в ISR. Это гарантирует, что новый лидер обладает всеми подтвержденными сообщениями.

Если все реплики из ISR становятся недоступны, Kafka по умолчанию (с unclean.leader.election.enable=false) не будет выбирать нового лидера, предпочитая недоступность партиции потере данных.

// Пример создания топика с фактором репликации 3
// Используется библиотека confluent-kafka-go

adminClient, err := kafka.NewAdminClient(&kafka.ConfigMap{"bootstrap.servers": brokers})
// ... обработка ошибки

_, err = adminClient.CreateTopics(ctx, []kafka.TopicSpecification{{
    Topic:             "my-topic",
    NumPartitions:     6,
    ReplicationFactor: 3, // 1 лидер и 2 реплики для каждой партиции
}})

Ответ 18+ 🔞

Так, слушай, а вот эта ваша репликация в Кафке — это ж, блядь, не просто так, а чтоб если один брокер накрылся медным тазом, данные не улетели в пизду. Всё крутится вокруг партиций, понял?

Модель Главный-Подчинённый (Leader-Follower)

  1. Главный (Leader): Для каждой партиции один брокер — главный по району. Только он принимает все записи и читает. Остальные — так, подпевалы.
  2. Подчинённые (Followers): Остальные брокеры с копиями этой партиции. Их работа — тупо тянуть данные с главного, как попугаи, асинхронно.

In-Sync Replicas (ISR) — «В строю»

ISR — это, грубо говоря, отряд бойцов (включая главного), которые не сильно отстали. Реплика считается «в строю», если она успевает за главным в течение replica.lag.time.max.ms (по дефолту 30 секунд). Если отстал больше — вылетаешь из отряда, мартышлюшка.

Как пишем и подтверждаем (acks)

Тут вся магия в настройке acks у продюсера. От неё зависит, насколько ты готов рискнуть.

  • acks=0: Продюсер плюёт и отправляет дальше, не ждёт ни хуя. Скорость — овердохуища, но данные могут просто испариться, и ты даже не узнаешь.
  • acks=1 (по умолчанию): Ждём кивка только от главного. «Записал у себя? Окей, поехали дальше». Данные могут потеряться, если главный рухнет, не успев передать эстафету подчинённым. Волнение ебать.
  • acks=all (или -1): Вот это надёжность, мать её. Продюсер ждёт, пока ВСЕ бойцы из отряда ISR не скопируют сообщение. Данные почти неубиваемые, но ждать, блядь, дольше. Терпения ноль ебать.

Если всё пошло по пизде (Отказоустойчивость)

Упал главный брокер? Не беда. Контроллер Кафки выберет нового главного из тех, кто «в строю» (ISR). Новый будет знать всё, что знал старый.

А если ВЕСЬ отряд ISR полег? Тут два пути. По умолчанию (unclean.leader.election.enable=false) Кафка скажет: «Ну нахуй, лучше вообще не работать, чем выбрать какого-нибудь отстающего и потерять данные». Честная позиция.

// Пример создания топика с фактором репликации 3
// Используется библиотека confluent-kafka-go

adminClient, err := kafka.NewAdminClient(&kafka.ConfigMap{"bootstrap.servers": brokers})
// ... обработка ошибки

_, err = adminClient.CreateTopics(ctx, []kafka.TopicSpecification{{
    Topic:             "my-topic",
    NumPartitions:     6,
    ReplicationFactor: 3, // 1 главный и 2 подчинённых для каждой партиции
}})

Вот и вся философия. Хочешь скорость — рискуй. Хочешь надёжность — жди. А репликация — это чтобы твои данные не стали призраками в случае пиздеца.