---
title: "Comparatif des files d'attente de messages : Redis, RabbitMQ, Kafka | DevSense"
description: "Comment choisir un courtier pour le travail asynchrone : comparaison des files d'attente en mémoire (Redis), des courtiers AMQP (RabbitMQ) et des journaux de validation (Kafka) selon l'ordonnancement, la mise à l'échelle, la durabilité et le coût opérationnel."
faq:
    - { question: "Quelle est la principale différence entre une file d'attente de messages (comme RabbitMQ) et un courtier basé sur les journaux (comme Kafka) ?", answer: "RabbitMQ utilise un modèle 'courtier intelligent, consommateur passif' (smart broker, dumb consumer), où le courtier suit l'état des messages (acquittements, lectures, suppressions) et supprime les messages immédiatement après leur consommation réussie. Kafka utilise un modèle 'courtier passif, consommateur intelligent' (dumb broker, smart consumer), où les messages sont ajoutés à un journal de transactions (write-ahead log) sur le disque et conservés pendant une période de rétention définie. Les consommateurs suivent leur propre position de lecture (offset), ce qui leur permet de rejouer les messages indépendamment." }
    - { question: "Pourquoi les files d'attente de messages sont-elles préférées aux tables de bases de données pour les files de tâches asynchrones ?", answer: "Les bases de données ne sont pas conçues pour les modèles de file d'attente. L'interrogation (polling) des tables crée des contentions de verrous (lock contention), une utilisation élevée du processeur et une fragmentation des tables (bloat) en raison d'insertions et de suppressions rapides. Les files d'attente de messages stockent l'état en mémoire (ou dans des segments de disque séquentiels structurés) et prennent en charge des notifications de poussée (push) vers les consommateurs connectés, ce qui offre un débit beaucoup plus élevé et une latence d'exécution plus faible." }
    - { question: 'Comment Kafka parvient-il à un débit élevé par rapport aux courtiers traditionnels ?', answer: "Kafka écrit les messages de manière séquentielle dans un journal sur disque (en exploitant le cache de pages du système d'exploitation et le transfert sans copie (zero-copy) vers les sockets réseau), contournant ainsi la surcharge de sérialisation en mémoire. Il partitionne les journaux pour paralléliser les charges d'écriture et de lecture sur plusieurs serveurs (brokers) et regroupe les messages par lots pour réduire la surcharge réseau et d'E/S." }
    - { question: 'Quand Redis est-il un bon choix pour la messagerie, et quelles sont ses limites ?', answer: "Redis est un excellent choix à faible latence pour les files d'attente simples (à l'aide de Listes ou de Pub/Sub) ou les flux (Streams) structurés lorsque vous l'utilisez déjà pour la mise en cache. Cependant, il est limité par la taille de la RAM du serveur car toutes les données actives sont stockées en mémoire, et il ne dispose pas de fonctionnalités de routage avancées telles que le routage par échange (exchange routing), la mise en file d'attente des messages rejetés (dead-lettering) ou une durabilité sur disque garantie à long terme." }
published: '2026-05-31'
---
# Comparatif des files d'attente de messages : Redis, RabbitMQ et Apache Kafka

Décider comment extraire le travail du chemin de la requête HTTP est une étape architecturale classique. Mais choisir **comment** acheminer ce travail peut conduire à une paralysie décisionnelle. Vous n'avez pas besoin de faire tourner un cluster Kafka à trois nœuds pour envoyer cinquante e-mails de bienvenue par jour, et vous ne devriez pas non plus concevoir un grand livre financier sur du Pub/Sub Redis. Le bon courtier (broker) résulte d'un équilibre entre **les exigences d'ordonnancement**, **les garanties de livraison**, **le débit**, et **la surcharge opérationnelle (Ops) que votre équipe est prête à supporter**.

**Guides associés :** [High-load event ingestion](high-load-event-ingestion) · [Databases under load](database-performance-and-scaling) · [Observability and monitoring](observability-monitoring-laravel)

## Table des matières

* [Pourquoi ne pas utiliser une table de base de données ?](#why-not-db)
* [Les trois modèles de messagerie](#three-models)
* [Redis : simple, en mémoire, à faible latence](#redis)
* [RabbitMQ : courtier intelligent, routage flexible](#rabbitmq)
* [Apache Kafka : le journal de validation distribué](#kafka)
* [Matrice de comparaison des fonctionnalités](#matrix)
* [Garanties de livraison : au moins une fois, au plus une fois, exactement une fois](#delivery)
* [Ordonnancement, groupes de consommateurs et mise à l'échelle](#ordering)
* [Coût opérationnel : Géré (Managed) vs Auto-hébergé](#ops-cost)
* [Erreurs courantes](#common-mistakes)
* [Liste de contrôle](#checklist)
* [Quiz d'auto-évaluation](#self-test-quiz)

---

<a id="why-not-db"></a>
## Pourquoi ne pas utiliser une table de base de données ?

Il est tentant de consigner des tâches (`jobs`) dans PostgreSQL ou MySQL, d'indexer la colonne `status` et d'interroger la table toutes les secondes.
Pour les configurations à faible volume, cela **peut fonctionner**. Cependant, à mesure que le volume augmente, la base de données s'effondre sous ce type de charge :
* **Fragmentation de la table (Bloat)** — les moteurs de bases de données n'aiment pas les schémas d'écriture puis de suppression constante. Les tuples morts s'accumulent, l'autovacuum prend du retard et les performances des index se dégradent.
* **Contention de verrous par interrogation (Polling)** — plusieurs processus workers exécutant `SELECT ... FOR UPDATE LIMIT 1` verrouillent en écriture les mêmes pages d'index, bloquant ainsi le débit.
* **Poussée (Push) vs Tirage (Pull)** — les bases de données vous obligent à faire de l'interrogation (pull) ; les courtiers poussent les messages instantanément vers les connexions TCP en attente.

---

<a id="three-models"></a>
## Les trois modèles de messagerie

1. **File d'attente en mémoire volatile (Redis Lists / Pub/Sub)** — Rapide, légère, les données doivent tenir dans la RAM, modèles simples.
2. **File d'attente de messages classique (RabbitMQ / ActiveMQ)** — Routage complexe, les files d'attente suivent l'état des consommateurs, les messages sont supprimés une fois acquittés.
3. **Flux d'événements basé sur les journaux (Kafka / Redpanda)** — Journal sur disque en écriture seule à la fin (append-only), les messages persistent après lecture, les consommateurs suivent leurs propres positions (offsets).

---

<a id="redis"></a>
## Redis : simple, en mémoire, à faible latence

Redis est un magasin de données en mémoire qui prend en charge des primitives de file d'attente.

### Mécanismes
* **Listes (`LPUSH` / `BRPOP`)** — Une file d'attente FIFO de base. Simple, latence extrêmement faible (microsecondes), mais manque de routage avancé.
* **Flux / Streams (Redis 5.0+)** — Ajoute des entrées à un journal, prend en charge les groupes de consommateurs et l'acquittement (`XACK`).
* **Pub/Sub** — Diffusion de type diffusion et oubli (fire-and-forget). Si aucun consommateur n'est connecté lorsqu'un message est publié, le message est **perdu**.

### Points forts
* Aucune infrastructure supplémentaire si vous utilisez déjà Redis pour le cache ou le stockage de sessions.
* Latence extrêmement faible.

### Faiblesses
* **Limites de la RAM** — Si les workers ralentissent et que la file d'attente grandit, vous risquez d'épuiser la mémoire du serveur.
* **Compromis de durabilité** — La persistance AOF/RDB s'écrit de manière asynchrone ; un crash soudain peut faire perdre les messages récents.

---

<a id="rabbitmq"></a>
## RabbitMQ : courtier intelligent, routage flexible

RabbitMQ est un courtier AMQP (Advanced Message Queuing Protocol) écrit en Erlang.

### Concepts clés
* Les **Producteurs** publient des messages vers des **Exchanges**.
* Les **Exchanges** acheminent les messages vers des **Files d'attente (Queues)** à l'aide de **Liaisons (Bindings)** (règles basées sur des clés de routage, des en-têtes ou de la diffusion/fanout).
* Les **Consommateurs** lisent depuis les **Files d'attente**.

```
Producteur ──> [ Exchange ] ──(Règles de liaison)──> [ File d'attente ] ──> Consommateur
```

### Points forts
* Modèles de routage riches (par exemple, correspondance de thèmes/topics, routage d'en-têtes).
* Sémantique d'acquittement (Ack / Negative-Ack) par message.
* Files d'attente de messages rejetés (Dead Letter Exchanges - DLX) intégrées pour les tentatives infructueuses.

### Faiblesses
* **L'environnement d'exécution Erlang** ajoute une surcharge opérationnelle pour la configuration et la gestion des clusters.
* Les performances des files d'attente se dégradent si elles stockent des millions de messages et doivent déborder sur le disque.

---

<a id="kafka"></a>
## Apache Kafka : le journal de validation distribué

Kafka n'est pas une file d'attente de messages traditionnelle. C'est un journal de transactions distribué, partitionné et en écriture seule en fin de fichier (append-only).

### Concepts clés
* Les **Sujets (Topics)** sont divisés en **Partitions**.
* Les messages sont ajoutés de manière séquentielle sur le disque.
* Un message est identifié par son **Offset** (position d'index).
* Les consommateurs rejoignent des **Groupes de consommateurs (Consumer Groups)** ; Kafka attribue des partitions aux membres du groupe.

```
Sujet : Commandes
Partition 0 : [Msg 0][Msg 1][Msg 2][Msg 3]  <-- Consommateur A (Offset 3)
Partition 1 : [Msg 0][Msg 1]                <-- Consommateur B (Offset 1)
```

### Points forts
* **Débit élevé** — Les écritures sont séquentielles sur le disque ; les lectures exploitent le cache de pages du système d'exploitation et le transfert réseau sans copie (zero-copy).
* **Rejeu des messages (Message Replay)** — Comme les messages persistent sur le disque pendant une fenêtre de rétention définie, vous pouvez rembobiner les offsets et rejouer l'historique.
* **Évolutivité** — Le partitionnement permet une mise à l'échelle horizontale sur plusieurs serveurs (brokers).

### Faiblesses
* Grande complexité. Nécessite Apache ZooKeeper ou KRaft pour la coordination.
* Latence plus élevée par rapport à Redis (millisecondes contre microsecondes).
* Surdimensionné pour le traitement de tâches simples.

---

<a id="matrix"></a>
## Matrice de comparaison des fonctionnalités

| Fonctionnalité | Redis (Lists) | RabbitMQ | Apache Kafka |
|----------------|---------------|----------|--------------|
| **Modèle principal** | Liste / Flux en mémoire | Courtier intelligent (AMQP) | Journal de validation distribué |
| **Persistance** | Volatile / Disque optionnel | Disque/Mémoire (configurable) | Toujours sur disque (Journal) |
| **Débit maximal**| Élevé (limité par le CPU monocœur/RAM) | Modéré (dizaines de milliers/s) | Extrême (millions/s via partitionnement) |
| **Durée de vie du message** | Supprimé à la lecture (pop) | Supprimé après Ack | Conservé selon politique de temps/taille |
| **Flexibilité du routage** | Aucune (FIFO) | Élevée (Exchanges & Bindings) | Mappage clé-partition |
| **Garanties d'ordre** | FIFO strict | Strict par file (consommateur unique) | Strict **au sein d'une partition** |

---

<a id="delivery"></a>
## Garanties de livraison

Aucun système de messagerie ne peut garantir une livraison « exactement une fois » (exactly-once) à travers le réseau sans coordination distribuée des transactions (ce qui dégrade les performances).

* **Au plus une fois (At-most-once)** — Les messages sont envoyés sans confirmation. Si une coupure réseau ou un crash survient, le message est perdu.
* **Au moins une fois (At-least-once)** — Les consommateurs doivent accuser réception du traitement. En cas de crash en cours de traitement, le courtier livre à nouveau le message. **Votre logique applicative doit être idempotente** pour gérer les doublons.
* **Exactement une fois (Exactly-once)** — Nécessite une coordination de bout en bout (comme les transactions Kafka). Souvent simulé en combinant la livraison « au moins une fois » avec une déduplication à la destination.

> [!NOTE]
> **Règle d'idempotence**
> Concevez toujours vos consommateurs pour gérer les doublons. Utilisez des identifiants de transaction uniques ou des clés métier pour vous prémunir contre le traitement d'un même événement deux fois.

---

<a id="ordering"></a>
## Ordonnancement, groupes de consommateurs et mise à l'échelle

* **RabbitMQ** garantit l'ordre au sein d'une seule file d'attente. Si vous passez à plusieurs consommateurs parallèles, ils traitent les messages à des vitesses différentes, ce qui peut entraîner une exécution désordonnée au niveau de l'application.
* **Kafka** garantit l'ordre **uniquement au sein d'une partition**. Pour maintenir l'ordre d'une ressource (par exemple, les mises à jour de la commande #105), vous devez acheminer tous ses événements vers la même partition en utilisant une clé de partition (par exemple, `order_id`).

---

<a id="ops-cost"></a>
## Coût opérationnel : Géré (Managed) vs Auto-hébergé

* **Redis** est facile à exécuter et à gérer. Presque tous les fournisseurs de cloud proposent un service Redis géré.
* **RabbitMQ** nécessite une surveillance active de l'utilisation de la mémoire des files d'attente, de l'espace disque et de la synchronisation des clusters Erlang. Les options gérées (comme CloudAMQP ou AWS Amazon MQ) réduisent cette charge.
* **Kafka** est le plus complexe à exploiter. Gérer les rééquilibrages de partitions, la configuration des courtiers, la rétention sur disque et le consensus KRaft est un rôle opérationnel à plein temps. Utilisez des plateformes gérées (comme Confluent Cloud, AWS MSK ou Aiven) à moins d'avoir une équipe d'infrastructure dédiée.

---

<a id="common-mistakes"></a>
## Erreurs courantes

1. **Publication d'événements à l'intérieur de transactions de base de données** : Enfiler un message avant d'avoir validé (commit) la transaction de base de données. Si le consommateur s'exécute plus vite que la validation, il recherchera des enregistrements qui n'existent pas encore.
2. **Absence de limites de pré-lecture (Prefetch) dans RabbitMQ** : Ne pas définir la limite de pré-lecture par défaut. RabbitMQ poussera tous les messages de la file d'attente vers le premier consommateur disponible, le surchargeant pendant que les autres workers restent inactifs.
3. **Utilisation de Kafka sans clés de partition** : Publier des événements sur Kafka sans spécifier de clé de routage, ce qui achemine les messages de manière aléatoire et rompt les garanties d'ordonnancement pour les enregistrements liés.
4. **Traitement du Pub/Sub comme une file d'attente persistante** : Utiliser le Pub/Sub Redis pour les tâches en arrière-plan, en supposant que les messages sont mis en tampon lorsque les consommateurs sont hors ligne.

---

<a id="checklist"></a>
## Liste de contrôle

1. **Vérifiez votre volume :** Moins de 10 000 messages/s ? Oubliez Kafka ; commencez par Redis ou RabbitMQ.
2. **Définissez la durabilité :** Pouvez-vous vous permettre de perdre un message en cas de panne du serveur ? Si non, évitez les listes Redis purement en mémoire.
3. **Vérifiez les exigences de routage :** Avez-vous besoin de schémas de routage complexes (par exemple, routage par thème/topic) ? Choisissez RabbitMQ.
4. **Établissez les limites d'ordonnancement :** Avez-vous besoin d'un ordre strict par entité sur des workers parallèles ? Choisissez Kafka avec des clés de partition.
5. **Prenez en compte le coût opérationnel :** Votre équipe a-t-elle la bande passante nécessaire pour maintenir KRaft/ZooKeeper ? Si non, choisissez un service géré.

---

## Résumé

Le bon outil correspond à la forme de vos données. Utilisez **Redis** pour les files de tâches rapides, **RabbitMQ** lorsque la logique de routage est complexe, et **Kafka** lorsque vous avez besoin d'un journal de validation à haut débit.

---

<a id="self-test-quiz"></a>
## Quiz d'auto-évaluation

### Question 1 : Qu'advient-il d'un message dans le Pub/Sub Redis si aucun abonné actif n'est connecté au moment où il est publié ?
- A) Il est mis en file d'attente en mémoire jusqu'à ce qu'un abonné se connecte.
- B) Il est rejeté et perdu de manière permanente.
- C) Il est écrit dans le fichier instantané RDB.

<details>
<summary><b>Afficher les réponses</b></summary>

**Réponse : B**
Le Pub/Sub Redis est un mécanisme de diffusion de type diffusion et oubli (fire-and-forget). Il ne met pas en tampon les messages pour les clients déconnectés ; ils sont perdus immédiatement si aucun abonné n'est actif.
</details>

---

### Question 2 : Dans Apache Kafka, comment s'assurer que toutes les mises à jour de statut pour un utilisateur spécifique sont traitées dans l'ordre exact où elles se sont produites ?
- A) Ne faites fonctionner qu'un seul courtier (broker).
- B) Utilisez l'identifiant de l'utilisateur (`user_id`) comme clé de partition afin que tous les événements pour cet utilisateur atterrissent dans la même partition.
- C) Réglez la rétention des journaux sur l'infini.

<details>
<summary><b>Afficher les réponses</b></summary>

**Réponse : B**
Kafka garantit l'ordre des messages uniquement au sein d'une seule partition. En utilisant le `user_id` comme clé de partition, Kafka achemine tous les événements de cet utilisateur vers la même partition, préservant ainsi l'ordre d'exécution.
</details>