При реализации алгоритма Рафта я обнаружил, что есть ситуация, которая, я думаю, может или не может нанести вред кластеру.
Разумно предположить, что некоторые AppendEntriesRPC от Лидера получены с переупорядочением (сетевая задержка или другие причины). Предположим, что Лидер отправляет одноранговый сигнал AppendEntriesRPC на узел A с prev_log_index = 1
, а затем отправляет еще один AppendEntriesRPC с записью 2, а затем происходит сбой (я гарантирую, что это произойдет немедленно с помощью обратного вызова в моем тесте). Если два RPC обрабатываются в порядке их отправки, запись 2 будет успешно вставлена. Однако, если RPC сердцебиения задерживается, то узел A сначала вставит запись 1 и ответит Лидеру. Затем идет задержанное сердцебиение, узел A сотрет запись 2, потому что запись конфликтует с prev_log_index = 1
Лидера. Таким образом, peer A по ошибке удаляет запись в журнале.
Если покопаться немного глубже, если Лидер не рухнет сразу, это исправит это? Я думаю, что если узел A правильно отреагирует на задержку сердцебиения, Лидер обнаружит и исправит это в некоторых последующих RPC.
Однако, что если ответ пэра А на запись 2 приведет к продвижению commit_index
? В этом случае равный A голосует за продвижение commit_index
до 2, даже если у него фактически нет записи 2. Так что может быть недостаточно голосов для этого продвижения. Когда Leader падает, узел с меньшим количеством журналов будет выбран в качестве Leader. И я сталкиваюсь с такой ситуацией во время тестирования.
Мой вопрос:
- Верны ли мои рассуждения?
- Если переупорядочить RPC - реальная проблема, как мне это решить? Является ли индексирование и кэширование всех RPC и принудительно обрабатывать их один за другим хорошим решением? Мне было трудно реализовать в gRPC.