Восстановление после сбоя и гарантия согласованности
После того, как определенный фрагмент данных доставлен в определенную систему потоковой обработки, система обрабатывает этот фрагмент данных только один раз, и это идеальная ситуация для обеспечения гарантии Exactly-Once. Если система не дает сбоев, она просто идеальна. Однако в реальном мире на системы часто влияют различные неожиданные факторы и они выходят из строя, например, скачки трафика, колебания сети и проблемы с распределением ресурсов облачных служб. В случае сбоя Flink перезапускает задание, считывает данные в контрольной точке, восстанавливает состояние и повторно выполняет расчет.
Механизм состояния и контрольно-пропускного пункта Flink:
Контрольная точка и процесс восстановления после сбоя могут обеспечить согласованность внутреннего состояния, но возникает проблема повторной передачи данных, как показано на следующем рисунке. Предположим, что отметка времени последней контрольной точки системы равна 3, система дает сбой с отметкой времени 10, и система обработала некоторые данные между 3 и 10 после контрольной точки и до сбоя (данные с отметками времени 5 и 8 на рисунке). С точки зрения Бога, мы предполагаем, что система выходит из строя с временной меткой 10, но в реальном сценарии мы не можем предсказать время сбоя, только после того, как произойдет сбой, мы получим информацию о тревоге и узнаем, что последняя временная метка контрольной точки равна 3. . После перезапуска мы можем восстановить самые последние данные контрольной точки, и состояние всего задания инициализируется с отметкой времени 3. Для обеспечения согласованности необходимо повторно обработать данные после временной метки 3. В этом примере повторно обрабатываются данные с временными метками 5 и 8. Процесс Checkpoint Flink обеспечивает согласованность данных в задании, главным образом потому, что Flink выполняет резервное копирование двух типов данных:- Состояние каждого оператора в задании
- Смещение входных данных
Процесс ретрансляции данных похож на просмотр игры в прямом эфире.Даже если мы пропустим какие-то прекрасные моменты, мы сможем снова посмотреть повтор из видео.Английское слово Replay может очень ярко описать эту сцену. Но возникает проблема, заключающаяся в том, что данные между временными метками 3 и 10 повторно отправляются. До сбоя эта часть данных обрабатывалась некоторыми операторами и, возможно, даже отправлялась во внешнюю систему, после перезагрузки данные отправляются снова. Часть данных обрабатывается не только один раз, но и может обрабатываться несколько раз (по крайней мере один раз). С точки зрения точности результатов мы ожидаем, что часть данных повлияет на конечный результат только один раз. Если система может гарантировать, что часть данных повлияет на конечный результат только один раз, мы говорим, что система обеспечивает сквозную гарантию «Точно один раз».
End-to-end EXACTLY-ONCE — одна из самых сложных проблем в области распределенных систем, и многие фреймворки пытаются решить эту проблему. В этом вопросе согласованность внутреннего состояния Flink в основном зависит от механизма CheckPoint, а согласованность внешних взаимодействий в основном зависит от некоторых источников и приемников. Источник должен поддерживать функцию повторной отправки, SINK должен записывать определенную технологию записи данных, например мощность и т. д. или транзакцию.
Для функции повторения источника, как показано на рисунке выше, пока мы записываем входное смещение OFFSET, отправитель данных перезапустится со смещения после входного смещения OFFSET. Помимо отправки данных в дополнение к отправке данных, продукты Kafka также сохраняют данные в файл журнала. Если нижестоящее приложение перезапущено, Producter перемещается из постоянного файла в данные в соответствии с нижестоящим смещением и может перезапустить данные в нижестоящем направлении.
Повторная передача источника приведет к тому, что часть данных будет обрабатываться несколько раз.Чтобы гарантировать, что они повлияют на нижестоящую систему только один раз, также необходимо полагаться на идемпотентную запись или транзакционную запись приемника. Эти два понятия выделены ниже.
идемпотентная запись
Идемпотентная операция записи означает, что запись данных в систему любое количество раз повлияет на целевую систему только один раз. Например, повторение доHashMap
Вставьте ту же двоичную пару ключ-значение вHashMap
изменения, последующие операции вставки не изменятсяHashMap
Результатом этого является мощная операция записи. Повторение целого числа для выполнения операций сложения не является степенью, потому что целое число станет больше после нескольких операций.
Базы данных KV, такие как Cassandra, HBase и Redis, часто используются в качестве приемников для достижения сквозной точности Exactly-Once. Следует отметить, что это не означает, что база данных KV поддерживает идемпотентную запись на 100%. Для идемпотентного письма требуются пары KV, то есть ключ-значение должно вычисляться детерминистически. Если ключ, который мы разработали:name + curTimestamp
, каждый раз, когда данные передаются повторно, сгенерированный ключ отличается, и будет сгенерировано несколько результатов, и вся операция не является идемпотентной. Поэтому, чтобы реализовать сквозную технологию Exactly-Once, мы должны изо всех сил стараться использовать детерминированную вычислительную логику и модель данных при разработке бизнес-логики.
В качестве приемника база данных KV также может столкнуться с феноменом возврата во времени. Мы по-прежнему возьмем только что повторную передачу данных в качестве примера, предполагая, что данные временной метки 5 вычисляются для создания(a, t=5)
Пара KV метки времени 8 рассчитывается для генерации(a, t=8)
В результате разные элементы влияют на один и тот же ключ. Перед перезапуском(a, t=5)
и(a, t=8)
Предоставляется в базу данных последовательно, два ряда данных основаны на одном и той же ключе, когда(a, t=8)
При отправке в базу данных база данных обычно считает, что текущая отправка является последней, она будет(a, t=5)
Эта строка старых данных перезаписывается, и в это время она должна быть сохранена в базе данных.(a, t=8)
этот результат. К сожалению, неудачная перезагрузка произошла позже, и на начальный период после перезагрузки(a, t=5)
Отправьте его в базу данных еще раз, база данных ошибочно думает, что на этот раз это снова последняя операция, она снова обновит ключ, но на самом деле откатится к отметке времени 5. Только когда все последующие данные будут переданы повторно и все ключи, которые должны быть перезаписаны, будут перезаписаны последними данными, вся система достигнет согласованного состояния данных. Следовательно, с этой точки зрения, данные в базе данных KV, вероятно, будут несогласованными в процессе перезапуска.Когда повторная передача данных завершена, данные восстанавливаются до согласованности, и тогда они могут обеспечить сквозную точность. Раз гарантия. .
запись транзакции
Транзакция - это основная проблема, которая должна быть решена системой базы данных. Flink рисует на технологии транзакции в базе данных, объединяя свой собственный механизм контрольно-пропускного пункта, чтобы обеспечить влияние только на внешний выход.
В двух словах, запись транзакции Flink означает, что Flink сначала сохраняет данные для вывода и пока не отправляет их во внешнюю систему, а ожидает окончания контрольной точки, когда данные всех вышестоящих и нижестоящих операторов Flink будут последовательный. , и отправить все ранее сохраненные данные во внешнюю систему. Другими словами, во внешнюю систему записываются только данные, подтвержденные Checkpoint. В примере повторной передачи данных, как показано на рисунке ниже, если используется запись транзакции, во внешнюю систему передаются только выходные данные до временной метки 3, а данные после временной метки 3 (например, данные, сгенерированные временной меткой 5 и 8). ) временно сохраните его и подождите, пока следующая контрольная точка запишется во внешнюю систему вместе. Это позволяет избежать того, что данные с меткой времени 5 будут давать несколько результатов и многократно записываться во внешнюю систему.
Что касается конкретной реализации записи транзакций, Flink в настоящее время предоставляет два метода: журнал с опережающей записью (Write-Ahead-Log, WAL) и двухэтапная фиксация (Two-Phase-Commit, 2PC). Эти два метода также являются протоколами, которые часто используются многими базами данных и распределенными системами для реализации транзакций.Flink внесла адаптивные корректировки в эти два протокола в соответствии со своими собственными сценариями. Основное различие между двумя методами заключается в том, что метод WAL более универсален и подходит практически для всех внешних систем, но он не может обеспечить 100% end-to-end Exactly-Once, если внешняя система сама поддерживает транзакции (например, Kafka). , вы можете использовать способ 2PC, чтобы обеспечить 100% сквозную передачу Exactly-Once. Мы подробно рассмотрим оба способа в следующих статьях.
Способ записи транзакций может обеспечить сквозную согласованность Exactly-Once, и его стоимость также весьма очевидна, то есть жертвование задержкой. Выходные данные больше не записываются во внешние системы в режиме реального времени, а передаются пакетами. В настоящее время не существует идеального механизма восстановления после отказа и гарантии Exactly-Once, поэтому разработчикам необходимо балансировать между различными требованиями.