Utilisez le connecteur SQL Kafka en tant que table source ou table de destination dans Realtime Compute for Apache Flink.
Présentation
Apache Kafka est une plateforme open source distribuée de streaming d'événements, largement utilisée pour le traitement de données haute performance, l'analytique en continu et l'intégration de données. Le connecteur Kafka pour Realtime Compute for Apache Flink s'appuie sur le client Apache Kafka open source pour offrir un débit de données élevé, prendre en charge la lecture et l'écriture de plusieurs formats de données, et garantir la sémantique exactly-once.
|
Catégorie |
Description |
|
Types pris en charge |
Source SQL, destination Source Flink CDC, destination Source DataStream, destination |
|
Mode d'exécution |
Streaming |
|
Formats de données |
|
|
Métriques |
|
|
Types d'API |
SQL, DataStream, Flink CDC |
|
Mise à jour/suppression dans la destination |
Le connecteur prend uniquement en charge l'ajout de données à une table de destination. Les mises à jour et les suppressions ne sont pas prises en charge. Remarque
Pour savoir comment mettre à jour ou supprimer des données dans une table de destination, consultez Upsert Kafka. |
Prérequis
Avant de commencer, vérifiez que vous remplissez les prérequis correspondant au type de votre cluster Kafka :
-
Connexion à un cluster ApsaraMQ for Kafka
La version du cluster Kafka doit être 0,11 ou ultérieure.
Vous avez créé un cluster ApsaraMQ for Kafka. Pour plus d'informations, consultez Étape 3 : Créer des ressources.
L'espace de travail Flink et le cluster Kafka doivent se trouver dans le même Virtual Private Cloud (VPC), et vous devez avoir ajouté le bloc CIDR de l'espace de travail Flink à la liste d'autorisation ApsaraMQ for Kafka. Pour plus d'informations, consultez Configurer les listes d'autorisation.
ImportantLimitations liées à l'écriture de données dans ApsaraMQ for Kafka :
ApsaraMQ for Kafka ne prend pas en charge le format de compression Zstandard (zstd) pour les écritures.
ApsaraMQ for Kafka ne prend pas en charge les écritures idempotentes ou transactionnelles, ce qui empêche d'utiliser la sémantique exactly-once fournie par les tables de destination Kafka. À partir de Ververica Runtime (VVR) 8.0.0, le connecteur Kafka utilise le client Kafka 3.x, où la propriété
properties.enable.idempotencea par défaut la valeurtrue. Par conséquent, pour éviter les échecs d'écriture lors de l'utilisation de Ververica Runtime (VVR) 8.0.0 ou ultérieur pour écrire dans ApsaraMQ for Kafka, vous devez ajouter la configuration properties.enable.idempotence=false à la définition de votre table de destination. Pour une comparaison des moteurs de stockage et des limitations fonctionnelles d'ApsaraMQ for Kafka, consultez Comparaison des moteurs de stockage.
-
Connexion à un cluster Apache Kafka autogéré
La version du cluster Apache Kafka autogéré doit être 0,11 ou ultérieure.
L'espace de travail Flink doit disposer d'une connectivité réseau avec le cluster Apache Kafka autogéré. Pour obtenir des détails sur la connexion à un cluster via Internet public, consultez FAQ sur la connectivité réseau.
Seules les options de configuration client pour Apache Kafka version 2.8 sont prises en charge. Pour plus d'informations, consultez la documentation Apache Kafka relative aux configurations du consommateur et aux configurations du producteur.
Remarques
Les écritures transactionnelles ne sont pas recommandées en raison de limitations de conception connues dans Apache Flink et Apache Kafka. Lorsque vous définissez sink.delivery-guarantee = 'exactly-once', le connecteur Kafka active les écritures transactionnelles, avec les problèmes connus suivants :
Chaque point de contrôle génère un nouvel ID de transaction. Si l'intervalle entre les points de contrôle est trop court, le nombre élevé d'ID de transaction peut saturer la mémoire du coordinateur du cluster Kafka, compromettant ainsi la stabilité du cluster.
Chaque transaction crée une nouvelle instance de producteur. Si trop de transactions sont validées simultanément, le TaskManager peut manquer de mémoire, déstabilisant ainsi la tâche Apache Flink.
Si plusieurs tâches Apache Flink utilisent le même préfixe
sink.transactional-id-prefix, les ID de transaction générés peuvent entrer en conflit. Lorsqu'une opération d'écriture échoue dans une tâche, cela peut empêcher l'avancement du Log Start Offset (LSO) d'une partition Apache Kafka. Cela affecte tous les consommateurs de cette partition.
Si vous avez besoin de la sémantique exactly-once, utilisez le connecteur Upsert Kafka pour écrire dans une table avec clé primaire, garantissant ainsi l'idempotence. Si vous devez utiliser des écritures transactionnelles, consultez les remarques d'utilisation de la sémantique exactly-once.
Dépannage de la connectivité réseau
Une erreur Timed out waiting for a node assignment lors du démarrage d'une tâche Realtime Compute for Apache Flink indique généralement un problème de connectivité réseau entre Realtime Compute for Apache Flink et le cluster Kafka.
Un client Kafka se connecte aux brokers comme suit :
Le client utilise les adresses spécifiées dans
bootstrap.serverspour établir une connexion initiale au cluster Kafka.Le cluster Kafka renvoie les métadonnées de chaque broker, y compris leurs endpoints.
Le client utilise ensuite ces endpoints pour se connecter aux brokers afin de lire ou d'écrire des données.
Même si les adresses bootstrap.servers sont accessibles, le client ne peut ni lire ni écrire de données si Kafka renvoie des endpoints de broker incorrects. Ce problème survient souvent dans les architectures réseau utilisant un proxy, une redirection de port ou une ligne louée.
Étapes de dépannage
ApsaraMQ for Kafka
-
Confirmez le type d'endpoint
Endpoint par défaut (réseau interne)
Endpoint SASL (réseau interne avec authentification)
Endpoint public (nécessite une demande distincte)
Utilisez la fonctionnalité Network Probe dans la console de développement Realtime Compute for Apache Flink pour écarter les problèmes de connectivité avec l'adresse
bootstrap.servers. -
Vérifiez les groupes de sécurité et les listes d'autorisation
Ajoutez le bloc CIDR de l'espace de travail Realtime Compute for Apache Flink à la liste d'autorisation de votre instance Kafka. Pour plus d'informations, consultez Afficher le bloc CIDR du VPC et Configurer une liste d'autorisation.
-
Vérifiez la configuration SASL (si activée)
Si vous utilisez un endpoint SASL_SSL, assurez-vous que les mécanismes JAAS, SSL et SASL sont correctement configurés dans votre tâche Realtime Compute for Apache Flink. Sans une authentification appropriée, la connexion peut échouer pendant la phase de handshake, ce qui peut également se manifester par un délai d'attente. Pour plus d'informations, consultez la section Sécurité et authentification.
Self-managed Kafka
-
Utilisez la fonctionnalité Network Probe
Cette fonctionnalité vous aide à écarter les problèmes de connectivité avec l'adresse
bootstrap.serverset à vérifier que l'endpoint interne ou public correct est utilisé. -
Vérifiez les groupes de sécurité et les listes d'autorisation
Le groupe de sécurité de l'instance Elastic Compute Service (ECS) doit autoriser le trafic entrant sur le port de l'endpoint Kafka, généralement 9092 ou 9093.
Assurez-vous que tout pare-feu sur l'instance ECS autorise le trafic provenant du VPC de votre espace de travail Realtime Compute for Apache Flink. Pour plus d'informations, consultez Afficher le bloc CIDR du VPC.
-
Vérifiez la configuration
Utilisez l'outil zkCli.sh ou zookeeper-shell.sh pour vous connecter au cluster ZooKeeper utilisé par Kafka.
-
Exécutez une commande pour obtenir les métadonnées du broker. Par exemple, exécutez
get /brokers/ids/0. Dans le champ endpoints de la réponse, repérez l'adresse que Kafka annonce aux clients.# bin/zookeeper-shell.sh localhost:2181 Connecting to localhost:2181 Welcome to ZooKeeper! JLine support is disabled WATCHER:: WatchedEvent state:SyncConnected type:None path:null get /brokers/ids/0 {"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://116.62.xxx:9092"],"jmx_port":-1,"host":"116.62.xxx","timestamp":"1614840078030","port":9092,"version":4} -
Utilisez la fonctionnalité Network Probe dans la console de développement Realtime Compute for Apache Flink pour tester l'accessibilité de cette adresse.
RemarqueSi l'adresse n'est pas accessible, contactez vos administrateurs Kafka pour vérifier et corriger les configurations
listenersetadvertised.listenersafin de garantir que l'adresse annoncée est accessible depuis Realtime Compute for Apache Flink.Pour plus d'informations sur les connexions des clients Kafka, consultez Dépannage de la connectivité.
-
Vérifiez la configuration SASL (si activée)
Si vous utilisez un endpoint SASL_SSL, assurez-vous que les mécanismes JAAS, SSL et SASL sont correctement configurés dans votre tâche Realtime Compute for Apache Flink. Sans une authentification appropriée, la connexion peut échouer pendant la phase de handshake, ce qui peut également se manifester par un délai d'attente. Pour plus d'informations, consultez la section Sécurité et authentification.
SQL
Utilisez le connecteur Kafka en tant que table source ou table de destination dans les tâches SQL.
Syntaxe
CREATE TABLE KafkaTable (
`user_id` BIGINT,
`item_id` BIGINT,
`behavior` STRING,
`ts` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp' VIRTUAL
) WITH (
'connector' = 'kafka',
'topic' = 'user_behavior',
'properties.bootstrap.servers' = 'localhost:9092',
'properties.group.id' = 'testGroup',
'scan.startup.mode' = 'earliest-offset',
'format' = 'csv'
)
Colonnes de métadonnées
Définissez des colonnes de métadonnées dans une table source ou de destination pour accéder aux métadonnées des messages Kafka. Par exemple, lorsque vous vous abonnez à plusieurs topics, une colonne de métadonnées peut identifier le topic d'origine de chaque enregistrement.
CREATE TABLE kafka_source (
-- Read the message topic as the `record_topic` column
`record_topic` STRING NOT NULL METADATA FROM 'topic' VIRTUAL,
-- Read the timestamp from the ConsumerRecord as the `ts` column
`ts` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp' VIRTUAL,
-- Read the message offset as the `record_offset` column
`record_offset` BIGINT NOT NULL METADATA FROM 'offset' VIRTUAL,
...
) WITH (
'connector' = 'kafka',
...
);
CREATE TABLE kafka_sink (
-- Write the timestamp from the `ts` column as the ProducerRecord's timestamp to Kafka
`ts` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp' VIRTUAL,
...
) WITH (
'connector' = 'kafka',
...
);
Le tableau suivant répertorie les colonnes de métadonnées prises en charge par les tables source et sink Kafka.
|
Key |
Type |
Description |
Scope |
|
topic |
STRING NOT NULL METADATA VIRTUAL |
Sujet du message. |
Table source |
|
partition |
INT NOT NULL METADATA VIRTUAL |
ID de partition du message. |
Table source |
|
headers |
MAP<STRING, BYTES> NOT NULL METADATA VIRTUAL |
En-têtes du message. |
Table source et table sink |
|
leader-epoch |
INT NOT NULL METADATA VIRTUAL |
Époque du leader du message. |
Table source |
|
offset |
BIGINT NOT NULL METADATA VIRTUAL |
Décalage (offset) du message. |
Table source |
|
timestamp |
TIMESTAMP(3) WITH LOCAL TIME ZONE NOT NULL METADATA VIRTUAL |
Horodatage du message. |
Table source et table sink |
|
timestamp-type |
STRING NOT NULL METADATA VIRTUAL |
Type d'horodatage du message. Les valeurs valides sont :
|
Table source |
|
__raw_key__ |
STRING NOT NULL METADATA VIRTUAL |
Clé brute du message. |
Table source et table sink Remarque
Ce paramètre est pris en charge uniquement dans Ververica Runtime (VVR) 11.4 et versions ultérieures. |
|
__raw_value__ |
STRING NOT NULL METADATA VIRTUAL |
Valeur brute du message. |
Table source et table sink Remarque
Ce paramètre est pris en charge uniquement dans Ververica Runtime (VVR) 11.4 et versions ultérieures. |
Options du connecteur
-
Général
Option
Description
Type
Required
Default
Remarks
connector
Type de connecteur.
String
Yes
–
La valeur doit être
kafka.properties.bootstrap.servers
Liste des adresses des brokers Kafka.
String
Yes
–
Format :
host1:port1,host2:port2,.... Séparez les adresses par des virgules (,).properties.*
Propriétés supplémentaires pour le client Kafka.
String
No
–
Les clés de propriété doivent correspondre aux options valides définies dans la documentation officielle d'Apache Kafka pour les configurations du producteur et les configurations du consommateur.
Realtime Compute for Apache Flink supprime le préfixe properties. et transmet les paires clé-valeur restantes au client Kafka sous-jacent. Par exemple, vous pouvez définir
'properties.allow.auto.create.topics' = 'false'pour désactiver la création automatique de topics.Le connecteur Kafka écrase ces options ; vous ne pouvez donc pas les configurer de cette manière :
-
key.deserializer
-
value.deserializer
format
Format de sérialisation et de désérialisation de la valeur d'un message Kafka.
String
No
–
Formats pris en charge :
-
csv
-
json
-
avro
-
debezium-json
-
canal-json
-
maxwell-json
-
avro-confluent
-
raw
RemarquePour plus d'informations, consultez les options de format.
key.format
Format de sérialisation et de désérialisation de la clé d'un message Kafka.
String
No
–
Formats pris en charge :
-
csv
-
json
-
avro
-
debezium-json
-
canal-json
-
maxwell-json
-
avro-confluent
-
raw
RemarqueLorsque vous utilisez cette configuration, key.options est obligatoire.
key.fields
Champs du schéma de table à utiliser comme clé de message Kafka.
String
No
–
Séparez plusieurs noms de champs par des points-virgules (;). Par exemple,
'field1;field2'.key.fields-prefix
Préfixe personnalisé pour tous les champs de clé afin d'éviter les conflits de nom avec les champs de valeur.
String
No
–
Ce préfixe permet de distinguer les champs de clé des champs de valeur. Il est supprimé avant la sérialisation de la clé ou après sa désérialisation.
RemarqueSi vous utilisez cette option,
value.fields-includedoit être défini surEXCEPT_KEY.value.format
Format de sérialisation et de désérialisation de la valeur d'un message Kafka.
String
No
–
Cette configuration équivaut à
format. Vous ne pouvez définir que l'une des optionsformatouvalue.format. Si les deux sont configurées,value.formatremplaceformat.value.fields-include
Indique si les champs de clé sont inclus dans le format de valeur.
String
No
ALL
Valeurs valides :
-
ALL: la valeur du message Kafka inclut toutes les colonnes de la table. -
EXCEPT_KEY: la valeur du message Kafka inclut toutes les colonnes de la table, à l'exception de celles définies danskey.fields.
-
-
Table source
Option
Description
Type
Required
Default
Remarks
topic
Topic ou topics à lire.
String
No
–
Pour s'abonner à plusieurs topics, séparez leurs noms par des points-virgules (;), par exemple
'topic-1;topic-2'.RemarqueVous pouvez spécifier cette option ou
topic-pattern, mais pas les deux simultanément.topic-pattern
Expression régulière correspondant aux topics auxquels s'abonner. Le consommateur s'abonne à tous les topics dont les noms correspondent à ce modèle.
String
No
–
Exemples :
-
user_event_.*: correspond à tous les topics préfixés paruser_event_. -
prod\.logs\..*: correspond aux topics préfixés parprod.logs.(le caractère.doit être échappé).
RemarqueVous pouvez spécifier cette option ou
topic, mais pas les deux simultanément.properties.group.id
ID du groupe de consommateurs source Kafka.
String
No
KafkaSource-{Source-Table-Name}
Si vous utilisez un ID de groupe de consommateurs pour la première fois, vous devez également définir properties.auto.offset.reset sur
earliestoulatestafin de définir le décalage de démarrage initial.scan.startup.mode
Décalage de démarrage du consommateur Kafka.
String
No
group-offsets
Valeurs valides :
-
earliest-offset: commence la lecture à partir du décalage disponible le plus ancien. -
latest-offset: commence la lecture à partir du dernier décalage. -
group-offsets: commence la lecture à partir des décalages validés du properties.group.id spécifié. -
timestamp: commence la lecture à partir du scan.startup.timestamp-millis spécifié. -
specific-offsets: commence la lecture à partir des décalages spécifiés dans scan.startup.specific-offsets.
RemarqueCette option s'applique uniquement lorsqu'un travail démarre sans état. Si un travail reprend à partir d'un point de contrôle, il lit à partir des décalages stockés dans l'état du point de contrôle.
scan.startup.specific-offsets
Décalage de démarrage par partition lorsque
scan.startup.modeest défini surspecific-offsets.String
No
–
Par exemple,
partition:0,offset:42;partition:1,offset:300scan.startup.timestamp-millis
Horodatage de démarrage en millisecondes lorsque
scan.startup.modeest défini surtimestamp.Long
No
–
L'unité est la milliseconde.
scan.topic-partition-discovery.interval
Intervalle de découverte des partitions.
Duration
No
5 minutes
Le connecteur découvre et lit périodiquement les nouvelles partitions. Lorsque vous utilisez topic-pattern, le connecteur découvre également les nouveaux topics correspondant au modèle. Définissez l'intervalle sur une valeur non positive pour désactiver cette fonctionnalité.
RemarqueDans Ververica Runtime (VVR) 6,0.x, la découverte dynamique des partitions est désactivée par défaut. À partir de VVR 8.0, cette fonctionnalité est activée par défaut avec un intervalle de découverte de 5 minutes.
scan.header-filter
Filtre les messages en fonction des en-têtes de message Kafka.
String
No
–
Une clé d'en-tête et sa valeur sont séparées par deux-points (:). Plusieurs conditions d'en-tête sont reliées à l'aide d'opérateurs logiques (& et |). L'opérateur logique NON (!) est également pris en charge. Par exemple,
depart:toy|depart:book&!env:testconserve les données Kafka si l'en-tête contientdepart=toyoudepart=booket ne contient pasenv=test.Remarque-
Cette option est prise en charge uniquement dans Ververica Runtime (VVR) 8.0.6 et versions ultérieures.
-
Les parenthèses dans les expressions ne sont pas prises en charge.
-
Les opérations logiques sont évaluées de gauche à droite.
-
Les valeurs d'en-tête sont converties en chaînes UTF-8 pour la comparaison.
scan.check.duplicated.group.id
Vérifie si un autre consommateur actif utilise déjà le
properties.group.id.Boolean
No
false
Valeurs valides :
-
true : avant de démarrer le travail, le système vérifie l'existence d'un groupe de consommateurs dupliqué. Si un tel groupe est trouvé, le travail échoue pour éviter les conflits.
-
false : démarre le travail sans vérifier les conflits.
RemarqueCette option est prise en charge uniquement dans Ververica Runtime (VVR) 6.0.4 et versions ultérieures.
-
-
Table sink
Option
Description
Type
Required
Default
Remarks
topic
Topic cible.
String
Yes
–
–
sink.partitioner
Mappe les enregistrements des instances de sink parallèles vers les partitions Kafka.
String
No
default
Valeurs valides :
-
default: utilise le partitionneur Kafka par défaut. -
fixed: chaque instance de sink parallèle écrit dans une partition Kafka fixe. -
round-robin: les enregistrements sont distribués aux partitions selon un algorithme tournant. -
Partitionneur personnalisé : pour utiliser un partitionneur personnalisé, indiquez le nom de classe qualifié complet d'une sous-classe
FlinkKafkaPartitioner, par exempleorg.mycompany.MyPartitioner.
sink.delivery-guarantee
Garantie de livraison du sink.
String
No
at-least-once
Valeurs valides :
-
none: aucune garantie n'est fournie. Les enregistrements peuvent être perdus ou dupliqués. -
at-least-once: garantit qu'aucun enregistrement n'est perdu, mais ils peuvent être dupliqués. -
exactly-once: utilise les transactions Kafka pour fournir une sémantique exactly-once, garantissant que les enregistrements ne sont ni perdus ni dupliqués.
RemarqueLorsque vous utilisez la sémantique
exactly-once, vous devez également spécifier sink.transactional-id-prefix.sink.transactional-id-prefix
Préfixe d'ID de transaction. Obligatoire lorsque
sink.delivery-guaranteeest défini surexactly-once.String
Yes, if
sink.delivery-guaranteeisexactly-once–
Requis uniquement lorsque sink.delivery-guarantee est défini sur
exactly-once.sink.parallelism
Parallélisme de l'opérateur de sink.
Integer
No
–
Par défaut, le framework détermine le parallélisme en fonction des opérateurs en amont.
-
Sécurité et authentification
Si le cluster Kafka nécessite une connexion sécurisée ou une authentification, préfixez les configurations de sécurité et d'authentification pertinentes par properties. et définissez-les dans le paramètre WITH. L'exemple suivant configure une table Kafka pour utiliser PLAIN comme mécanisme SASL avec une configuration JAAS.
CREATE TABLE KafkaTable (
`user_id` BIGINT,
`item_id` BIGINT,
`behavior` STRING,
`ts` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp'
) WITH (
'connector' = 'kafka',
...
'properties.security.protocol' = 'SASL_PLAINTEXT',
'properties.sasl.mechanism' = 'PLAIN',
'properties.sasl.jaas.config' = 'org.apache.flink.kafka.shaded.org.apache.kafka.common.security.plain.PlainLoginModule required username="username" password="password";'
)
L'exemple suivant montre comment utiliser SASL_SSL comme protocole de sécurité et SCRAM-SHA-256 comme mécanisme SASL.
CREATE TABLE KafkaTable (
`user_id` BIGINT,
`item_id` BIGINT,
`behavior` STRING,
`ts` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp'
) WITH (
'connector' = 'kafka',
...
'properties.security.protocol' = 'SASL_SSL',
/* SSL configuration */
/* Path to the truststore for the server's CA certificate. */
/* Files uploaded using Artifacts are stored in the /flink/usrlib/ directory. */
'properties.ssl.truststore.location' = '/flink/usrlib/kafka.client.truststore.jks',
'properties.ssl.truststore.password' = 'test1234',
/* If client authentication is required, you must also configure the path to the keystore (private key). */
'properties.ssl.keystore.location' = '/flink/usrlib/kafka.client.keystore.jks',
'properties.ssl.keystore.password' = 'test1234',
/* The algorithm used to verify the server hostname. An empty string disables hostname verification. */
'properties.ssl.endpoint.identification.algorithm' = '',
/* SASL configuration */
/* Set the SASL mechanism to SCRAM-SHA-256. */
'properties.sasl.mechanism' = 'SCRAM-SHA-256',
/* Configure JAAS. */
'properties.sasl.jaas.config' = 'org.apache.flink.kafka.shaded.org.apache.kafka.common.security.scram.ScramLoginModule required username="username" password="password";'
)
Vous pouvez utiliser la fonctionnalité Artifacts de la console Realtime Compute for Apache Flink pour télécharger le certificat CA et la clé privée mentionnés dans l'exemple. Les fichiers téléchargés sont stockés dans le répertoire /flink/usrlib. Pour utiliser un fichier de certificat CA nommé my-truststore.jks, vous pouvez définir la propriété 'properties.ssl.truststore.location' dans la clause WITH de l'une des deux manières suivantes :
Définissez
'properties.ssl.truststore.location' = '/flink/usrlib/my-truststore.jks'. Cette méthode évite de télécharger dynamiquement des fichiers depuis Object Storage Service (OSS) au moment de l'exécution, mais elle ne prend pas en charge le mode Debug.Si la version du moteur Realtime Compute est VVR 11.5 ou ultérieure, vous pouvez configurer
properties.ssl.truststore.locationetproperties.ssl.keystore.locationavec un chemin OSS absolu. Le format du chemin de fichier est oss://flink-fullymanaged-<Workspace ID>/artifacts/namespaces/<Namespace name>/<file name>. Cette méthode télécharge dynamiquement les fichiers OSS lors de l'exécution de Flink et prend en charge le mode Debug.
Vérifiez votre configuration : Les exemples de cette rubrique présentent des configurations courantes. Avant de configurer le connecteur Kafka, contactez votre équipe d'exploitation et de maintenance Kafka pour obtenir les paramètres de sécurité et d'authentification corrects.
Échappement : Contrairement à Apache Flink natif, l'éditeur SQL de Realtime Compute for Apache Flink échappe par défaut les guillemets doubles ("). Par conséquent, vous n'avez pas besoin d'ajouter des barres obliques inverses (\) pour échapper les guillemets doubles utilisés pour le nom d'utilisateur et le mot de passe dans l'option
properties.sasl.jaas.config.Identifiants d'hôte dans KMS : Vous pouvez définir le nom d'utilisateur et le mot de passe dans
properties.sasl.jaas.configsursecret://kms.<secret-name>.<key>pour référencer un identifiant géré par KMS au lieu d'utiliser du texte brut. Cette fonctionnalité est prise en charge dans Realtime Compute engine VVR 11.9 et versions ultérieures. Pour la procédure de configuration, consultez Intégration de la gestion des identifiants KMS.
Offset de démarrage de la table source
Mode de démarrage
Vous pouvez configurer l'option scan.startup.mode pour spécifier l'offset à partir duquel une table source Kafka commence à lire les données. Les valeurs valides incluent :
earliest-offset : Commence la lecture à partir du premier offset.
latest-offset : Commence la lecture à partir du dernier offset.
group-offsets : Commence la lecture à partir des offsets validés pour le groupe de consommateurs spécifié dans properties.group.id.
timestamp : Commence la lecture à partir du premier message dont l'horodatage est supérieur ou égal à la valeur spécifiée dans scan.startup.timestamp-millis.
specific-offsets : Commence la lecture à partir des offsets de partition spécifiques indiqués dans scan.startup.specific-offsets.
Si vous ne spécifiez pas de mode de démarrage, la valeur par défaut est 'group-offsets'.
L'option scan.startup.mode s'applique uniquement aux jobs sans état. Lorsqu'un job avec état démarre, il consomme toujours à partir des offsets stockés dans son état.
Exemple :
CREATE TEMPORARY TABLE kafka_source (
...
) WITH (
'connector' = 'kafka',
...
-- Consume from the earliest offset.
'scan.startup.mode' = 'earliest-offset',
-- Consume from the latest offset.
'scan.startup.mode' = 'latest-offset',
-- Consume from the committed offsets of the consumer group "my-group".
'properties.group.id' = 'my-group',
'scan.startup.mode' = 'group-offsets',
'properties.auto.offset.reset' = 'earliest', -- If "my-group" is used for the first time, consumption starts from the earliest offset.
'properties.auto.offset.reset' = 'latest', -- If "my-group" is used for the first time, consumption starts from the latest offset.
-- Consume from the specified timestamp in milliseconds: 1655395200000.
'scan.startup.mode' = 'timestamp',
'scan.startup.timestamp-millis' = '1655395200000',
-- Consume from specific offsets.
'scan.startup.mode' = 'specific-offsets',
'scan.startup.specific-offsets' = 'partition:0,offset:42;partition:1,offset:300'
);
Priorité de l'offset de démarrage
L'offset de démarrage de la table source est déterminé par les règles suivantes, par ordre de priorité :
|
Priorité (de la plus élevée à la plus faible) |
L'offset stocké dans un point de contrôle (checkpoint) ou un point de sauvegarde (savepoint). |
|
L'heure de démarrage sélectionnée dans la console Realtime Compute for Apache Flink lors du lancement du job. |
|
|
L'offset de démarrage spécifié par scan.startup.mode dans la clause WITH. |
|
|
Si scan.startup.mode n'est pas spécifié, group-offsets est utilisé pour démarrer la consommation à partir des offsets du groupe de consommateurs correspondant. |
Si l'offset déterminé par l'une de ces étapes est invalide, par exemple parce qu'il a expiré ou qu'un problème est survenu dans le cluster Kafka, le système réinitialise l'offset selon la politique spécifiée dans properties.auto.offset.reset. Si cette option n'est pas configurée, le système lève une exception qui nécessite une intervention de l'utilisateur.
Un scénario courant consiste à démarrer la consommation avec un nouvel ID de groupe de consommateurs. La table source interroge d'abord le cluster Kafka pour obtenir les offsets validés de ce groupe. Comme l'ID de groupe est nouveau, aucun offset valide n'est trouvé. Par conséquent, le système réinitialise l'offset selon la politique spécifiée dans properties.auto.offset.reset. Ainsi, lors de la consommation avec un nouvel ID de groupe, vous devez configurer l'option properties.auto.offset.reset.
Validation des offsets source
La table source Kafka valide son offset de consommateur auprès du cluster Kafka uniquement après un point de contrôle (checkpoint) réussi ; ainsi, un intervalle de checkpoint long entraîne un décalage de l'offset validé. La table source stocke la progression réelle de la lecture dans l'état du checkpoint, que le système utilise pour la récupération après incident. Les offsets validés servent uniquement de moniteur de progression et ne sont pas utilisés pour la récupération ; par conséquent, les échecs de validation n'affectent pas l'exactitude des données.
Partitionneur de sink personnalisé
Si la stratégie de partitionnement intégrée de Kafka ne répond pas à vos besoins, vous pouvez implémenter un partitionneur personnalisé en étendant la classe FlinkKafkaPartitioner. Une fois le développement terminé, compilez votre code dans un package JAR et téléchargez-le à l'aide de la fonctionnalité Artifacts dans la console Realtime Compute. Après le téléchargement et la référence du package JAR, définissez le paramètre sink.partitioner dans la clause WITH avec le nom de classe complet de votre partitionneur, par exemple org.mycompany.MyPartitioner.
Kafka, Upsert Kafka et catalogue Kafka JSON
Kafka est une plateforme de streaming d'événements en ajout seul qui ne prend pas en charge les mises à jour ou les suppressions de données. En SQL streaming, une table sink Kafka standard ne peut pas gérer les données CDC (Change Data Capture) en amont ni la logique de rétractation des opérateurs tels que l'agrégation et la jointure. Si vous devez écrire des données contenant des modifications ou des rétractations, utilisez une table sink Upsert Kafka.
Pour simplifier la synchronisation par lot des données CDC (Change Data Capture) d'une ou plusieurs tables de base de données en amont vers Kafka, vous pouvez utiliser un catalogue Kafka JSON. Si les données stockées dans Kafka sont au format JSON, un catalogue Kafka JSON vous permet d'ignorer l'étape de définition du schéma et des paramètres WITH. Pour plus de détails, consultez Gérer les catalogues Kafka JSON.
Exemples
Exemple 1 : Lire et écrire dans Kafka
Cet exemple lit les données d'un topic source Kafka et les écrit dans un topic sink. Les données sont au format CSV.
CREATE TEMPORARY TABLE kafka_source (
id INT,
name STRING,
age INT
) WITH (
'connector' = 'kafka',
'topic' = 'source',
'properties.bootstrap.servers' = '<yourKafkaBrokers>',
'properties.group.id' = '<yourKafkaConsumerGroupId>',
'format' = 'csv'
);
CREATE TEMPORARY TABLE kafka_sink (
id INT,
name STRING,
age INT
) WITH (
'connector' = 'kafka',
'topic' = 'sink',
'properties.bootstrap.servers' = '<yourKafkaBrokers>',
'properties.group.id' = '<yourKafkaConsumerGroupId>',
'format' = 'csv'
);
INSERT INTO kafka_sink SELECT id, name, age FROM kafka_source;
Exemple 2 : Synchroniser le schéma et les données de la table
Vous pouvez utiliser le connecteur Kafka pour synchroniser en temps réel les messages d'un topic Kafka vers Hologres. Pour éviter les messages en double dans Hologres lors d'un basculement, vous pouvez utiliser l'offset et l'ID de partition des messages Kafka comme clé primaire composite.
CREATE TEMPORARY TABLE kafkaTable (
`offset` INT NOT NULL METADATA,
`part` BIGINT NOT NULL METADATA FROM 'partition',
PRIMARY KEY (`part`, `offset`) NOT ENFORCED
) WITH (
'connector' = 'kafka',
'properties.bootstrap.servers' = '<yourKafkaBrokers>',
'topic' = 'kafka_evolution_demo',
'scan.startup.mode' = 'earliest-offset',
'format' = 'json',
'json.infer-schema.flatten-nested-columns.enable' = 'true'
-- Optional. Flattens all nested columns.
);
CREATE TABLE IF NOT EXISTS hologres.kafka.`sync_kafka`
WITH (
'connector' = 'hologres'
) AS TABLE vvp.`default`.kafkaTable;
Exemple 3 : Synchroniser les clés et les valeurs Kafka
Si la clé d'un message Kafka contient des informations pertinentes, vous pouvez synchroniser à la fois la clé et la valeur.
CREATE TEMPORARY TABLE kafkaTable (
`key_id` INT NOT NULL,
`val_name` VARCHAR(200)
) WITH (
'connector' = 'kafka',
'properties.bootstrap.servers' = '<yourKafkaBrokers>',
'topic' = 'kafka_evolution_demo',
'scan.startup.mode' = 'earliest-offset',
'key.format' = 'json',
'value.format' = 'json',
'key.fields' = 'key_id',
'key.fields-prefix' = 'key_',
'value.fields-prefix' = 'val_',
'value.fields-include' = 'EXCEPT_KEY'
);
CREATE TABLE IF NOT EXISTS hologres.kafka.`sync_kafka`(
WITH (
'connector' = 'hologres'
) AS TABLE vvp.`default`.kafkaTable;
Les clés de message Kafka ne prennent pas en charge l'évolution du schéma ni l'analyse automatique des types. Vous devez déclarer le schéma manuellement.
Exemple 4 : Synchroniser les données et effectuer un calcul
Lorsque vous synchronisez des données de Kafka vers Hologres, vous pouvez avoir besoin de transformations légères.
CREATE TEMPORARY TABLE kafkaTable (
`distinct_id` INT NOT NULL,
`properties` STRING,
`timestamp` TIMESTAMP_LTZ METADATA,
`date` AS CAST(`timestamp` AS DATE)
) WITH (
'connector' = 'kafka',
'properties.bootstrap.servers' = '<yourKafkaBrokers>',
'topic' = 'kafka_evolution_demo',
'scan.startup.mode' = 'earliest-offset',
'key.format' = 'json',
'value.format' = 'json',
'key.fields' = 'key_id',
'key.fields-prefix' = 'key_'
);
CREATE TABLE IF NOT EXISTS hologres.kafka.`sync_kafka` WITH (
'connector' = 'hologres'
) AS TABLE vvp.`default`.kafkaTable
ADD COLUMN
`order_id` AS COALESCE(JSON_VALUE(`properties`, '$.order_id'), 'default');
--Use COALESCE to handle null values.
Exemple 5 : Analyser du JSON imbriqué
Voici un exemple de message JSON :
{
"id": 101,
"name": "VVP",
"properties": {
"owner": "Alibaba Cloud",
"engine": "Flink"
}
}
Pour éviter d'utiliser des fonctions telles que JSON_VALUE(payload, '$.properties.owner') pour analyser les champs, vous pouvez définir directement la structure dans le DDL Source :
CREATE TEMPORARY TABLE kafka_source (
id VARCHAR,
`name` VARCHAR,
properties ROW<`owner` STRING, engine STRING>
) WITH (
'connector' = 'kafka',
'topic' = 'xxx',
'properties.bootstrap.servers' = 'xxx',
'scan.startup.mode' = 'earliest-offset',
'format' = 'json'
);
Avec cette approche, Flink analyse le JSON en champs structurés lors de la phase de lecture. Les requêtes SQL ultérieures peuvent référencer directement properties.owner sans appels de fonction supplémentaires, ce qui améliore les performances globales.
Sémantique Exactly-once
-
Configurer le niveau d'isolation du consommateur
Toutes les applications qui consomment des données Kafka doivent définir la propriété
isolation.level:read_committed: Lit uniquement les données validées.read_uncommitted(Par défaut) : Peut lire des données non validées.
EXACTLY_ONCE dépend de
read_committed. Sinon, les consommateurs peuvent voir des données non validées, ce qui rompt la cohérence. -
Délai d'expiration de la transaction et perte de données
Lors de la récupération à partir d'un checkpoint, Realtime Compute for Apache Flink ne prend en compte que les transactions qui ont été validées avant le début de ce checkpoint. Si la durée entre une panne du job et son redémarrage dépasse le délai d'expiration de la transaction Kafka, Kafka abandonne automatiquement la transaction ouverte, ce qui peut entraîner une perte de données.
Le
transaction.max.timeout.mspar défaut pour un broker Kafka est de 15 minutes.Par défaut, Flink Kafka Sink définit le paramètre
transaction.timeout.mssur 1 heure.Vous devez augmenter
transaction.max.timeout.mssur le broker pour qu'il soit supérieur ou égal au paramètre défini dans Flink.
-
Pool de producteurs et checkpoints concurrents
Le mode
EXACTLY_ONCEutilise un pool de producteurs Kafka de taille fixe. Chaque checkpoint utilise un producteur de ce pool. Si le nombre de checkpoints concurrents dépasse la taille du pool, le job échoue.Configurez la taille du pool de producteurs en fonction du nombre maximal de checkpoints concurrents.
-
Contraintes de réduction du parallélisme
Si un job échoue avant que le premier checkpoint ne soit terminé, les informations du pool de producteurs d'origine sont perdues au redémarrage. Par conséquent, ne réduisez pas le parallélisme du job avant que le premier checkpoint ne soit terminé. Si une réduction est nécessaire, le nouveau parallélisme ne doit pas être inférieur à
FlinkKafkaProducer.SAFE_SCALE_DOWN_FACTOR. -
Les transactions bloquent les lectures
En mode
read_committed, toute transaction qui n'a pas été validée ou abandonnée bloque les opérations de lecture sur l'ensemble du topic.Par exemple :
La transaction 1 écrit des données.
La transaction 2 écrit davantage de données et est validée.
Tant que la transaction 1 reste ouverte, les données de la transaction 2 validée sont invisibles pour les consommateurs.
Cela a les implications suivantes :
Pendant le fonctionnement normal, la latence de visibilité des données est approximativement égale à l'intervalle de checkpoint.
Si un job échoue, tout topic sur lequel il écrivait est bloqué pour les consommateurs jusqu'à ce que le job redémarre ou que la transaction expire. Dans les cas extrêmes, le processus d'expiration de la transaction lui-même peut également affecter les opérations de lecture.