Architecture systèmeArchitecte Système

Décrivez l'architecture d'un pipeline de synchronisation des vues matérialisées qui est fortement cohérent, interrégional, reliant les magasins **OLTP** et **OLAP** en temps réel, prenant en charge l'évolution de schéma non bloquante et mettant en œuvre une résolution automatique des conflits pour les mises à jour de logique commerciale régionales divergentes.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse à la question.

Implémentez une couche de Capture de Données Modifiées (CDC) à l'aide de connecteurs Debezium attachés aux journaux de transactions PostgreSQL. Diffusez des événements via Apache Kafka avec la compression des journaux activée pour garantir la durabilité et la rétention des messages.

Déployez Apache Flink ou ksqlDB pour le traitement de flux avec état, maintenant les sémantiques de exactement une fois via la mise en mémoire tampon sur S3 ou GCS. Utilisez le Confluent Schema Registry avec des formats Avro ou Protobuf pour appliquer des règles de compatibilité arrière et avant, empêchant la rupture des consommateurs pendant l'évolution.

Pour la résolution des conflits, implémentez des Horloges Vectorielles ou des Vecteurs de Versions dans la couche de métadonnées pour suivre la causalité à travers les régions. Appliquez Last-Write-Wins (LWW) uniquement pour les champs non critiques, tout en utilisant des fonctions de fusion basées sur CRDT pour les compteurs et les ensembles. Matérialisez les vues finales dans ClickHouse ou Apache Druid pour l'analyse, garantissant les propriétés ACID via des coordinateurs de transactions distribuées comme Narayana ou des schémas de Saga pour une cohérence éventuelle dans le magasin de vues.

Situation de la vie réelle

GlobalMart, une plateforme de commerce électronique internationale, a rencontré une obsolescence critique des données pendant les événements de Black Friday. Leurs travaux de ETL en lot nocturne créaient une latence de 4 heures entre les enregistrements de transactions MySQL et les tableaux de bord d'analyse BigQuery, entraînant une survente d'inventaire et des mises à jour de prix échouées.

Solution A : CDC Direct vers Index de Recherche. Ils ont considéré le streaming du binlog MySQL directement dans Elasticsearch en utilisant Logstash. Cela offrait une faible latence et un paramétrage simple. Cependant, des opérations de jointure complexes entre les tables devenaient impossibles, et les changements de schéma nécessitaient un réindexage complet d'Elasticsearch, entraînant 6 heures d'interruption.

Solution B : Sourcing d'Événements avec Segmentation des Responsabilités de Commande et de Requête (CQRS). Cette approche utilisait le Framework Axon pour séparer les modèles de lecture et d'écriture. Bien qu'elle ait fourni d'excellentes pistes d'audit et de flexibilité, elle nécessitait une refonte complète de l'application. L'application monolithique existante de Spring Boot de l'équipe ne pouvait pas facilement passer au sourcing d'événements, et la courbe d'apprentissage était trop raide pour le délai de 2 mois.

Solution C : Vues Matérialisées en Streaming avec Registre de Schéma. Ils ont mis en œuvre Debezium capturant depuis PostgreSQL, diffusant vers Kafka, traité par Flink appliquant la logique commerciale, et s'enfonçant vers ClickHouse. Les schémas Avro dans le Confluent Schema Registry appliquaient des vérifications de compatibilité pendant le CI/CD. Pour la résolution des conflits, ils ont utilisé des Horloges Vectorielles intégrées dans les en-têtes de Kafka, permettant une fusion automatique lorsque les promotions régionales causaient des comptes d'inventaire divergents.

Ils ont choisi la Solution C car elle préservait les schémas SQL existants tout en permettant des capacités en temps réel. Le Registre de Schéma a empêché les échecs de déploiement en rejetant les modifications de schéma incompatibles lors des déploiements canari.

Le résultat a atteint une latence de bout en bout de 120 ms, pris en charge 50 000 transactions par seconde et maintenu un RPO de zéro pendant la panne de la région us-east-1 en basculant vers le second système de Kafka mirror maker 2 de la région secondaire.

Ce que les candidats manquent souvent

Comment le CDC gère-t-il la cohérence transactionnelle multi-tables pour prévenir les mises à jour partielles dans les vues matérialisées ?

Beaucoup supposent que Debezium garantit automatiquement l'atomicité à travers les tables. En réalité, le CDC émet des événements séparés par table. Pour maintenir la cohérence, vous devez mettre en œuvre le modèle Transactional Outbox : écrivez les événements business dans une table outbox au sein de la même transaction de base de données que votre logique commerciale. Debezium capture uniquement la table outbox, garantissant l'émission atomique d'événements. Alternativement, utilisez la fonctionnalité transaction.metadata de Debezium pour grouper les événements par ID de transaction dans le consommateur, en tamponnant jusqu'à ce que tous les événements associés arrivent avant de mettre à jour la vue.

Quand choisiriez-vous la cohérence éventuelle plutôt que la cohérence forte pour les vues interrégionales, et quels sont les compromis spécifiques de mise en œuvre ?

Les candidats se dirigent souvent vers la cohérence forte sans prendre en considération les coûts de latence. La cohérence forte nécessite un Commit en Deux Phases (2PC) ou un consensus Paxos/Raft entre les régions, ajoutant 100 à 300 ms de latence par écriture. Cela est nécessaire pour les registres financiers ou l'allocation d'inventaire. Pour les moteurs de recommandations ou les tableaux de bord d'analyse, utilisez des CRDT ou last-write-wins avec des Horloges Vectorielles. Le compromis réside dans la complexité de la logique de fusion côté client par rapport à la coordination côté serveur. Les CRDT nécessitent des structures de données immuables et des opérations commutatives, limitant la flexibilité de la logique commerciale mais offrant une disponibilité pendant les partitions (AP dans le théorème CAP).

Comment empêchez-vous l'évolution de schéma de casser les consommateurs en aval lors de la suppression de champs obsolètes ?

La plupart comprennent la compatibilité avant (le nouveau code lit les anciennes données) mais manquent la compatibilité arrière (l'ancien code lit les nouvelles données). Lors de la suppression d'un champ, ne le supprimez jamais immédiatement. Au lieu de cela, utilisez les valeurs par défaut d'Avro dans le Registre de Schéma, déployez des consommateurs avec le nouveau schéma, puis arrêtez d'écrire le champ dans les producteurs après deux cycles de version. Pour les changements susceptibles de casser (par exemple, changements de type), mettez en œuvre l'Évolution du Schéma via des Sujets Séparés : écrivez dans le sujet events-v2 tout en maintenant events-v1 avec un consommateur de pont, permettant une migration progressive sans temps d'arrêt.