System Design

Le cadre d'entretien de conception système : Concevoir des raccourcisseurs d'URL et des applications de messagerie

Les entretiens de conception système peuvent sembler écrasants, mais ils suivent un schéma prévisible. Le succès ne repose pas sur la connaissance de chaque technologie, mais sur la capacité à structurer clairement sa réflexion. Cet article présente un cadre robuste applicable à des problèmes classiques comme les raccourcisseurs d'URL et les applications de messagerie en temps réel, vous aidant à démontrer une maturité architecturale et une profondeur d'analyse.

Étape 1 : Clarifier les exigences et le périmètre

Ne sautez jamais directement à l'architecture. Commencez par définir les limites du problème. Pour un raccourcisseur d'URL, demandez : avons-nous besoin d'analyses ? Quel est le trafic attendu ? Le temps d'expiration du lien est-il critique ? Pour une application de messagerie, clarifiez : s'agit-il d'échanges individuels ou de groupes ? Faut-il un support hors ligne ou des accusés de lecture ? Les contraintes quantitatives sont cruciales. Supposons que le raccourcisseur d'URL doive gérer 100 millions d'écritures par jour et 1 milliard de lectures par jour. Pour l'application de messagerie, supposons 500 000 utilisateurs actifs quotidiens avec une moyenne de 50 messages par utilisateur.

Étape 2 : Conception de l'architecture de haut niveau

Esquissez les composants principaux. Les deux systèmes incluent typiquement un Client, un Équilibreur de charge, des Serveurs d'application, une Couche de données et éventuellement un Cache.

Architecture du raccourcisseur d'URL

La logique centrale est simple : associer une URL longue à un code court unique. À l'écriture, générez un ID unique et stockez l'association. À la lecture, recherchez l'ID et redirigez. Une décision critique est la stratégie de génération d'ID. L'utilisation d'un auto-incrément de base de données est simple mais peut devenir un goulot d'étranglement. Une meilleure approche consiste à utiliser un générateur d'ID distribué ou du hachage. Envisagez l'encodage base62 pour maximiser le nombre d'URL courtes possibles dans une limite de 7 caractères.

// Pseudocode pour la génération d'URL courtes
function generateShortCode(longUrl) {
    // Option 1 : Séquence de base de données
    id = db.get_next_id();
    
    // Option 2 : Basé sur le hachage (avec vérification de collision)
    hash = md5(longUrl).substring(0, 7);
    if (db.exists(hash)) {
        handle_collision(hash);
    }
    
    base62_code = to_base62(id);
    return base62_code;
}

Architecture de l'application de messagerie

La messagerie est en temps réel, nécessitant des connexions WebSocket ou du long polling. L'architecture doit gérer l'état éphémère (statut en ligne) et l'état persistant (messages). Une File de messages (Kafka, RabbitMQ) est essentielle pour découpler l'ingestion des messages de leur livraison. Le serveur d'application ne doit pas maintenir directement les connexions WebSocket vers la base de données ; au lieu de cela, il doit persister les messages dans un magasin NoSQL (comme Cassandra ou DynamoDB) pour la durabilité et utiliser un service séparé pour la diffusion en temps réel.

Étape 3 : Modèle de données et choix du stockage

Les modèles de données doivent correspondre aux motifs d'accès.

Modèle de données du raccourcisseur d'URL

Une base de données relationnelle (MySQL) est souvent suffisante pour la table d'association si les ratios de lecture/écriture sont équilibrés, mais la recherche est le chemin le plus sollicité. Utilisez Redis pour mettre en cache les codes courts fréquents. La structure de la table est simple : short_code (PK), long_url, created_at, creator_id. Le partitionnement par hachage de short_code assure une distribution uniforme entre les nœuds.

Modèle de données de l'application de messagerie

Les messages de messagerie sont en ajout uniquement. Un magasin à colonnes larges comme Cassandra est idéal pour des écritures à haut débit. Concevez la table pour permettre une récupération efficace des messages récents d'une conversation.

CREATE TABLE messages (
    conversation_id uuid,
    message_timestamp timeuuid,
    sender_id uuid,
    content text,
    PRIMARY KEY (conversation_id, message_timestamp)
) WITH CLUSTERING ORDER BY (message_timestamp DESC);

Étape 4 : Évolutivité et goulots d'étranglement

Identifiez où votre conception échoue.

Évolutivité des raccourcisseurs d'URL

Les lectures sont typiquement 10 à 100 fois plus fréquentes que les écritures. La mise en cache est obligatoire. Implémentez un cache multi-niveaux : L1 en mémoire (Caffeine) sur le serveur d'application, L2 distribué (Redis). Pour les clés chaudes, utilisez un cache local pour réduire la latence réseau. Si le générateur d'ID devient un goulot d'étranglement, passez à un générateur de séquences distribué qui pré-alloue des plages d'ID aux serveurs d'application.

Évolutivité des applications de messagerie

Le goulot d'étranglement est la couche WebSocket. Les serveurs d'application qui maintiennent des connexions socket sont à état. Utilisez une couche de connexion qui prend en charge l'évolutivité horizontale, éventuellement avec un équilibreur de charge à sessions collantes ou un service de passerelle à état. Pour la diffusion des messages dans les conversations de groupe, utilisez un système Pub/Sub (comme Kafka) où chaque membre d'un groupe s'abonne à son propre sujet ou partition. Cela garantit que chaque utilisateur reçoit ses messages sans bloquer les autres.

Étape 5 : Compromis et cas limites

Démontrez votre profondeur en discutant des compromis. Pour les raccourcisseurs d'URL, discutez du compromis entre la garantie d'unicité et les performances. Un hachage peut entraîner des collisions ; une séquence est unique mais centralisée. Pour la messagerie, discutez du compromis entre la cohérence et la disponibilité. Dans une application de messagerie, perdre un message est mauvais, donc priorisez la durabilité. Cependant, pour les mises à jour de présence (en ligne/hors ligne), la forte cohérence n'est pas nécessaire ; la cohérence éventuelle via un cache basé sur TTL est acceptable et plus performante.

Conclusion

Les entretiens de conception système concernent la résolution structurée de problèmes, pas la mémorisation. En suivant ce cadre—clarifier les exigences, concevoir l'architecture de haut niveau, choisir le bon modèle de données, identifier les goulots d'étranglement d'évolutivité et discuter des compromis—vous pouvez naviguer avec confiance dans des questions de conception complexes. Pratiquez l'application de cette méthodologie aux raccourcisseurs d'URL et aux applications de messagerie, et vous développerez l'intuition nécessaire pour relever tout défi de conception système.

Share: