Внутреннее поведение ZooKeeper по сценарию с разделенным мозгом

Я пытаюсь понять внутреннюю работу Apache ZooKeeper в ситуациях разделения мозга. Предположим, что существует кластер из 5 серверов: A, B, C, D и E, где A - лидер. Предположим теперь, что подкластер {A, B} отделен от подкластера {C, D, E}.

В этом случае субкластер {C, D, E} может выбрать нового лидера и добиться прогресса. С другой стороны, {A, B} не может добиться прогресса, поскольку большинство узлов не подтверждают обновления.

Мне интересно:

  • Что происходит со старым лидером A? Я ожидаю, что он потеряет лидерство, но как это происходит? Активный лидер периодически проверяет, есть ли у него большинство подписчиков?

  • Что происходит с клиентами, которые были подключены к A и B? Будет ли они автоматически перенаправляться на один из серверов, которые все еще могут добиться прогресса (C, D или E). Вернее, они застряли с A или B, пока раскол мозга не исцелится, и весь кластер повторно подключен?

Спасибо, Габриэль

Ответ 1

После некоторых экспериментов с локальным кластером, я думаю, что я понял поведение.

Я начал локальный кластер из 5 узлов, а затем снял 2 узла. Остальные 3 узла все еще составляли большинство, поэтому кластер работал и работал. Я подключил клиента в этот момент.

Затем я снял еще один сервер, после чего оставшиеся 2 узла не могут поддерживать работу кластера.

1) В журнале одного из двух оставшихся узлов (который оказался лидером) я мог видеть:

[myid: 5] - WARN [RecvWorker: 3: QuorumCnxManager $RecvWorker @762] - Соединение нарушено для id 3, my id = 5, error = java.io.EOFException         в java.io.DataInputStream.readInt(DataInputStream.java:392)         на org.apache.zookeeper.server.quorum.QuorumCnxManager $RecvWorker.run(QuorumCnxManager.java:747)

и позже

[myid: 5] - INFO [QuorumPeer [myid = 5]/127.0.0.1:2185:[email protected]] - Новый выборы. Мой id = 5, предлагается zxid = 0x300000002

Итак, кажется, что узлы активно контролируют связь и реагируют на сброшенные соединения (в этом случае попробуйте выбрать другого лидера).

2) В журналах подключенного клиента я мог видеть:

[myid:] - INFO [main-SendThread (localhost: 2185): ClientCnxn $SendThread @966] - Открытие подключение сокета к серверу localhost/127.0.0.1: 2185. Не будет пытаться для аутентификации с использованием SASL (неизвестная ошибка)

[myid:] - INFO [main-SendThread (localhost: 2185): ClientCnxn $SendThread @849] - Socket соединение установлено на localhost/127.0.0.1: 2185, инициирование Сессия

[myid:] - INFO [main-SendThread (localhost: 2185): ClientCnxn $SendThread @1085] - Невозможно для чтения дополнительных данных с сервера sessionid 0x343d9a80f220000, вероятно, сервер закрыл разъем, закрывая соединение сокета и попытка повторного подключения

Таким образом, node закрывает соединение, открытое клиентом, из-за того, что кластер не работает.

В этом случае весь кластер был отключен, поэтому клиент продолжает пытаться подключиться к одному из узлов, без везения. Но я предполагаю, что в случае сценария с разделенным мозгом, когда большинство все еще работает и работает где-то, клиент в конечном итоге сможет подключиться к нему (при условии, что он имеет сетевое подключение, конечно).

Ответ 2

1) Лидер отправляет пакет ping всем подписчикам, когда подписчики принимают ping, а затем отправляют данные сеанса обратно к лидеру, если подписчик мертв или отключается от лидера, тогда лидер удаляет этого последователя из него syncedAckSet, если лидер syncedAckSet меньше половины размера кластера. тогда свинец сам отключится.