Гарантия exactly-once

По умолчанию стриминг в SPYT даёт гарантию at-least-once — запись в выходную таблицу и фиксация смещения консьюмера выполняются независимо, поэтому при повторной обработке микробатча после сбоя в таблице могут появиться дубликаты.

Если дубликаты недопустимы, в SPYT есть два способа обеспечить exactly-once:

Подход

Принцип работы

Когда использовать

Транзакционный режим (SPYT 2.10+)

exactly-once для любых трансформаций, включая join и stateful. Запись данных и фиксация смещения выполняются в одной транзакции атомарно

Когда важна корректность данных: финансовая аналитика, ML-признаки, инкрементальное построение витрин

Идемпотентный приёмник

exactly-once только для stateless 1:1 трансформаций. Повторная запись строк по уникальному составному ключу не создаёт дубликатов (upsert)

Когда нежелательна дополнительная нагрузка на RPC-прокси от транзакционного режима, или при поддержке старого кода

Важно

Оба подхода гарантируют exactly-once только в рамках Spark-джобов в YTsaurus: гарантия покрывает запись в выходную таблицу и фиксацию смещения консьюмера. На внешние системы — запись в стороннюю БД, отправку сообщений в другие очереди, вызовы внешних API — гарантия не распространяется. Для таких сценариев нужны дополнительные меры на уровне приложения.

Если дубликаты в выходных данных допустимы, дополнительных настроек не требуется — нетранзакционный стриминг работает по умолчанию.

Производительность

Ниже — результаты замеров пропускной способности транзакционного режима относительно других подходов: нетранзакционного стриминга и идемпотентного приёмника.

Условия: синтетические нагрузки NEXMark-стиля, очередь 5 млн строк (16 таблетов, средний размер строки ~70 байт), 8 экзекьюторов × 2 ядра, коммунальный RPC-прокси в обоих режимах для честного сравнения.

Тип нагрузки

Режим

Пропускная способность

Стрим-статик join с shuffle по ключу

Нетранзакционный стриминг

~22 700 строк/с

Транзакционный стриминг

~26 200 строк/с (+13%)

Stateful-агрегация в 1-минутных событийных окнах

Нетранзакционный стриминг

~13 900 строк/с

Транзакционный стриминг

~14 000 строк/с (в пределах шума)

Сравнение с идемпотентным приёмником (passthrough 1 млн строк, 1 экзекьютор × 1 ядро)

Идемпотентный приёмник (сортированная таблица)

~2 000 строк/с

Транзакционный стриминг

~2 600 строк/с (+23%)

Транзакционный режим выигрывает там, где много мелких записей или есть shuffle (join, groupBy, агрегации): одна транзакция вместо нескольких десятков сокращает накладные расходы на коммиты. На stateful с малым объёмом выхода амортизировать нечего, поэтому разницы практически нет.

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

См. также

Предыдущая