Введение
Решил проанализировать статью, описывающую некоторые интересные детали потоковой обработки ровно один раз: exactly-once. Дело в том, что некоторые авторы очень странно понимают термины. Разбор статьи как раз позволит прояснить многие детали более глубже, т.к. выявление нелогичностей и странностей позволяет более полноценно прочувствовать понятия и смысл.
Приступим.
Анализ
Начинается все очень даже неплохо:
Distributed event stream processing has become an increasingly hot topic in the area of Big Data. Notable Stream Processing Engines (SPEs) include Apache Storm, Apache Flink, Heron, Apache Kafka (Kafka Streams), and Apache Spark (Spark Streaming). One of the most notable and widely discussed features of SPEs is their processing semantics, with “exactly-once” being one of the most sought after and many SPEs claiming to provide “exactly-once” processing semantics.
Т.е., обработка данных крайне важна и т.п., а особенно обсуждаемая тема — это exactly-once. Обсудим же ее.
There exists a lot of misunderstanding and ambiguity, however, surrounding what exactly “exactly-once” is, what it entails, and what it really means when individual SPEs claim to provide it.
Действительно, очень важно понимать, что же это такое. Для этого было бы неплохо дать правильное определение перед пространными рассуждениями. Да и кто я такой, чтобы давать такие чертовски здравые советы?
I’ll discuss how “exactly-once” processing semantics differ across many popular SPEs and why “exactly-once” can be better described as effectively-once
Выдумывание новых терминов — это, безусловно, важная задача. Сам люблю это дело. Только для этого необходимо обоснование. Попробуем его найти.
Я не буду описывать очевидные вещи по типу направленных графов обработки и прочее. Читатели могут самостоятельно почитать оригинальную статью. Тем более, что для анализа эти детали малосущественны. Приведу лишь картинку:
Далее, идет описание семантик:
- At-most-once, т.е. не более одного раза. При кажущейся очевидности, такое поведение крайне сложно гарантировать при краевых сценариях по типу падений, нарушение сетевой связности и другое. Но для автора тут все просто:
- At-least-once, т.е. не менее одного раза. Схема более сложная. И граблей можно насобирать поболее:
- Exactly-once. Что же такое exactly-once?
Events are guaranteed to be processed “exactly once” by all operators in the stream application, even in the event of various failures.
Т.е. гарантия обработки exactly-once — это когда произошла обработка "ровно один раз".
Чувствуете мощность определения? Перефразирую: обработка один раз — это когда обработка происходит "один раз". Ну да, там еще говорится про то, что эта гарантия должна сохраняться и в случае отказов. Но для распределенных систем это вещь очевидная. И кавычки намекают на то, что что-то тут не так. Давать определения с кавычками, не объясняя, что это означает — признак глубокого и вдумчивого подхода.
Далее идет описание способов реализации такой семантики. И здесь я бы хотел остановиться более подробно.
Two popular mechanisms are typically used to achieve “exactly-once” processing semantics.
- Distributed snapshot/state checkpointing
- At-least-once event delivery plus message deduplication
Если первый механизм по поводу снепшотов и чекпоинтов вопросов не вызывает, ну кроме некоторых деталей типа эффективности, то со вторым есть небольшие проблемы, о которых автор умолчал.
Почему-то подразумевается, что обработчик может быть только детерминированным. В случае же недетерминированного обработчика каждый последующий перезапуск будет давать, вообще говоря, другие выходные значения и состояния, а значит дедупликация не будет работать, т.к. выходные значения будут другие. Таким образом, общий механизм будет гораздо сложнее, нежели описанный в статье. Или, говоря прямо, такой механизм некорректный.
Однако переходим к самому вкусному:
Is exactly-once really exactly-once?
Now let’s reexamine what the “exactly-once” processing semantics really guarantees to the end user. The label “exactly-once” is misleading in describing what is done exactly once.
Говорится о том, что пора бы уже пересмотреть это понятие, т.к. есть какие-то нестыковки.
Some might think that “exactly-once” describes the guarantee to event processing in which each event in the stream is processed only once. In reality, there is no SPE that can guarantee exactly-once processing. To guarantee that the user-defined logic in each operator only executes once per event is impossible in the face of arbitrary failures, because partial execution of user code is an ever-present possibility.
Дорогому автору стоит напомнить то, как работают современные процессоры. Каждый процессор при обработке выполняет большое количество параллельных стадий. Более того, есть ветвления, при которых процессор начинает выполнять не те действия если предсказатель переходов ошибся. В этом случае действия откатываются. Таким образом, обработчик один и тот же кусок кода, внезапно, может исполнить дважды, даже если никаких отказов не произошло!
Внимательный читатель тут же воскликнет: так ведь важен выхлоп, а не то, как это исполняется. Именно! Важно то, что произошло в результате, а не то, как на самом деле это происходило. Если результат такой, как если бы это происходило ровно один раз, так значит и произошло это ровно один раз. Не находите? А все остальное — это шелуха, не относящееся к делу. Системы сложны, и получаемые абстракции создают лишь иллюзию выполнения определенным образом. Нам кажется, что код выполняется последовательно, инструкция за инструкцией, что сначала идет чтение, потом запись, потом новая инструкция. Но это не так, все гораздо сложнее. И сущность правильных абстракций и заключается в том, чтобы поддерживать иллюзию простых и понятных гарантий, без ковыряния вглубь каждый раз, когда надо присвоить значения переменной.
И как раз вся проблема этой статьи и заключается в том, что exactly-once — это абстракция, позволяющая строить приложения, не задумываясь о дубликатах и потерянных значениях. Что все будет нормально, даже в случае падения. И изобретать для этого новые термины нет необходимости.
Пример же кода в статье наглядно демонстрирует отсутствие понимания того, как надо писать обработчики:
Map (Event event) {
Print "Event ID: " + event.getId()
Return event
}
Читателю предлагается самостоятельно переписать код, чтобы не повторять ошибок автора статьи.
So what does SPEs guarantee when they claim “exactly-once” processing semantics? If user logic cannot be guaranteed to be executed exactly once then what is executed exactly once? When SPEs claim “exactly-once” processing semantics, what they’re actually saying is that they can guarantee that updates to state managed by the SPE are committed only once to a durable backend store.
Пользователю не нужна гарантия физического исполнения кода. Зная, как работает процессор, легко заключить, что такое невозможно. Главное — логическое исполнение ровно один раз, как будто отказов и не было вовсе. Привлечение же понятий "коммита в хранилище данных" лишь усугубляет отсутствие понимания автором базовых вещей, т.к. существуют реализации подобной семантики без необходимости в наличии коммита.
Для более подробной информации можно кратко ознакомиться с моей статьей: Гетерогенная конкурентная обработка данных в реальном времени строго один раз.
In other words, the processing of an event can happen more than once but the effect of that processing is only reflected once in the durable backend state store.
То, что есть "durable backend state store" пользователю абсолютно фиолетово. Важен лишь эффект от обработки, т.е. консистентное состояние и выходные значения на всем промежутке выполнения обработки потоковых данных. Стоит отметить, что для некоторых задач нет необходимости иметь durable backend state store, а гарантировать exactly once было бы неплохо.
Here at Streamlio, we’ve decided that effectively-once is the best term for describing these processing semantics.
Типичный пример бестолкового ввода понятий: напишем некоторый пример и пространные рассуждения на целый абзац, а в конце допишем, что "мы так определяем это понятие". Точность и четкость определений вызывает по-настоящему яркий эмоциональный отклик.
Выводы
Непонимание сути абстракций приводит к искажению исходного смысла существующих понятий и последующем выдумыванием новых терминов на пустом месте.
[1] Exactly once is NOT exactly the same.
[2] Гетерогенная конкурентная обработка данных в реальном времени строго один раз.
Автор: Григорий Демченко