Séparez votre réplique de lecture avant que les rapports ne freinent l'achat
L'affirmation Quand la même base de données sert à la fois vos transactions clients et vos rapports internes, les deux se disputent les mêmes ressources, et la lourde requête de ra...
L'affirmation
Quand la même base de données sert à la fois vos transactions clients et vos rapports internes, les deux se disputent les mêmes ressources, et la lourde requête de rapport que quelqu'un lance un mardi après-midi peut ralentir — ou bloquer — l'achat qui paie vos factures. Une réplique de lecture sépare ces charges pour qu'aucun rapport, aucune requête d'analytique, aucune exportation de données ne puisse dégrader les transactions qui comptent, et pour la plupart des entreprises en croissance, c'est le point où une base unique cesse de suffire.
Pourquoi une base pour tout finit par faire mal
Une base unique faisant les deux travaux fonctionne bien jusqu'à ce que la charge de rapports croisse assez pour nuire à la charge transactionnelle, et l'interférence est pire qu'un simple ralentissement. Une grande requête analytique — sommer une année de commandes, joindre plusieurs grandes tables pour un tableau de bord — consomme processeur, mémoire et bande passante de disque pendant qu'elle tourne, et elle peut retenir des verrous ou remplir le cache de données que les requêtes transactionnelles doivent ensuite recharger. Le résultat est que l'achat de votre client, qui doit être rapide et fiable, se dispute désormais avec un rapport interne que personne ne verrait d'inconvénient à attendre — et c'est le client, non le rapport, qui ressent le délai.
Les deux charges ont des formes opposées, ce qui est la racine du conflit. Le travail transactionnel, ce sont de nombreuses petites requêtes rapides qui doivent être promptes et cohérentes. Le travail analytique, ce sont quelques grandes requêtes lentes qui touchent d'énormes quantités de données. Les exécuter sur le même serveur signifie que régler pour l'une compromet l'autre, et la lourde affame par intermittence la légère exactement aux moments — les après-midis chargés — où les deux sont les plus actives.
Ce que fait une réplique de lecture
Une réplique de lecture est une seconde copie de votre base qui reste continuellement synchronisée avec la principale, recevant un flux de changements pour détenir les mêmes données quelques instants en retard. Vous dirigez toutes les requêtes de rapport, d'analytique et d'exportation vers la réplique, et la principale est laissée à ne faire que le travail transactionnel :
# principale : prend toutes les ecritures et les lectures transactionnelles rapides
# replique : prend les lourdes requetes de rapport en lecture seule
# routage de l'application :
write_db = connect(PRIMARY) # commandes, mises a jour, achat
report_db = connect(REPLICA) # tableaux de bord, exportations, analytique
Désormais, le rapport de revenus sur une année tourne sur la réplique, utilisant le processeur et le cache de la réplique, et aussi lourd soit-il, il ne peut pas ralentir l'achat, car l'achat est sur une machine entièrement différente. Les charges sont physiquement séparées, de sorte que la concurrence qui causait le ralentissement n'existe simplement plus.
La seule propriété à comprendre : le retard de réplication
Une réplique est légèrement en retard sur la principale — d'ordinaire de millisecondes, parfois plus sous charge — car les changements prennent un instant à voyager et à s'appliquer. Ce retard est la seule chose autour de laquelle vous devez concevoir, et il dicte une règle simple : lisez de la réplique seulement là où être un instant périmé est acceptable, et lisez de la principale là où ça ne l'est pas.
Pour les rapports, l'analytique et les exportations, quelques secondes de retard sont complètement sans importance — un tableau de bord montrant des données d'il y a dix secondes convient. Mais il y a un piège précis : lire de la réplique vos propres données à peine écrites. Si un utilisateur met à jour son profil et que la page suivante lit de la réplique avant que le changement ne soit répliqué, il voit ses anciennes données et conclut que la sauvegarde a échoué. La règle est qu'une lecture qui doit refléter une écriture qui vient d'arriver va à la principale ; tout le reste peut aller à la réplique.
save_profile(primary, changes) # ecrire sur la principale
show_profile(primary, user) # lecture apres ecriture : principale aussi
generate_monthly_report(replica) # retard sans importance : replique
L'avantage de basculement que vous obtenez gratuitement
Une réplique de lecture achetée pour la performance améliore aussi votre reprise après sinistre, car une copie continuellement synchronisée de votre base est l'essentiel de ce qu'il faut pour survivre à la défaillance de la principale. Si la principale est perdue, la réplique — détenant déjà vos données, quelques instants en retard — peut être promue pour devenir la nouvelle principale, transformant ce qui aurait été une longue panne de restauration en un basculement bien plus court. Cela ne remplace pas les sauvegardes, qui protègent contre la corruption de données et les erreurs qu'une réplique copierait fidèlement, mais cela ajoute une voie de reprise rapide pour le cas où le matériel de la principale échoue simplement, et cette voie vient comme effet secondaire de la réplique ajoutée pour la séparation des charges.
Quand vous en avez besoin, et quand non
Une réplique de lecture n'est pas gratuite — c'est une seconde instance de base à exploiter et à payer, et elle ajoute la considération lecture-après-écriture à votre application — elle devrait donc être adoptée quand les charges entrent réellement en conflit, non préventivement. Les signaux que vous avez atteint ce point sont concrets : des requêtes transactionnelles ralentissant mesurablement quand les rapports tournent, des requêtes de rapport que vous craignez d'exécuter en heures ouvrables, ou une principale dont la charge est dominée par une poignée de lourdes requêtes analytiques. Si votre base gère confortablement les deux charges avec de la marge, une réplique est prématurée. Si vous planifiez les rapports au milieu de la nuit pour éviter de ralentir le site, les charges sont déjà en conflit et la réplique est en retard.
Comment migrer
Ajouter une réplique est habituellement bien pris en charge par les services de base gérés et simple à dresser. Le travail n'est pas la réplique elle-même mais le changement d'application : repérer quelles lectures peuvent aller sans risque à la réplique et les y router, tout en gardant les écritures et les lectures-après-écriture sur la principale. Commencez par déplacer les requêtes les plus lourdes et les plus clairement tolérantes au retard — les rapports et exportations planifiés — vers la réplique, puisque ce sont celles qui causent la contention et les plus sûres à déplacer. Ce seul changement retire souvent la pression qui vous inquiétait au sujet de la principale, et il le fait en garantissant que les rapports ne pourront plus jamais ralentir l'achat, car les deux ne partagent plus de machine.