L'architecture utilise un modèle à double stockage qui sépare strictement les préoccupations de service en ligne et de formation hors ligne. Le niveau en ligne utilise Redis Cluster déployé sur des instances soutenues par NVMe dans chaque région, précédé par Envoy Proxy pour l'équilibrage de charge local et la terminaison TLS. Les mises à jour de caractéristiques transitent par Apache Kafka agissant comme le changelog immuable, avec des connecteurs CDC Debezium capturant les mutations des bases de données opérationnelles et les diffusant aux consommateurs Redis régionaux.
Pour le stockage hors ligne, les caractéristiques historiques sont compactées dans des tables Apache Iceberg sur S3, permettant des requêtes temporelles et un traitement par lots efficace via Apache Spark. La cohérence pendant le remplissage est assurée par le versionnement de l'horloge vectorielle : chaque valeur de caractéristique porte un horodatage logique, et les scripts Lua de Redis effectuent des opérations atomiques de comparaison et d'échange pour rejeter les écritures dans le désordre, garantissant que le chemin de service n'observe jamais des états de remplissage partiels.
La détection de dérive tire parti des histogrammes Prometheus récupérés par un job Apache Flink effectuant une analyse statistique en temps réel des distributions de caractéristiques. Lorsque la divergence KL ou l'indice de stabilité de la population dépasse des seuils, Flink déclenche les Argo Workflows pour orchestrer le réentraînement de modèle inter-régions et les déploiements canari.
Une entreprise fintech multinationale a besoin de capacités de détection de fraude en temps réel dans AWS, Azure et dans des centres de données sur site. Le défi critique était de servir des caractéristiques d'agrégation roulantes—telles que la vitesse de transaction des utilisateurs au cours de la dernière heure—aux points de terminaison d'inférence avec une latence inférieure à 5 ms. Leurs répliques de lecture PostgreSQL existantes souffraient d'un retard de réplication supérieur à 200 ms lors des charges de pointe, entraînant des modèles de scoring de fraude sur des données obsolètes et manquant des attaques coordonnées.
Solution 1: Base de données active-active mondiale Le déploiement de CockroachDB ou Google Spanner promettait une isolation sérialisable et une réplication globale automatique. Cette approche éliminait les préoccupations de cohérence mais introduisait une latence d'écriture inter-régions dépassant 100 ms en raison du coût de consensus de Paxos. Pour des caractéristiques à haute vitesse nécessitant une visibilité immédiate des nouvelles transactions, cette latence s'est révélée inacceptable. En outre, les coûts opérationnels augmentaient de manière quadratique avec le débit de lecture, rendant cela économiquement irréaliste pour des exigences de service au niveau de la milliseconde.
Solution 2: Cohérence éventuelle avec des caches régionaux La mise en œuvre de clusters Redis indépendants par région avec réplication asynchrone via Kafka MirrorMaker offrait d'excellentes performances de lecture et une scalabilité linéaire. Cependant, cela créait des vulnérabilités critiques de cohérence pendant les opérations de remplissage lorsque les data scientists recomptaient les caractéristiques historiques pour corriger les problèmes de qualité des données. Sans garanties de versionnement strict, le système servait des agrégats obsolètes à côté de nouveaux, conduisant à un biais dans l'inférence du modèle et à des scores de risque erronés qui marquaient faussement des transactions légitimes.
Solution 3: Caching en plusieurs couches avec horloges vectorielles (Choisi) Nous avons conçu un système en plusieurs couches en utilisant Redis comme couche chaude et Kafka comme source immuable de vérité. Chaque valeur de caractéristique portait un horodatage d'horloge vectorielle dérivé du pipeline d'ingestion. Pendant le remplissage, des jobs Spark écrivaient dans S3 tout en émettant des événements versionnés vers Kafka. Les consommateurs régionaux appliquaient des mises à jour via des scripts Lua de Redis qui effectuaient des comparaisons d'horloge vectorielle côté serveur, rejetant atomiquement les écritures dans le désordre tout en acceptant les nouvelles versions. Pour la détection de dérive, nous avons instrumenté les distributions de caractéristiques via des histogrammes Prometheus, alimentant Flink pour une comparaison statistique en temps réel par rapport aux références d'entraînement.
Le résultat a réduit la latence de service P99 à 1,2 ms au niveau mondial, éliminé les violations de cohérence pendant les remplissages, et réduit les incidents de dégradations de modèle de 94 % grâce à des pipelines de réentraînement déclenchés par la dérive automatisée.
Comment empêchez-vous le empoisonnement du cache pendant les remplissages historiques de caractéristiques en vrac lorsque la couche de service en ligne doit rester disponible ?
De nombreux candidats suggèrent simplement de mettre en pause le service pendant les remplissages ou d'utiliser des transactions distribuées couvrant le cache et la base de données. L'approche correcte implémente des horodatages logiques et des espaces de clés d'ombre. Les flux de données de remplissage passent par un sujet Kafka séparé avec des ID de version augmentant monotoniquement. Les clusters de service en ligne maintiennent deux espaces de clés Redis : "current" et "staging". Le remplissage peuple le staging tandis que le service lit à partir de l'actuel. À l'achèvement, une opération atomique RENOMMER de Redis échange les espaces de clés en quelques microsecondes, ou alternativement, la couche d'application interroge les deux espaces de clés et sélectionne la valeur avec la version la plus élevée. Cela garantit zéro temps d'arrêt et empêche le service d'états de remplissage partiels sans protocoles de coordination complexes.
Quel modèle de cohérence devrait régir la relation entre les magasins de caractéristiques en ligne et hors ligne, et pourquoi la forte cohérence échoue-t-elle à l'échelle ?
Les candidats plaident souvent à tort pour des transactions ACID couvrant à la fois Redis et S3 en utilisant des protocoles à deux phases d'engagement. Le magasin hors ligne optimise le débit et l'immuabilité en lot, tandis que le magasin en ligne optimise les lectures à point à faible latence. La forte cohérence nécessite un coût de consensus qui introduit une latence inacceptable dans le chemin de service. Au lieu de cela, adoptez une cohérence éventuelle avec des garanties de fraîcheur bornées. Utilisez la compression de journal Kafka avec une fenêtre de réconciliation basée sur la rétention pour garantir que le magasin en ligne converge vers l'état du magasin hors ligne dans une limite de temps définie. Pour les caractéristiques nécessitant des garanties plus strictes, implémentez un cache d'écriture à traverse où l'accusé de réception d'écriture en ligne attend la confirmation d'engagement de Kafka, acceptant une latence légèrement plus élevée pour les caractéristiques critiques tout en maintenant un débit élevé pour les autres grâce à une réplication asynchrone.
Comment gérez-vous le versionnement des caractéristiques pendant les tests A/B de modèles nécessitant des transformations incompatibles des mêmes données brutes ?
Une erreur courante est de versionner uniquement l'artéfact du modèle tout en ignorant l'évolution du schéma des caractéristiques, menant à un biais d'entraînement-servidor. La solution implémente des espaces de noms de caractéristiques et un suivi de la lignée à l'aide de DataHub ou d'Apache Atlas. Chaque transformation de caractéristique reçoit une version sémantique. Le magasin de caractéristiques maintient plusieurs versions simultanément dans Redis en utilisant des clés préfixées. Les configurations de service de modèle spécifient les versions de caractéristiques requises via Consul ou etcd. Lors de la promotion d'un modèle de l'ombre à la production, la couche d'orchestration préchauffe les caches pour la nouvelle version de caractéristique en utilisant la reproduction historique de Kafka avant que le trafic ne change. Cela permet des tests A/B simultanés utilisant des calculs de caractéristiques incompatibles sans fuite de données entre les cohortes d'expérience ou des pics de latence de démarrage à froid.