Обзор Airbyte: перенос данных через коннекторы строится вокруг трёх сущностей. Source читает данные из системы-источника, destination пишет их в хранилище, а connection связывает пару и задаёт расписание. Документация проекта на docs.airbyte.com описывает платформу как средство репликации: данные из сотен источников сводятся в хранилища, озёра и базы, а затем уходят в операционные системы вроде CRM и маркетинговых платформ.
Архитектура source/destination/connection
В документации Airbyte на docs.airbyte.com связка описана прямо: данные движутся от sources к destinations, а отношение между источником и приёмником называется connection. Это разделение задаёт порядок работы. Сначала настраивается source — подключение к базе, API или сервису с учётом прав доступа. Затем destination — хранилище, куда лягут таблицы. Затем connection — расписание, набор streams и режим синхронизации для каждого потока.
Платформа поставляется в вариантах self-managed и cloud-managed, плюс гибридные схемы. В self-managed развёртывание идёт на вашем железе или в вашей инфраструктуре, в облачных вариантах инфраструктуру держит вендор. Документация перечисляет несколько способов работы: пользовательский интерфейс, API, Python SDK, Java SDK, Terraform Provider, PyAirbyte и Airbyte MCP для агентов. Выбор способа определяет, как вы будете повторять настройку: руками в UI или кодом.
Для команды это означает разный уровень контроля. UI удобен для разовой настройки и просмотра логов. API и Terraform дают воспроизводимость: конфигурацию источников и приёмников можно хранить в репозитории и переносить между средами. PyAirbyte подходит для сценариев в Jupyter Notebook и ранних прототипов, где сервер поднимать не нужно. Документация отдельно оговаривает: PyAirbyte — библиотека для перемещения данных, а управление инстансом идёт через API или Python SDK.
Практический вывод для архитектуры: connection — единица изменений. Правки расписания, режима и набора потоков применяются к паре source/destination. Если один и тот же источник должен кормить два хранилища, это два разных connection с независимыми настройками и независимой историей сбоев.
Локальный запуск Airbyte Core описан в quickstart на docs.airbyte.com. Требуется Docker Desktop, затем утилита abctl, затем команда abctl local install. Документация рекомендует машину с 4 и более CPU и минимум 8 ГБ памяти; для слабых машин есть low-resource mode, где недоступен Connector Builder. Пароль по умолчанию выдаёт abctl local credentials, сменить его можно флагом --password.
Full refresh и incremental
Документация Airbyte на странице sync modes объясняет логику через имя режима. Первая часть имени говорит, как source читает данные: Incremental читает записи, добавленные с прошлой синхронизации, Full Refresh читает всё содержимое источника. Вторая часть имени говорит, как destination пишет: Overwrite заменяет прежние данные, Append добавляет к существующим таблицам, Append Deduped сначала добавляет историю изменений, а итоговую таблицу строит дедупликацией по первичному ключу, Overwrite Deduped заменяет данные и дедуплицирует результат по ключу.
Интерфейс предлагает комбинации, доступные для конкретной пары коннекторов и потока: Incremental Append, Incremental Append + Deduped, Full Refresh Append, Full Refresh Overwrite, Full Refresh Overwrite + Deduped. Доступность режима проверяют для конкретной пары source/destination, поскольку не каждый источник умеет отдавать дельту, и не каждый приёмник умеет дедуплицировать.
| Режим | Чтение из source | Запись в destination | Когда подходит |
|---|---|---|---|
| Full Refresh Overwrite | всё содержимое | замена прежних данных | небольшие справочники, полная перезагрузка |
| Full Refresh Append | всё содержимое | добавление к таблице | аудит снимков, история полных выгрузок |
| Incremental Append | только новые и изменённые записи | добавление версий | журнал изменений, сырой слой |
| Incremental Append + Deduped | только новые и изменённые записи | добавление и дедупликация по ключу | актуальный слой с последним состоянием |
Первая синхронизация в режиме Incremental равна Full Refresh: все записи считаются новыми. Дальше источник отдаёт только дельту. Документация предупреждает о росте: в Incremental Append размер данных в хранилище увеличивается монотонно, поскольку обновлённая запись добавляется как новая строка. Если нужен только последний снимок, применяют Append + Deduped либо периодические задания очистки, оставляющие последнюю версию каждой записи.
Cursor и primary key
Cursor — значение, по которому определяется, нужно ли реплицировать запись в инкрементальной синхронизации. Документация приводит типичный пример: отметка времени из колонки updated_at. Cursor field — это поле или колонка, где лежит значение; cursor — само значение, по которому принимается решение. Набор записей, которые источник считает новыми или изменёнными, называется delta.
Часть источников определяет cursor сама. Документация называет Exchange Rates: источник знает, что для определения последней синхронизированной записи используется поле даты. В таких случаях в UI достаточно выбрать инкрементальный режим на вкладке Schema. Другие источники требуют выбора: в Postgres пользователь сам указывает колонку, которая станет cursor field.
Primary key решает другую задачу. В Incremental Append обновлённая запись добавляется к прежним, поэтому в приёмнике накапливается несколько строк с одним и тем же значением ключа. Дедупликация по primary key даёт актуальный слой, где на ключ приходится одна строка. Ключ и cursor работают в паре: cursor определяет, что забрать из источника, ключ объединяет версии одной записи при дедупликации.
Учебный пример, который помогает проверить настройку. Пусть source содержит две версии одной записи и одну новую: sync1 — (id1, updated_at=10:00, amount=100); sync2 — (id1, updated_at=11:00, amount=120) и (id2, updated_at=11:05, amount=50). Здесь cursor = updated_at, primary key = id. В сыром слое при Incremental Append ожидаются три версии. В актуальном слое при Append + Deduped по ключу id остаются id1 = 120 и id2 = 50.
Проверка результата: count(distinct id) = 2, актуальная сумма = 170. Сумму сырых событий 270 использовать как актуальную выручку нельзя — это накопленная история версий. Этот набор ручной и учебный, он не является запуском Airbyte и не подтверждает фактическое число физических строк в сыром слое. Инкрементальная доставка даёт гарантию at-least-once, а включающий cursor может повторно передать последнюю строку, поэтому уникальность ключей и последнее состояние проверяют отдельно от числа повторов.
Пример двух синхронизаций
Разберём порядок действий на учебном наборе выше. Шаг первый: выбрать source и destination, убедиться, что для потока доступен инкрементальный режим. Шаг второй: на вкладке Schema указать cursor field — колонку updated_at. Шаг третий: выбрать режим записи. Для журнала изменений подходит Incremental Append, для актуального слоя — Incremental Append + Deduped с ключом id.
Шаг четвёртый: запустить первую синхронизацию. Она отработает как Full Refresh и заберёт текущее состояние источника. Шаг пятый: изменить данные в источнике — обновить amount у id1 и добавить id2. Шаг шестой: запустить вторую синхронизацию и посмотреть, что легло в приёмник.
| Слой | После sync1 | После sync2 |
|---|---|---|
| Сырой, Append | id1 = 100 | id1 = 100, id1 = 120, id2 = 50 |
| Актуальный, Append + Deduped | id1 = 100 | id1 = 120, id2 = 50 |
Шаг седьмой: сверить результат запросами. Число уникальных ключей в актуальном слое равно 2. Сумма amount в актуальном слое равна 170. Сумма по сырому слою даёт 270 и отражает историю.
Шаг восьмой: проверить поведение при повторе. Инкрементальная доставка даёт гарантию at-least-once, поэтому повторный запуск может снова передать последнюю строку. Уникальность ключей и последнее состояние проверяют отдельным запросом. Число физических строк в сыром слое учитывает повторы доставки.
Изменение схемы и удаления
Документация Airbyte на странице incremental append описывает поведение cursor при изменениях. Источник извлекает дельту запросом вида SELECT * FROM table WHERE cursor_field >= 'last_sync_max_cursor_field_value'. Если запись изменили, не обновив cursor field, изменение не попадёт в дельту: значение cursor не превышает максимум прошлой синхронизации. Документация приводит пример, где запись с updated_at = 1754 остаётся незамеченной, поскольку максимум прошлой синхронизации равен 1755.
Второй случай — недостаточная гранулярность. Если cursor field имеет точность до дня, а синхронизация идёт дважды в сутки, источник не может определить, какие записи этого дня уже передавались. По соглашению источники предпочитают повторно отправить данные при неоднозначном cursor. Третий случай — несколько изменений одной записи за период между синхронизациями: при редком расписании промежуточные состояния не будут замечены, в приёмник попадёт состояние на момент запуска.
Схема источника меняется отдельно от данных. Страница Incremental Append описывает Full Refresh Overwrite как вариант повторной загрузки после добавления, переименования или удаления колонки. Этот совет нужно сверить с документацией выбранных source/destination и потока: он не устанавливает общую политику schema evolution для всех коннекторов.
Удаления требуют отдельного механизма. Cursor отслеживает появление и изменение записей, а факт удаления строки в источнике по одному cursor не подтверждается. Документация указывает на подход на основе бинарных логов и Write-Ahead-Logs — Change Data Capture. Поддержку CDC и обработку удалений проверяют для конкретного коннектора и потока, поскольку она зависит от возможностей источника.
Проверки до production
До перевода connection в рабочий режим стоит пройти короткий чек-лист. Он опирается на поведение, описанное в документации Airbyte, и на учебный пример выше.
- Режим доступен для пары source/destination и конкретного потока. Проверяют в UI на вкладке Schema.
- Cursor field выбран и обновляется при каждом изменении записи. Изменения записей без обновления cursor могут не попасть в дельту.
- Гранулярность cursor достаточна для расписания. При точности до дня и запуске дважды в сутки ожидаются повторы.
- Primary key определён и уникален. От него зависит дедупликация в актуальном слое.
- Часовой пояс приведён к UTC. Расхождение зон сдвигает границу дельты.
- Политика обработки null в cursor field зафиксирована. Записи с пустым cursor требуют отдельного решения.
- Backfill спланирован. Первая инкрементальная синхронизация равна полной выгрузке и создаёт нагрузку на источник.
- Права доступа source ограничены чтением нужных таблиц.
- Сверка после повтора описана. Проверяют уникальность ключей и последнее состояние отдельно от числа строк в сыром слое.
- Удаления и CDC проверены для конкретного коннектора.
- Для изменений схемы источника согласован порядок действий по документации выбранных коннекторов.
Контракт переноса удобно зафиксировать текстом, чтобы проверки не расходились между средами. Ниже учебный шаблон, который заполняется под конкретную таблицу.
Контракт переноса таблицы
Источник: [система, база, схема, таблица]
Приёмник: [хранилище, схема, таблица]
Поток: [имя stream]
Режим: [Incremental Append | Incremental Append + Deduped | Full Refresh Overwrite]
Cursor field: [колонка, например updated_at]
Гранулярность cursor: [секунда | минута | день]
Primary key: [колонка или набор колонок]
Часовой пояс: UTC
Политика null в cursor: [пропускать | считать минимальным | остановить синхронизацию]
Backfill: [дата старта | полная выгрузка]
Права доступа: [роль источника, только чтение]
Проверка после синхронизации:
count(distinct primary_key) = [ожидаемое число]
сумма по актуальному слою = [ожидаемое значение]
число строк в сыром слое сверяется отдельно
Удаления: [поддержка CDC у коннектора: да | нет | проверяется]
Изменения схемы: [подтверждённая политика и порядок повторной загрузки выбранных коннекторов].
Этот шаблон — учебный, он не является результатом запуска Airbyte и не подтверждает лимиты продукта. Его задача — сделать проверки явными до того, как connection начнёт работать по расписанию.
Частые вопросы
Что такое Airbyte простыми словами?
Это платформа репликации данных. Source читает данные из системы-источника, destination пишет их в хранилище, а connection связывает пару и задаёт расписание и режим синхронизации. Документация проекта на docs.airbyte.com описывает платформу как средство сведения данных из множества источников в хранилища, озёра и базы. Работать можно через UI, API, SDK, Terraform или PyAirbyte.
Чем отличается Full Refresh от Incremental?
Full Refresh читает всё содержимое источника, Incremental читает записи, добавленные с прошлой синхронизации. Первая инкрементальная синхронизация равна полной выгрузке. Вторая часть имени режима описывает запись в приёмник: Overwrite заменяет данные, Append добавляет версии, Append Deduped строит актуальный слой дедупликацией по ключу.
Как выбрать cursor и primary key?
Cursor — значение, по которому определяется необходимость репликации записи; типичный пример — отметка времени из колонки updated_at. Primary key определяет, какие версии относятся к одной записи при дедупликации. Cursor field выбирают в UI на вкладке Schema, если источник не определяет его сам. Колонка cursor должна обновляться при каждом изменении записи.
Что происходит при изменении схемы источника?
Порядок обработки изменений схемы проверяют для конкретной пары коннекторов и потока. Страница Incremental Append описывает Full Refresh Overwrite как вариант повторной загрузки после изменения схемы. Применимость этого шага и поддержку schema evolution нужно подтвердить по документации выбранных коннекторов.
Как проверить, что данные перенеслись корректно?
Сверяют число уникальных значений primary key и сумму по актуальному слою. В учебном примере это count(distinct id) = 2 и сумма 170. Сумма по сырому слою даёт 270 и отражает историю версий. Уникальность ключей и последнее состояние проверяют отдельно от числа физических строк, поскольку инкрементальная доставка даёт гарантию at-least-once.
