Change Data Capture (CDC) je technika používaná ke sledování změn na úrovni řádků v databázových operacích (vkládání, aktualizace, mazání) a oznamování ostatních systémů v pořadí událostí. Ve scénářích zotavení po havárii CDC primárně synchronizuje data mezi primární a záložní databází, což umožňuje synchronizaci dat z primární do sekundární databáze v reálném čase.
source ----------> CDC ----------> sink
SeaTunnel CDC nabízí dva typy synchronizace dat:
Fáze synchronizace snímků bez zámku je zdůrazněna, protože mnoho existujících platforem CDC, jako je Debezium, může během synchronizace historických dat uzamknout tabulky. Čtení snímků je proces synchronizace historických dat databáze. Základní průběh tohoto procesu je následující:
storage -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/
Dělené rozdělení
splitEnumerator
(rozdělovač rozdělení) rozděluje data tabulky do více částí na základě specifikovaných polí (jako je ID tabulky nebo jedinečné klíče) a definované velikosti kroku.
Paralelní zpracování
Každé rozdělení je přiřazeno jiné čtečce pro paralelní čtení. Jedna čtečka zabere jedno připojení.
Zpětná vazba k události
Po dokončení operace čtení pro rozdělení každý čtenář hlásí postup zpět do splitEnumerator
. Metadata pro rozdělení jsou poskytnuta následovně:
String splitId # Routing ID TableId tableId # Table ID SeatunnelRowType splitKeyType # The type of field used for partitioning Object splitStart # Start point of the partition Object splitEnd # End point of the partition
Jakmile čtenář obdrží informace o rozdělení, vygeneruje příslušné příkazy SQL. Před spuštěním zaprotokoluje odpovídající pozici aktuálního rozdělení do protokolu databáze. Po dokončení aktuálního rozdělení čtenář hlásí postup do splitEnumerator
s následujícími údaji:
String splitId # Split ID Offset highWatermark # Log position corresponding to the split, for future validation
Fáze přírůstkové synchronizace začíná po fázi čtení snímku. V této fázi jsou veškeré změny ve zdrojové databázi zachyceny a synchronizovány se záložní databází v reálném čase. Tato fáze poslouchá databázový protokol (např. MySQL binlog). Přírůstkové sledování je obvykle jednovláknové, aby se zabránilo duplicitnímu stahování binlogu a snížilo se zatížení databáze. Proto se používá pouze jedna čtečka, která zabírá jediné připojení.
data log -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/
Ve fázi přírůstkové synchronizace jsou všechna rozdělení a tabulky z fáze snímku spojena do jediného rozdělení. Rozdělení metadat během této fáze je následující:
String splitId Offset startingOffset # The lowest log start position among all splits Offset endingOffset # Log end position, or "continuous" if ongoing, eg, in the incremental phase List<TableId> tableIds Map<TableId, Offset> tableWatermarks # Watermark for all splits List<CompletedSnapshotSplitInfo> completedSnapshotSplitInfos # Snapshot phase split details
Pole CompletedSnapshotSplitInfo
jsou následující:
String splitId TableId tableId SeatunnelRowType splitKeyType Object splitStart Object splitEnd Offset watermark # Corresponds to the highWatermark in the report
Rozdělení v přírůstkové fázi obsahuje vodoznak pro všechna rozdělení ve fázi snímku. Minimální vodoznak je vybrán jako výchozí bod pro přírůstkovou synchronizaci.
Ať už ve fázi čtení snímku nebo přírůstkového čtení, databáze se může také změnit kvůli synchronizaci. Jak garantujeme právě jednu dodávku?
Ve fázi čtení snímku se například synchronizuje rozdělení, zatímco probíhají změny, jako je vložení řádku k3
, aktualizace k2
a vymazání k1
. Pokud se během procesu čtení nepoužije žádná identifikace úlohy, může dojít ke ztrátě aktualizací. SeaTunnel to řeší takto:
split{start, end}
.
Je-li high = low
, data pro rozdělení se během čtení nezměnila. Pokud (high - low) > 0
, došlo během zpracování ke změnám. V takovém případě SeaTunnel:
low watermark
na high watermark
v pořadí pomocí primárních klíčů k přehrání operací v tabulce v paměti.
insert k3 update k2 delete k1 | | | vvv bin log --|---------------------------------------------------|-- log offset low watermark high watermark CDC reads: k1 k3 k4 | Replays v Real data: k2 k3' k4
Před zahájením přírůstkové fáze SeaTunnel nejprve ověří všechna rozdělení z předchozího kroku. Mezi rozděleními mohou být data aktualizována, například pokud jsou mezi split1 a split2 vloženy nové záznamy, mohly by během fáze snímku chybět. K obnovení těchto dat mezi rozděleními se SeaTunnel řídí tímto přístupem:
completedSnapshotSplitInfos
, abyste zjistili, zda byla data zpracována v nějakém rozdělení. Pokud ne, považuje se to za data mezi rozděleními a mělo by být opraveno.
|------------filter split2-----------------| |----filter split1------| data log -|-----------------------|------------------|----------------------------------|- log offset min watermark split1 watermark split2 watermark max watermark
A co pozastavení a obnovení CDC? SeaTunnel používá algoritmus distribuovaných snímků (Chandy-Lamport):
Předpokládejme, že systém má dva procesy, p1
a p2
, kde p1
má tři proměnné X1 Y1 Z1
a p2
má tři proměnné X2 Y2 Z2
. Počáteční stavy jsou následující:
p1 p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3
V tomto okamžiku p1
zahájí globální snímek. p1
nejprve zaznamená svůj stav procesu a poté odešle značku na p2
.
Než značka dosáhne p2
, pošle p2
zprávu M
do p1
.
p1 p2 X1:0 -------marker-------> X2:4 Y1:0 <---------M---------- Y2:2 Z1:0 Z2:3
Po přijetí markeru zaznamená p2
svůj stav a p1
přijme zprávu M
. Protože p1
již provedl lokální snímek, potřebuje pouze zaprotokolovat zprávu M
. Konečný snímek vypadá takto:
p1 M p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3
V SeaTunnel CDC jsou značky odesílány všem čtenářům, děleným enumerátorům, zapisovačům a dalším uzlům, přičemž každý si zachovává svůj stav paměti.