Дизайн Kafka, реплицированные журналы, выборы лидера
Неясные выборы лидера: что, если они все не доступны?
Обратите внимание, что гарантия Kafka в отношении потери данных основана на сохранении как минимум одной реплики в синхронизации. Если все узлы, реплицирующие раздел, умирают, эта гарантия больше не действует.
Однако практическая система должна делать что-то разумное, когда все реплики умирают. Если вам не повезло, что это произошло, важно подумать о том, что произойдет. Можно реализовать два варианта поведения:
- Подождите, пока реплика в ISR вернется к жизни, и выберите эту реплику в качестве лидера (надеясь, что у нее все еще есть все данные).
- Выберите первую реплику (не обязательно в ISR), которая вернется к жизни в качестве лидера.
Это простой компромисс между доступностью и согласованностью. Если мы будем ждать реплик в ISR, мы останемся недоступными, пока эти реплики не работают. Если такие реплики были уничтожены или их данные были потеряны, то мы навсегда отключились. С другой стороны, если несинхронизированная реплика оживает и мы позволяем ей стать лидером, то ее журнал становится источником правды, даже если не гарантируется наличие всех зафиксированных сообщений. По умолчанию, начиная с версии 0.11.0.0, Kafka выбирает первую стратегию и предпочитает ожидание согласованной реплики. Это поведение можно изменить с помощью свойства конфигурации unclean.leader.election.enable для поддержки случаев использования, когда время безотказной работы предпочтительнее согласованности.
Эта дилемма характерна не только для Kafka. Она существует в любой схеме, основанной на кворумах. Например, при мажоритарной схеме голосования, если на большинстве серверов происходит постоянный сбой, вы должны либо выбрать потерю 100% своих данных, либо нарушить согласованность, приняв то, что осталось на существующем сервере, в качестве нового источника истины.
Гарантии доступности и долговечности
При записи в Kafka производители могут выбрать, будут ли они ждать подтверждения сообщения 0,1 или всеми (-1) репликами. Обратите внимание, что «подтверждение всеми репликами» не гарантирует, что полный набор назначенных реплик получил сообщение. По умолчанию, когда acks=all, подтверждение происходит, как только все текущие синхронизированные реплики получили сообщение. Например, если в теме настроено только две реплики и одна не работает (т.е. остается только одна синхронизированная реплика), то записи, в которых указано acks=all, будут успешными. Однако эти записи могут быть потеряны, если оставшаяся реплика также выйдет из строя. Хотя это обеспечивает максимальную доступность раздела, такое поведение может быть нежелательным для некоторых пользователей, которые предпочитают надежность доступности. Поэтому мы предоставляем две конфигурации на уровне темы, которые можно использовать, чтобы предпочесть надежность сообщений доступности:
- Отключить выбор неясного лидера - если все реплики станут недоступны, то раздел останется недоступным до тех пор, пока последний лидер не станет снова доступен. Это фактически предпочитает недоступность риску потери сообщения.
- Укажите минимальный размер ISR - раздел будет принимать записи, только если размер ISR выше определенного минимума, чтобы предотвратить потерю сообщений, которые были записаны только в одну реплику, которая впоследствии становится недоступной. Этот параметр вступает в силу только в том случае, если производитель использует acks=all и гарантирует, что сообщение будет подтверждено, по крайней мере, этим количеством синхронизированных реплик. Этот параметр предлагает компромисс между согласованностью и доступностью. Более высокое значение минимального размера ISR гарантирует лучшую согласованность, поскольку сообщение гарантированно будет записано в большее количество реплик, что снижает вероятность его потери. Однако это снижает доступность, поскольку раздел будет недоступен для записи, если количество синхронизируемых реплик упадет ниже минимального порога.
Управление репликами
Вышеупомянутое обсуждение реплицированных журналов действительно касается только одного журнала, то есть одного раздела темы. Однако кластер Kafka будет управлять сотнями или тысячами этих разделов. Kafka пытается сбалансировать разделы в кластере циклически, чтобы избежать кластеризации всех разделов для больших тем на небольшом количестве узлов. Точно так же Kafka пытается сбалансировать лидерство, чтобы каждый узел был лидером для пропорциональной доли своих разделов.
Также важно оптимизировать процесс выборов лидера, поскольку это критическое окно недоступности. Наивная реализация выбора лидера закончится тем, что выборы для каждого раздела будут выполняться для всех разделов, размещенных на узле, когда этот узел отказал. Вместо этого мы выбираем одного из брокеров в качестве «контролера». Этот контролер обнаруживает сбои на уровне брокера и отвечает за смену лидера всех затронутых разделов в отказавшем брокере. В результате мы можем группировать многие из необходимых уведомлений о смене лидерства, что значительно удешевляет и ускоряет процесс выборов для большого количества разделов. Если контролер выйдет из строя, новый контролер станет одним из оставшихся в живых брокеров.
Читайте также:
Комментарии
Отправить комментарий