Как Кафка обрабатывает сетевые разделы?
У Кафки есть концепция набора синхронных реплик, который представляет собой набор узлов, которые не слишком отстают от лидера.
Что произойдет, если сеть чисто разделится так, чтобы меньшинство, содержащее лидера, было на одной стороне, а большинство, содержащее другие синхронные узлы, на другой стороне?
Предположительно, меньшинство / лидерская сторона думает, что потеряло кучу узлов, соответственно уменьшило размер ISR и успешно продолжает работу.
Другая сторона, вероятно, думает, что потеряла лидера, поэтому выбирает нового и счастливо продолжает.
Теперь у нас есть два лидера в одном кластере, которые принимают записи независимо друг от друга. В системе, которой требуется большинство узлов для продолжения работы после раздела, старый лидер уходит в отставку и прекращает принимать записи.
Что происходит в этой ситуации в Кафке? Требуется ли большинство голосов для изменения набора ISR? Если да, происходит ли краткая потеря данных, пока сторона лидера не обнаружит перебои?
1 ответ
В кластере Kafka один из брокеров выбирается в качестве контролера.
Помимо прочего, контролер отвечает за выбор новых лидеров. Раздел управления репликами кратко описывает это: http://kafka.apache.org/documentation/
Кафка использует Zookeeper, чтобы убедиться, что одновременно используется только 1 контроллер. Однако описанная вами ситуация все еще может произойти, разделив ансамбль Zookeeper (при условии, что обе стороны все еще могут иметь кворум) и кластер Kafka на 2, в результате чего будет получено 2 контроллера.
В этом случае Kafka имеет несколько конфигураций для ограничения воздействия:
unclean.leader.election.enable
: Ложно по умолчанию, это используется для предотвращения того, чтобы реплики, которые не были синхронизированы, никогда не становились лидерами. Если никакие доступные реплики не синхронизированы, Kafka помечает раздел как отключенный, предотвращая потерю данныхreplication.factor
а такжеmin.insync.replicas
: Например, если вы установите их на 3 и 2 соответственно, в случае "раздельного мозга" вы можете запретить производителям отправлять записи на сторону меньшинства, если они используютacks=all
См. Также KIP-101 для получения подробной информации об обработке журналов, которые разошлись после того, как кластер снова вернулся.
I haven't tested this, but I think the accepted answer is wrong and Lars Francke is correct about the possibility of brain-split.
Zookeeper quorum requires a majority, so if ZK ensemble partitions, at most one side will have a quorum.
Being a controller requires having an active session with ZK (ephemeral znode registration). If the current controller is partitioned away from ZK quorum, it should voluntarily stop considering itself a controller. This should take at most zookeeper.session.timeout.ms = 6000
. Brokers still connected to ZK quorum should elect a new controller among themselves. (based on this: /questions/17700673/skolko-kontrollerov-kafka-v-klastere-i-kakova-tsel/17700679#17700679)
Being a topic-partition leader also requires an active session with ZK. Leader that lost a connection to ZK quorum should voluntarily stop being one. Elected controller will detect that some ex-leaders are missing and will assign new leaders from the ones in ISR and still connected to ZK quorum.
Now, what happens to producer requests received by the partitioned ex-leader during ZK timeout window? There are some possibilities.
If producer's acks = all
and topic's min.insync.replicas = replication.factor
, then all ISR should have exactly the same data. The ex-leader will eventually reject in-progress writes and producers will retry them. The newly elected leader will not have lost any data. On the other hand it won't be able to serve any write requests until the partition heals. It will be up to producers to decide to reject client requests or keep retrying in the background for a while.
Otherwise, it is very probable that the new leader will be missing up to zookeeper.session.timeout.ms + replica.lag.time.max.ms = 16000
worth of records and they will be truncated from the ex-leader after the partition heals.
Let's say you expect longer network partitions than you are comfortable with being read-only.
Something like this can work:
- you have 3 availability zones and expect that at most 1 zone will be partitioned from the other 2
- in each zone you have a Zookeeper node (or a few), so that 2 zones combined can always form a majority
- in each zone you have a bunch of Kafka brokers
- each topic has
replication.factor = 3
, one replica in each availability zone,min.insync.replicas = 2
- producers'
acks = all
This way there should be two Kafka ISRs on ZK quorum side of the network partition, at least one of them fully up to date with ex-leader. So no data loss on the brokers, and available for writes from any producers that are still able to connect to the winning side.