Apache Avro: schemat jest umową, którą podpisują wasze systemy

Agent, który przygotowuje decyzje kredytowe u dystrybutora, czyta trzy strumienie: zamówienia ze sklepu internetowego, wysyłki z magazynu, płatności z ERP. W pewien wtorek zespół ERP zmienia nazwę pola z customer_no na customer_id i jego typ. Producent działa dalej. Agent też działa dalej i przez cztery godziny przypisuje każdą płatność do nieznanego klienta, co raportuje jako zaległość. W żadnym logu nie ma informacji, że coś zawiodło.

Ten incydent jest powodem, dla którego Apache Avro istnieje w integracji enterprise. Avro jest formatem wierszowym i rozsądnym sposobem zwartej serializacji zdarzenia, ale jego zadanie w systemie zapisu jest inne: to miejsce, w którym umowa między dwoma systemami jest spisana, sprawdzana przez maszynę i zmieniana tylko przez kogoś, kto za nią odpowiada. Gdzie ta umowa leży między bazą operacyjną a lakehouse, pokazuje przewodnik serii.

Z czego składa się Avro

Dla architekta liczą się cztery części specyfikacji Avro; aktualne wydanie to 1.12.2 (sprawdzono 21.10.2026).

Schemat. Dokument JSON z typami prostymi (null, boolean, int, long, float, double, bytes, string) i złożonymi (record, enum, array, map, union, fixed). Pola mogą mieć wartość domyślną i dokumentację. Schemat jest tym, o co zespół się spiera, i tak powinno być.

Kodowanie binarne. Rekord jest zapisywany jako wartości pól w kolejności ze schematu, bez nazw pól i bez znaczników typów w danych. Dlatego rekordy Avro są małe i dlatego czytelnik musi mieć schemat, którego użył pisarz.

Plik kontenerowy. Dla danych w spoczynku własny plik Avro zaczyna się bajtami Obj i bajtem wersji, trzyma schemat w metadanych i zapisuje rekordy w blokach rozdzielonych 16-bajtowym znacznikiem synchronizacji, więc plik można dzielić i czytać równolegle. Kodeki null i deflate są wymagane przez specyfikację; snappy, zstandard, bzip2 i xz są opcjonalne.

Kodowanie pojedynczego obiektu. Dla jednego rekordu płynącego przez brokera komunikatów specyfikacja określa dwubajtowy marker, ośmiobajtowy odcisk schematu i dopiero dane, żeby czytelnik mógł schemat odnaleźć. Rejestr Confluent używa do tego samego celu własnej ramki: bajt magiczny, czterobajtowy identyfikator schematu, potem bajty Avro (dokumentacja).

Jak czytelnik przeżywa zmianę u pisarza

Częścią Avro, która zarabia na swoje miejsce, jest rozwiązywanie schematów: reguły, według których czytelnik z jednym schematem czyta dane zapisane innym. Pola dopasowuje się po nazwie. Pole, które pisarz zapisał, a czytelnik go nie zna, jest pomijane. Pole, którego czytelnik oczekuje, a pisarz go nie zapisał, przyjmuje wartość domyślną czytelnika; bez wartości domyślnej odczyt kończy się błędem. Dozwolona jest krótka lista promocji — int na long, long na float lub double, float na double, string i bytes w obie strony. Nieznany symbol wyliczenia wraca do wartości domyślnej czytelnika, jeśli została zadeklarowana.

Czytane przez pryzmat wtorkowego incydentu, reguły mówią dokładnie, co powinno się było stać. Zmiana nazwy customer_no na customer_id jest dla czytelnika zniknięciem jednego pola i pojawieniem się drugiego. Bez aliasu albo wartości domyślnej po stronie czytelnika to błąd, i błąd jest wynikiem poprawnym: głośnym, przy pierwszym komunikacie, w potoku wydania producenta, a nie w decyzji kredytowej cztery godziny później. Avro ma aliasy dla zmian nazw i wartości domyślne dla dodatków; zespół, który z nich korzysta, zamienia większość zmian w nie-zdarzenia, a pozostałe w widoczne decyzje.

Rejestr schematów czyni te reguły egzekwowalnymi. Każdy temat ma politykę zgodności — wstecz, w przód, pełną albo ich warianty przechodnie — i producent nie zarejestruje schematu, który ją narusza. Polityka należy do właściciela zdarzenia, którym zwykle jest zespół odpowiedzialny za opisywany system zapisu, a nie zespół, który akurat w tym kwartale pisze konsumenta.

Gdzie Avro się kończy

Avro słabo radzi sobie z pytaniami, dla których istnieje lakehouse. Raport z roku wysyłek, który potrzebuje trzech kolumn z trzydziestu, czyta każdy bajt każdego rekordu, bo układ wierszowy nie daje niczego do pominięcia. Cechy modeli, marża po kanałach i odsetki zwrotów należą do Parquet pod formatem tabeli, a rolą Avro jest dowieźć tam każde zdarzenie w całości. Zwykły wzorzec to procesor strumieni — Flink albo Spark — który czyta temat Avro i zapisuje tabele Parquet w Delta Lake, Apache Iceberg albo Apache Paimon z uzgodnionym opóźnieniem. Dlaczego oba formaty dzielą się pracą w ten sposób, wyjaśnia tekst Parquet czy Avro?.

Avro pojawia się też w miejscu, którego mało kto się spodziewa: Apache Iceberg zapisuje swoje manifesty — listy plików danych składających się na migawkę tabeli — w Avro właśnie dlatego, że czyta się je rekord po rekordzie i muszą przetrwać własne zmiany schematu.

Zmiana schematu w AI SDLC

Traktowanie integracji jak oprogramowania z cyklem życia zmienia to, kto co robi, gdy zmienia się pole. W projektach, które prowadzimy, kolejność jest stała, a większość pisania wykonują w niej agenci kodujący.

Infografika

Droga jednej zmiany schematu

  1. 01PropozycjaAgent przygotowuje nowy schemat ze zgłoszenia zmiany, z wartościami domyślnymi i aliasami, i wylicza każdego konsumenta znanego rejestrowi.
  2. 02Kontrola zgodnościRejestr ocenia schemat według polityki tematu; agent generuje i uruchamia testy rozwiązywania dla schematu każdego konsumenta.
  3. 03Zatwierdzenie właścicielaWłaściciel zdarzenia czyta różnicę i wyniki testów i podpisuje zmianę. Ten krok to osoba, nie etap potoku.
  4. 04ProducenciSystem produkujący jest wydany z nowym schematem; starzy konsumenci czytają dalej według reguł rozwiązywania.
  5. 05KonsumenciKażdy konsument przyjmuje nowe pole we własnym harmonogramie wydań; rejestr zapisuje, którą wersję który czyta.
Agenci przygotowują kroki pierwszy, drugi, czwarty i piąty. Krok trzeci jest umową.

Agenci są przydatni, bo ta praca jest mechaniczna i nużąca dla ludzi: wyliczanie konsumentów, pisanie testu schematu czytelnika na każdego konsumenta, generowanie kodu serializacji w trzech językach, utrzymywanie pola dokumentacji przy każdym atrybucie. Niebezpieczni są w jednym miejscu: agent poproszony o to, „żeby potok przeszedł”, chętnie poluzuje politykę zgodności albo doda pobłażliwą unię. Polityka rejestru i krok zatwierdzenia są więc konfiguracją, którą agenci mogą czytać, ale nie zmieniać.

Weźmy dystrybutora z trzema strumieniami z otwarcia. Po zmianie zdarzenie payment_posted z ERP ma w rejestrze wersję 7; agent kredytowy czyta wersję 5 z wartościami domyślnymi dla dwóch pól, których jeszcze nie używa; zadanie ładujące lakehouse czyta wersję 7. Nowe pole z kanałem płatności zostaje dodane w czwartek i dociera do raportu marży w kolejnym tygodniu, bez udziału weekendu. Liczby nie są sednem przykładu; sednem jest brak incydentu.

Jak wygląda dobry wynik

Każde zdarzenie, które przekracza granicę systemu, ma jeden schemat w jednym rejestrze, z właścicielem i polityką zgodności. Zmiany niezgodne padają w potoku producenta, a nie u konsumenta w nocy. Dodanie pola jest wydaniem, nie projektem. Lakehouse dostaje każde zdarzenie w całości, z zapisaną wersją schematu, więc na pytanie, co agent widział danego dnia, odpowiada się z danych, a nie z pamięci.

Nasza część

W inżynierii danych AI wprowadzamy umowy dla pierwszego istotnego przepływu: schematy Avro z wartościami domyślnymi i aliasami, rejestr i jego polityki, testy rozwiązywania generowane dla każdego konsumenta oraz lądowanie w otwartych formatach tabel. Nie odsprzedajemy platform. Więcej o predictes na stronie głównej.