L architecture event-driven est devenue centrale dans les systèmes data modernes. En entretien Architect, on évalue la capacité à concevoir des systèmes découplés et résilients.
Quels sont les avantages d une architecture event-driven pour un système data ?
Qu est-ce que CQRS ? Comment s applique-t-il à une architecture data ?
# CQRS : Command Query Responsibility Segregation
# Séparer les opérations d écriture (Commands) des lectures (Queries)
# COMMAND SIDE : optimisé pour les écritures
# - Base transactionnelle (PostgreSQL)
# - Modèle normalisé
# - Cohérence forte
class CreateOrderCommand:
def execute(self, order: dict) -> None:
db.insert('orders', order)
event_bus.publish('OrderCreated', order) # publier l event
# QUERY SIDE : optimisé pour les lectures
# - Data warehouse (Snowflake, BigQuery)
# - Modèle dénormalisé, pré-agrégé
# - Cohérence éventuelle (délai de réplication)
class GetRevenueByRegionQuery:
def execute(self, region: str) -> float:
return warehouse.query(
'SELECT SUM(amount) FROM fct_revenue WHERE region = ?', region
)Comment Kafka peut-il servir de source de vérité dans une architecture event sourcing ?
Quel problème l outbox pattern résout-il ?
# Problème sans outbox :
# 1. INSERT en base (succès)
# 2. Publier event Kafka (ÉCHEC)
# -> la base et Kafka sont incohérents
# Outbox Pattern : atomic dual write
# Dans la même transaction :
def create_order(order: dict):
with transaction():
db.insert('orders', order) # 1. Insérer en base
db.insert('outbox', { # 2. Insérer dans l outbox
'event_type': 'OrderCreated',
'payload': json.dumps(order),
'status': 'pending'
})
# Transaction atomique : les deux réussissent ou échouent ensemble
# Débrayeur (Debezium ou polling) :
# Lire l outbox et publier dans Kafka
# Marquer comme 'published' après succèsQu est-ce qu un Saga ? Comment gère-t-il l échec d une étape dans un processus multi-services ?
Comment décidez-vous si une architecture event-driven est justifiée ?
import asyncio
from dataclasses import dataclass
from typing import Callable
import json
# Event-driven pipeline simple avec Kafka
@dataclass
class OrderEvent:
order_id: str
customer_id: str
amount: float
event_type: str # order_created, order_paid, order_shipped
class EventBus:
def __init__(self):
self.handlers: dict[str, list[Callable]] = {}
def subscribe(self, event_type: str, handler: Callable):
self.handlers.setdefault(event_type, []).append(handler)
async def publish(self, event: OrderEvent):
for handler in self.handlers.get(event.event_type, []):
await handler(event)
# Handlers
async def update_inventory(event: OrderEvent):
await db.execute("UPDATE inventory SET stock = stock - 1 WHERE product_id = ?", [event.order_id])
async def send_confirmation_email(event: OrderEvent):
await email_service.send(customer_id=event.customer_id, template="order_confirmation")
bus = EventBus()
bus.subscribe("order_paid", update_inventory)
bus.subscribe("order_paid", send_confirmation_email)| Niveau | Maitrise | Signal GO | NO-GO |
|---|---|---|---|
| Confirmé | EDA principes, Kafka producer/consumer, découplage | Explique les avantages du découplage via events, a consommé Kafka | Ne sait pas ce qu est l eventual consistency |
| Senior | CQRS, Event Sourcing, Outbox pattern, Saga | A implémenté l outbox pattern, explique CQRS et ses trade-offs | Ne sait pas ce qu est l outbox pattern |
Premier entretien gratuit. Rapport GO/NO-GO sous 48h.