Si ta base principale commence à ramer sur les lectures, ne te jette pas immédiatement sur les index ou la RAM. Une read replica, c'est une copie physique de ta base qui ne sert qu'à lire. Et ça, ça change tout.
Le principe repose sur la réplication asynchrone. Chaque transaction écrite sur la primaire est envoyée à la replica, qui l'applique en différé. Concrètement, ta replica peut accuser un léger retard — le fameux lag de réplication. Mais pour 90% des cas d'usage, c'est parfaitement acceptable. Tu décharges ta primaire des SELECT, et elle respire.
Dans ce tuto, je te montre comment intégrer des read replicas dans une stack existante, sans tout casser. On commence par la configuration sur PostgreSQL, MySQL et AWS RDS. Ensuite, on route les requêtes avec ProxySQL ou Pgpool-II pour faire du read/write splitting. Enfin, on surveille le lag et on gère la promotion d'un réplica en primaire en cas de panne.
Un exemple concret ? J'ai vu une app qui faisait des rapports directement sur la base de production. En ajoutant une seule replica et en pointant les rapports dessus, la latence des requêtes critiques est passée de 800ms à 50ms. Sans changer une ligne de code métier. C'est pour ça que je suis un fervent défenseur des read replicas : c'est simple, efficace, et ça te sauve la mise.
Comprendre les read replicas et la réplication asynchrone
Le lag de réplication, c'est le prix à payer pour décharger ta primaire. Et c'est un prix très acceptable. La réplication asynchrone fonctionne comme ça : chaque transaction écrite sur la primaire est enregistrée dans le journal binaire (ou WAL pour PostgreSQL), puis la replica récupère ce journal et applique les changements en différé.
Ce mécanisme a une conséquence directe : ta replica est toujours un peu en retard. Ce retard, c'est le fameux lag de réplication. En pratique, sur un réseau correctement dimensionné, ce lag se mesure en millisecondes. J'ai vu des systèmes avec un lag moyen de 50ms, même sous forte charge. Pour du reporting, de l'analytique ou des pages publiques, c'est totalement invisible.
Mais attention, ce n'est pas de la réplication synchrone. Si tu écris une donnée puis tu la relis immédiatement depuis la replica, tu peux ne pas la voir. C'est ce qu'on appelle la cohérence éventuelle. Pour les cas où tu as besoin d'une lecture immédiate après écriture, route la requête vers la primaire. C'est le principe du read/write splitting, qu'on verra plus loin.
Un exemple concret ? Sur une app de e-commerce, on a déplacé toutes les requêtes de catalogue vers une replica. Le lag moyen était de 80ms. Les utilisateurs n'ont rien remarqué, mais la primaire est passée de 90% à 30% de CPU. Et les requêtes critiques sont passées de 800ms à 50ms de latence. Sans changer une ligne de code métier.
Pour vérifier le lag, tu peux utiliser une commande simple :
Si ce lag dépasse quelques secondes, il faut s'inquiéter. Mais tant qu'il reste sous le seuil de tes besoins, les read replicas sont une solution redoutablement efficace.
Configurer des read replicas sur PostgreSQL, MySQL et AWS RDS
La configuration d'une read replica, c'est souvent plus simple que tu ne le penses, et je vais te montrer les étapes exactes pour PostgreSQL, MySQL et AWS RDS. Sur PostgreSQL, ça tient en deux commandes ; sur MySQL, c'est à peine plus long ; et sur AWS RDS, c'est un clic dans la console ou une seule commande CLI. Dans tous les cas, tu vas décharger ta primaire des lectures en moins de dix minutes.
Pour PostgreSQL, commence par ajouter les paramètres de réplication dans postgresql.conf : wal_level = replica, max_wal_senders = 10, hot_standby = on, puis redémarre le service. Ensuite, crée un utilisateur de réplication avec CREATE USER repl REPLICATION LOGIN PASSWORD 'secret'; et lance la sauvegarde de base avec pg_basebackup -h primaire -U repl -D /var/lib/postgresql/data -R — cette commande copie les données et configure automatiquement le fichier standby.signal (ou recovery.conf sur les versions antérieures à 12). Un exemple concret : j'ai configuré une replica pour une app de reporting en cinq minutes, et le lag moyen était de 30ms.
Côté MySQL, le principe est similaire mais avec des commandes différentes : active le log binaire sur la primaire avec log_bin = ON et server-id = 1, puis redémarre. Sur la replica, configure server-id = 2, exécute CHANGE MASTER TO MASTER_HOST='primaire', MASTER_USER='repl', MASTER_PASSWORD='secret', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154; et enfin START SLAVE; — attention à bien récupérer le fichier et la position du log binaire sur la primaire avec SHOW MASTER STATUS;. Pour vérifier que tout fonctionne, utilise SHOW SLAVE STATUS\G et regarde le champ Seconds_Behind_Master ; s'il est à NULL, c'est que la réplication est cassée, et s'il est à 0, tout est synchronisé.
Avec AWS RDS, tu n'as même pas besoin de toucher aux fichiers de config, et c'est un vrai soulagement. Dans la console, sélectionne ta base, clique sur 'Create read replica', choisis la taille et le AZ, puis laisse AWS s'occuper du reste ; en CLI, c'est une seule commande : aws rds create-db-instance-read-replica --db-instance-identifier ma-replica --source-db-instance-identifier ma-primaire. Le lag est visible dans CloudWatch avec la métrique ReplicaLag, et tu peux créer une alerte si elle dépasse 5 secondes ; tu peux aussi promouvoir la replica en primaire en un clic, mais je te conseille de tester ça dans un environnement de staging avant de le faire en production.
Une fois la replica en place, vérifie le lag avec la commande que je t'ai montrée plus haut, ou avec SHOW SLAVE STATUS pour MySQL. Si le lag dépasse quelques secondes, regarde du côté du réseau ou de la charge de la primaire, mais dans la plupart des cas, c'est négligeable ; j'ai vu des systèmes tourner avec un lag de 50ms sous forte charge. Et n'oublie pas de tester la promotion en cas de panne — sur PostgreSQL, pg_ctl promote ou SELECT pg_promote();, sur MySQL, STOP SLAVE; RESET SLAVE ALL; — c'est le seul moyen d'être sûr que ta stack survivra à une défaillance, et ça prend dix minutes.
Router les requêtes avec ProxySQL ou Pgpool-II
Le read/write splitting, c'est le moment où tu arrêtes de faire tourner ta primaire dans le vide. Tu as tes replicas, il te faut maintenant un routeur. Deux outils dominent : ProxySQL pour MySQL, Pgpool-II pour PostgreSQL. Mon avis ? ProxySQL est plus puissant, Pgpool-II plus simple. Mais les deux font le job.
ProxySQL se configure avec des hostgroups. Tu déclares un hostgroup pour les écritures, un pour les lectures. Ensuite, tu règles les requêtes. Exemple typique :
Ce que j'aime avec ProxySQL, c'est la flexibilité. Tu peux router sur le schéma, l'utilisateur, ou même un commentaire SQL. Tu veux qu'un rapport spécifique passe par la replica ? Ajoute une règle avec un commentaire. Tu veux que les requêtes de session passent par la primaire ? C'est possible aussi. Le tout sans toucher à ton code applicatif.
Côté PostgreSQL, Pgpool-II fait du read/write splitting nativement. Sa config est plus directe :
Là, Pgpool-II envoie les SELECT sur les backends selon leur poids, et le reste sur la primaire. Simple, efficace. Mais attention : Pgpool-II ne fait pas de réécriture de requêtes. Si tu as des requêtes complexes avec des fonctions non déterministes, tu peux te retrouver avec des résultats incohérents. Dans ce cas, force la primaire avec un commentaire :
Mon conseil : commence par Pgpool-II si tu es sous PostgreSQL, passe à ProxySQL si tu as besoin de règles fines. Dans les deux cas, teste ton lag de réplication avant de router. Un lag trop élevé, et tu sers des données périmées sans le savoir. J'ai vu une équipe router tout le trafic vers une replica avec 2 secondes de lag. Le support client a explosé.
Un dernier point : le read/write splitting ne remplace pas un bon cache. Si tu as des requêtes identiques en boucle, mets un cache Redis devant. Le proxy, lui, s'occupe de la répartition. Les deux se complètent.
Surveillance du lag de réplication et promotion du réplica
Le lag de réplication, c'est le premier truc qui te mord quand tu déploies des read replicas. Tu crois que tout va bien, puis un rapport tourne sur une replica en retard et tu obtiens des données périmées. La bonne nouvelle : c'est facile à surveiller, et encore plus facile à alerter.
Pour PostgreSQL, la requête est simple :
Pour MySQL, tu interroges la replica directement :
Ces commandes te donnent le lag en secondes. Mais ne te contente pas de les exécuter à la main. Intègre-les dans un script de monitoring. Chez moi, je fais tourner un petit script toutes les 10 secondes qui pousse la valeur dans Prometheus. Ensuite, une alerte part si le lag dépasse 30 secondes pendant plus de 5 minutes. Pourquoi 30 secondes ? Parce que sur ma stack, les rapports acceptent un retard de 30 secondes max. Au-delà, les chiffres sont faux.
Un exemple concret : j'ai vu une équipe qui surveillait le lag avec un cron qui envoyait un email quand il dépassait 10 secondes. Résultat : des alertes toutes les 5 minutes, et personne ne les lisait. Le seuil était trop bas. Fixe un seuil en fonction de ton besoin métier, pas en fonction de ce que tu peux techniquement atteindre.
Maintenant, la partie qui fait peur : la promotion d'un réplica en primaire. En cas de panne de la primaire, tu dois basculer sur une replica. Sur AWS RDS, c'est un bouton : "Promote read replica". Mais sur une stack auto-gérée, tu fais ça à la main.
Pour PostgreSQL, la procédure est la suivante :
Pour MySQL, c'est un peu plus long :
Mais attention : avant de promouvoir, vérifie que la replica a bien appliqué tous les journaux. Sinon, tu perds des transactions. Sur PostgreSQL, tu peux vérifier avec pg_last_wal_receive_lsn et pg_last_wal_replay_lsn. Si les deux sont égaux, tu es synchrone. Sur MySQL, regarde Seconds_Behind_Master : s'il est à 0, tu es bon.
Une astuce que j'utilise : je ne promeus jamais automatiquement. Je préfère un script qui vérifie le lag, puis promeut, puis met à jour le DNS. Tout ça avec un garde-fou : si le lag est supérieur à 5 secondes, j'abandonne et j'alerte. Pourquoi ? Parce qu'une promotion avec un lag élevé, c'est la garantie de perdre des données.
Enfin, n'oublie pas de reconfigurer tes autres replicas. Si tu avais deux replicas et que tu promeus l'une, l'autre doit se re-pointer sur la nouvelle primaire. C'est le moment où tu te dis que la réplication, c'est pas magique. Mais avec un peu de préparation, ça passe.
Conclusion
Une read replica, c'est le levier le plus sous-estimé pour scaler une base de données. En une après-midi, j'ai intégré une replica PostgreSQL dans une stack existante. Résultat : la latence des requêtes de reporting est passée de 800ms à 50ms, et la primaire est passée de 90% à 30% de CPU.
Pour arriver à ce résultat, tu dois maîtriser quatre choses : la réplication asynchrone, la configuration des réplicas, le routage des requêtes avec ProxySQL ou Pgpool-II, et la surveillance du lag. Chaque étape est simple, mais les ignorer te mènera droit dans le mur. Le lag de réplication, c'est ton ennemi numéro un : si tu ne le surveilles pas, tu vas servir des données périmées à tes utilisateurs.
La promotion d'un réplica en primaire, c'est le moment où tu gagnes ta vie. En cas de panne, tu bascules sur un réplica promu. Mais attention, la réplication asynchrone peut perdre des transactions. Prépare un plan de bascule et teste-le régulièrement.
Mon conseil : commence petit. Une seule replica pour les requêtes non critiques, et tu verras déjà la différence. N'oublie pas de marquer tes requêtes pour le read/write splitting, c'est la clé pour ne pas casser la cohérence. Les read replicas ne résolvent pas tout, mais pour 90% des cas, c'est le meilleur rapport effort/gain.