Baseret på nyere praksis i produktionsmiljøer ved hjælp af SeaTunnel CDC (Change Data Capture) til synkronisering af scenarier som Oracle, MySQL og SQL Server, og kombineret med feedback fra en bred vifte af brugere, har jeg skrevet denne artikel for at hjælpe dig med at forstå den proces, som SeaTunnel implementerer CDC. Indholdet primært dækker de tre faser af CDC: Snapshot, Backfill og Incremental. De tre faser af CDC Den overordnede CDC data læsning proces kan opdeles i tre hovedfaser: Snapshot (Fuld belastning) Tilbagevendende Øget 1. snapshot fase Betydningen af Snapshot-fasen er meget intuitiv: Tag et snapshot af de aktuelle databasetabeldata og udfør en fuld tabelskanning via JDBC. Hvis man tager MySQL som et eksempel, registreres den aktuelle binlog-position under snapshot: SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB Executed_Gtid_Set binlog.000011 1001373553 Køge 0011 1001373553 SeaTunnel registrerer filen og placeringen som . low watermark Bemærk: Dette udføres ikke kun én gang, fordi SeaTunnel har implementeret sin egen split-cutting logik for at fremskynde snapshots. Bemærk: Dette udføres ikke kun én gang, fordi SeaTunnel har implementeret sin egen split-cutting logik for at fremskynde snapshots. MySQL snapshot splitter mekanisme (Split) Lad os antage, at den globale parallelisme er 10: SeaTunnel analyserer først alle tabeller og deres primære nøgle / unikke nøgleområder og vælger en passende splittet kolonne. Det er opdelt baseret på de maksimale og minimale værdier i denne kolonne, med en standard snapshot.split.size = 8096. Store tabeller kan skæres i hundredvis af splits, som er tildelt til 10 parallelle kanaler af nummeratoren i henhold til rækkefølgen af underopgaver anmodninger (tendens til en afbalanceret fordeling i det hele taget). Table-level sequential processing (schematic): // Processing sequence: // 1. Table1 -> Generate [Table1-Split0, Table1-Split1, Table1-Split2] // 2. Table2 -> Generate [Table2-Split0, Table2-Split1] // 3. Table3 -> Generate [Table3-Split0, Table3-Split1, Table3-Split2, Table3-Split3] Split-level parallel allocation: // Allocation to different subtasks: // Subtask 0: [Table1-Split0, Table2-Split1, Table3-Split2] // Subtask 1: [Table1-Split1, Table3-Split0, Table3-Split3] // Subtask 2: [Table1-Split2, Table2-Split0, Table3-Split1] Hver Split er faktisk en forespørgsel med en rækkebetingelse, for eksempel: SELECT * FROM user_orders WHERE order_id >= 1 AND order_id < 10001; Hver del registrerer separat sit eget lave vandmærke/høj vandmærke. Crucial: Gør ikke den for lille; at have for mange splits er ikke nødvendigvis hurtigere, og planlægningen og hukommelsen overhead vil være meget stor. Practical Advice: split_size 2. tilbagevirkende fase Forestil dig, at du laver et fuldt snapshot af en tabel, der ofte skrives til. Når du læser den 100. række, kan dataene i 1. række allerede være blevet ændret. Hvis du kun læser snapshot, de data, du holder, når du er færdig med at læse, er faktisk "inkonsistent" (del er gammel, del er ny). Why is Backfill needed? The role of Backfill is to compensate for the "data changes that occurred during the snapshot" so that the data is eventually consistent. Opførslen af denne fase afhænger hovedsageligt af konfigurationen af af parametre. exactly_once 2.1 Enkel måde ( ) exactly_once = false Dette er standardindstillingen; logikken er relativt enkel og direkte, og den kræver ikke hukommelsecaching: Direct Snapshot Emission: Læser snapshot data og sender det direkte nedstrøms uden at indtaste en cache. Direkte Log Emission: Læser Binlog på samme tid og sender det direkte nedstrøms. Eventuel konsistens: Selvom der vil være duplikater i midten (gammel A sendt først, så ny B), så længe downstream understøtter idempotent skriver (som MySQL's REPLACE INTO), det endelige resultat er konsistent. Det er ikke muligt at gøre det på en eller anden måde ( ) exactly_once = true Dette er den mest imponerende del af SeaTunnel CDC, og det er hemmeligheden til at garantere, at data er "aldrig tabt, aldrig gentaget." til afduplikation af. memory buffer (Buffer) Forestil dig, at læreren beder dig om at tælle, hvor mange mennesker der er i klassen lige nu (Snapshot-fase). Men eleverne i klassen er meget forvirrende; mens du tæller, løber folk ind og ud (dataændringer). Simple Explanation: SeaTunnel gør det sådan her: Tag et billede først (Snapshot): Tæl antallet af mennesker i klassen først og registrer det i en lille notesbog (hukommelsesbuffer); fortæl ikke hovedpersonen (downstream) endnu. Se overvågningen (Backfill): Hent overvågningsvideoen (Binlog log) for den periode, du tæller. Rettelse af optegnelser (merge): Hvis overvågningen viser, at nogen lige er kommet ind, men du ikke har talt dem -> tilføj dem. Hvis overvågningen viser, at nogen lige løb ud, men du tæller dem i -> kryds dem ud. Hvis overvågningen viser, at nogen har ændret deres tøj -> ændre rekord til det nye tøj. Indsend hjemmearbejde (Send): Efter korrektion er den lille notesbog i din hånd en perfekt nøjagtig liste; nu overgive den til hovedpersonen. betyder Summary for Beginners: exactly_once = true "hold it in and don't send it until it's clearly verified." Fordel: De data, der modtages nedadgående, er helt rene, uden duplikater eller uorden. Omkostninger: Fordi det skal "holdes i", skal det forbruge noget hukommelse til at gemme dataene. 2.3 To vigtige spørgsmål og svar Hvorfor er der ingen READ-begivenheder under Backfill-fasen? Q1: Why is case READ: throw Exception READ-begivenheden er defineret af SeaTunnel selv, specifikt for at repræsentere "lagerdata læst fra snapshot". Binlog kun registrerer "tilføjelser, sletninger og modifikationer" (INSERT/UPDATE/DELETE) og aldrig registrerer "nogen forespurgte et stykke data." Derfor, hvis du læser en READ-begivenhed under Backfill-fasen, betyder det, at kodens logik er forvirret. Q2: If it's placed in memory, can the memory hold it? Will it OOM? Det er ikke at sætte hele bordet i hukommelsen: SeaTunnel processer ved splitter. Splits er små: En standard split har kun 8096 rækker af data. Kast efter brug: Efter at have behandlet en splittelse, send den, rense hukommelsen og behandle den næste. Formel for hukommelsesbesættelse ≈ : Parallelisme × Split størrelse × Single row data størrelse. 2.4 Nøgle Detalje: Watermark Alignment mellem flere splitter Dette er et meget skjult, men yderst vigtigt spørgsmål. it will lead to data being either lost or repeated. Fast/Slow Runner Problem: Forestil dig, at to studerende (Split A og Split B) kopierer hjemmearbejde (Backfill data). Plain Language Explanation: Student A (hurtig): Kopieret til side 100 og afsluttet klokken 10:00. Studerende B (langsomt): Kopieret til side 200 og lige afsluttet ved 10:05. Nu skal læreren (Incremental task) fortsætte med at undervise en ny lektion (læse Binlog) fra hvor de sluttede med at kopiere. Hvis du starter fra side 200: Student B er tilsluttet, men indholdet Student A savnes mellem siderne 100 og 200 (hvilket skete mellem 10:00 og 10:05) er helt tabt. Hvis du starter fra side 100: Student A er tilsluttet, men Student B klager: "Lærer, jeg har allerede kopieret indholdet fra side 100 til 200!" SeaTunnels løsning: Start tidligt og dæk dine ører for det, du allerede har hørt: SeaTunnel vedtager en af strategi: "Minimum Watermark Starting Point + Dynamic Filtering" Bestem Start (pleje for den langsomme): Læreren beslutter at starte fra side 100 (det mindste vandmærke blandt alle splitterne). Dynamisk filtrering (hør ikke, hvad der er blevet hørt): Mens læreren forelægger (læser Binlog), holder de en liste: { A: 100, B: 200 }. Når læreren når side 150: Se på listen; er det for A? 150 > 100, A har ikke hørt det, optag det (send). Se på listen; er det for B? 150 < 200, B allerede kopieret det, hoppe det direkte (discard). Full Speed Mode (alle er færdige med at lytte): Når læreren når side 201 og finder ud af, at alle allerede har hørt det, har de ikke længere brug for listen. med : Den incrementelle fase filtrerer strengt efter kombinationen af "start offset + splittet rækkevidde + højt vandmærke." Summary in one sentence: exactly_once Uden Den incrementelle fase bliver en simpel "sekventiel forbrug fra en bestemt start offset." exactly_once Øgede stadier Efter afslutningen (for ) eller Snapshot fase slutter, det går ind i den rene incremental fase: exactly_once = true MySQL: Baseret på binlog. Oracle: Baseret på redo / logminer. SQL Server: Baseret på transaktionslog / LSN. PostgreSQL: Baseret på WAL. SeaTunnels adfærd i den incrementelle fase er meget tæt på den indfødte Debezium: Forbruger logs i offset rækkefølge. Opbygger begivenheder som INSERT/UPDATE/DELETE for hver ændring. Når exactly_once = true, er offset- og split-status inkluderet i kontrolpunktet for at opnå "exactly-once" semantik efter fejlgenopretning. 4. sammenfatning Den centrale designfilosofi hos SeaTunnel CDC er at finde den perfekte balance mellem og "Fast" (parallel snapshots) "Stable" (data consistency). Lad os gennemgå de vigtigste punkter i hele processen: Slicing (Split) er grundlaget for parallel acceleration: Skæring af store tabeller i små stykker for at lade flere tråde arbejde på samme tid. Snapshot er ansvarlig for at flytte lager: Brug af skiver til at læse historiske data parallelt. Backfill er ansvarlig for at sy hullerne: Dette er det mest kritiske skridt. Det kompenserer for ændringer under snapshot og eliminerer duplikater ved hjælp af hukommelsesfusion algoritmer for at opnå Exactly-Once. Incremental er ansvarlig for realtidssynkronisering: Sømløs forbindelse til Backfill-fasen og kontinuerlig forbrug af database logs. I denne trilogi af Den koordinerende rolle for Indenfor det er virkelig at mestre essensen af SeaTunnel CDC. "Snapshot -> Backfill -> Incremental" "Watermarks"