Basado en las prácticas recientes en entornos de producción utilizando SeaTunnel CDC (Change Data Capture) para sincronizar escenarios como Oracle, MySQL y SQL Server, y combinado con los comentarios de una amplia gama de usuarios, he escrito este artículo para ayudarle a comprender el proceso por el que SeaTunnel implementa CDC. Las tres etapas del CDC El proceso general de lectura de datos del CDC se puede dividir en tres etapas principales: Snapshot (carga completa) retroalimentación Incremento 1 Etapa de Snapshot El significado de la etapa Snapshot es muy intuitivo: tome una imagen instantánea de los datos de la tabla de la base de datos actual y realice una exploración de la tabla completa a través de JDBC. Tomando MySQL como ejemplo, la posición binlog actual se registra durante el snapshot: SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB Executed_Gtid_Set binlog.000011 1001373553 Página 0011 1001373553 SeaTunnel registra el Archivo y la Ubicación como . low watermark Nota: Esto no se ejecuta una sola vez, porque SeaTunnel ha implementado su propia lógica de corte dividido para acelerar las capturas instantáneas. Nota: Esto no se ejecuta una sola vez, porque SeaTunnel ha implementado su propia lógica de corte dividido para acelerar las capturas instantáneas. Mecanismo de división de snapshot de MySQL (Split) Suponiendo que el paralelismo global es 10: SeaTunnel analizará primero todas las tablas y sus rangos de clave primaria/única y seleccionará una columna de división adecuada. Se divide en función de los valores máximos y mínimos de esta columna, con un estándar de snapshot.split.size = 8096. Las grandes tablas se pueden cortar en cientos de Splits, que son asignados a 10 canales paralelos por el enumerador de acuerdo con el orden de las solicitudes de subtask (tendiendo hacia una distribución equilibrada en general). 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] Cada Split es en realidad una consulta con una condición de rango, por ejemplo: SELECT * FROM user_orders WHERE order_id >= 1 AND order_id < 10001; Cada Split registra por separado su propia marca de agua baja / marca de agua alta. Crucial: No hagas el demasiado pequeño; tener demasiados Splits no es necesariamente más rápido, y la planificación y la memoria serán muy grandes. Practical Advice: split_size 2 Fase de retroalimentación Imagínese que está realizando una captura instantánea completa de una tabla a la que se está escribiendo con frecuencia.Cuando lee la línea 100, los datos en la primera fila pueden haber sido ya modificados.Si sólo lee la captura instantánea, los datos que mantiene cuando acaba de leer son realmente "inconsistentes" (parte es vieja, parte es nueva). 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. El comportamiento de esta etapa depende principalmente de la configuración de la Los parámetros. exactly_once 2.1 Modalidad simple ( ) exactly_once = false Este es el modo predeterminado; la lógica es relativamente simple y directa, y no requiere cache de memoria: Emisión instantánea directa: lee los datos instantáneos y los envía directamente hacia abajo sin introducir un caché. Emisión de registros directos: lee Binlog al mismo tiempo y lo envía directamente hacia abajo. Eventual Consistencia: Aunque habrá duplicados en el medio (antiguo A enviado primero, luego nuevo B), siempre que el downstream soporte los escritos idempotent (como el reemplazo INTO de MySQL), el resultado final es consistente. En el caso de las variables ( ) exactly_once = true Esta es la parte más impresionante de SeaTunnel CDC, y es el secreto para garantizar que los datos "nunca se pierden, nunca se repiten". para la deduplicación. memory buffer (Buffer) Imagínese que el maestro le pide que cuente cuántas personas están en la clase en este momento (etapa de snapshot). sin embargo, los estudiantes en la clase son muy malintencionados; mientras usted está contando, la gente está corriendo y saliendo (cambios de datos). Simple Explanation: SeaTunnel lo hace así: Tome una foto primero (Snapshot): Cuente el número de personas en la clase primero y grabe en un pequeño notebook (buffer de memoria); no diga al principal (downstream) todavía. Watch the Surveillance (Backfill): Recupere el vídeo de vigilancia (log de Binlog) para el período que estaba contando. Corregir los registros (Merge): Si la vigilancia muestra que alguien acaba de entrar, pero no los contó -> agregarlos. Si la vigilancia muestra a alguien que acaba de salir, pero los contó en -> cruzarlos. Si la vigilancia muestra que alguien cambió su ropa -> cambiar el registro a la nueva ropa. Submit Homework (Enviar): Después de la corrección, el pequeño cuaderno en tu mano es una lista perfectamente exacta; ahora entrega al principal. significa Summary for Beginners: exactly_once = true "hold it in and don't send it until it's clearly verified." Beneficio: Los datos recibidos a continuación son absolutamente limpios, sin duplicados ni desorden. Coste: Debido a que debe ser "tenido en", necesita consumir algo de memoria para almacenar los datos. 2.3 Preguntas y respuestas clave ¿Por qué no hay eventos READ durante la etapa de Backfill? Q1: Why is case READ: throw Exception El evento READ es definido por el propio SeaTunnel, específicamente para representar "datos de stock leídos de la imagen instantánea". La etapa Backfill lee el Binlog de la base de datos. Binlog solo registra "additions, deletions, and modifications" (INSERT/UPDATE/DELETE) y nunca registra "alguien consultó un pedazo de datos". Por lo tanto, si lee un evento READ durante la etapa de Backfill, significa que la lógica del código está confusa. Q2: If it's placed in memory, can the memory hold it? Will it OOM? No se trata de poner toda la mesa en la memoria: SeaTunnel procesa por partes. Las divisiones son pequeñas: una división predeterminada solo tiene 8096 líneas de datos. Desechar después del uso: Después de procesar una fracción, envíela, borrar la memoria y procesar la siguiente. Fórmula de ocupación de memoria ≈ : Paralelismo × tamaño dividido × tamaño de datos de una sola fila. 2.4 Detalle clave: Alineación de la marca de agua entre múltiples divisiones Este es un asunto muy oculto pero extremadamente importante.Si no se trata bien, it will lead to data being either lost or repeated. El problema de los corredores rápidos y lentos: Imagina que dos estudiantes (Split A y Split B) están copiando tareas domésticas (datos de repliegue). Plain Language Explanation: Estudiante A (rápido): copiado a la página 100 y terminado a las 10:00. Estudiante B (lento): copiado a la página 200 y acabado a las 10:05. Ahora, el profesor (trabajo incremental) necesita seguir enseñando una nueva lección (leer Binlog) desde donde terminaron de copiar. Si a partir de la página 200: Estudiante B está conectado, pero el contenido Estudiante A se pierde entre las páginas 100 y 200 (lo que ocurrió entre las 10:00 y las 10:05) se pierde completamente. Si a partir de la página 100: El estudiante A está conectado, pero el estudiante B se quejará: "Maestro, ya he copiado el contenido de la página 100 a 200!" Solución de SeaTunnel: Comienza desde el principio y cubre tus oídos por lo que ya has oído: SeaTunnel adopta una La estrategia: "Minimum Watermark Starting Point + Dynamic Filtering" Determinar el comienzo (cuidado para el lento): El maestro decide comenzar desde la página 100 (la marca de agua mínima entre todas las divisiones). Filtrado dinámico (no escuche lo que se ha escuchado): Mientras el profesor está dando conferencias (leer Binlog), ellos mantienen una lista: { A: 100, B: 200 }. Cuando el profesor llega a la página 150: Mira la lista; es para A? 150 > 100, A no lo ha oído, grabarlo (enviar). Mira la lista; es para B? 150 < 200, B ya lo copió, salta directamente (discard). Modo de velocidad completa (todo el mundo ha terminado de escuchar): Cuando el profesor llega a la página 201 y encuentra que todo el mundo ya lo ha oído, ya no necesitan la lista. con : La fase incremental filtra estrictamente de acuerdo con la combinación de "comienzo offset + rango dividido + marca de agua alta". Summary in one sentence: exactly_once sin La etapa incremental se convierte en un simple "consumo secuencial de un determinado offset inicial". exactly_once 3 Fase incremental Después de la recogida (por ) o final de la fase de Snapshot, entra en la fase incremental pura: exactly_once = true MySQL: Basado en binlog. Oracle: Basado en redo/logminer. SQL Server: Basado en el registro de transacciones / LSN. PostgreSQL: Basado en WAL. El comportamiento de SeaTunnel en la etapa incremental es muy cercano a Debezium nativo: Consume los logs en orden offset. Construye eventos como INSERT/UPDATE/DELETE para cada cambio. Cuando exact_once = true, el estado de descomposición y división se incluye en el punto de control para lograr la semántica "exactamente una vez" después de la recuperación de fallos. 4 Resumen La filosofía de diseño central de SeaTunnel CDC es encontrar el equilibrio perfecto entre y "Fast" (parallel snapshots) "Stable" (data consistency). Revisemos los puntos clave de todo el proceso: Slicing (Split) es la base de la aceleración paralela: cortar tablas grandes en piezas pequeñas para permitir que múltiples hilos funcionen al mismo tiempo. Snapshot es responsable de mover el stock: Utilizar fatias para leer los datos históricos en paralelo. Backfill es responsable de coser las lagunas: Este es el paso más crítico. Compensa los cambios durante la captura instantánea y elimina duplicados utilizando algoritmos de fusión de memoria para lograr Exactly-Once. Incremental es responsable de la sincronización en tiempo real: se conecta sin problemas a la etapa de Backfill y consume continuamente los registros de bases de datos. Con esta trilogía de El papel coordinador de dentro de ella es realmente dominar la esencia de SeaTunnel CDC. "Snapshot -> Backfill -> Incremental" "Watermarks"