Replicatie in MySQL bestaat al heel lang en is in de loop der jaren gestaag verbeterd. Het lijkt meer op evolutie dan op revolutie. Dit is volkomen begrijpelijk, aangezien replicatie een belangrijke functie is waarvan velen afhankelijk zijn - het moet werken.
In de laatste MySQL-versies hebben we verbeteringen gezien in de replicatieprestaties door ondersteuning voor het parallel toepassen van transacties. In MySQL 5.6 werd parallellisatie gedaan op schemaniveau - alle transacties die in afzonderlijke schema's zijn uitgevoerd, konden in één keer worden uitgevoerd. Dit was een mooie verbetering voor die workloads met meerdere schema's op een enkele server, en de belasting was min of meer gelijk verdeeld over de schema's.
In MySQL 5.7 is een andere parallellisatiemethode toegevoegd, de zogenaamde "logische klok". Het maakte het mogelijk om een bepaald niveau van gelijktijdigheid op een slaaf te krijgen, zelfs als al je gegevens in een enkel schema zijn opgeslagen. Het was, kort gezegd, gebaseerd op het feit dat sommige transacties samen zouden plaatsvinden vanwege een latentie die door hardware werd toegevoegd. Je zou die latentie zelfs handmatig kunnen toevoegen om een betere parallellisatie op de slaves te krijgen door binlog_group_commit_sync_delay te gebruiken.
Deze oplossing was erg leuk maar niet zonder nadelen. Elke vertraging bij het uitvoeren van een transactie kan uiteindelijk van invloed zijn op gebruikersgerichte delen van de applicatie. Natuurlijk kun je vertragingen instellen binnen een bereik van enkele milliseconden, maar zelfs dan is het extra latentie die de app vertraagt.
Replicatieprestatieverbeteringen in MySQL 8.0
MySQL 8.0, dat vanaf nu (augustus 2017) nog steeds in bèta is, brengt een aantal mooie verbeteringen aan de replicatie. Oorspronkelijk werd het ontwikkeld voor Group Replication (GR), maar aangezien GR reguliere replicatie onder de motorkap gebruikt, profiteerde de "normale" MySQL-replicatie ervan. De verbetering die we noemden, is informatie over het bijhouden van afhankelijkheid die is opgeslagen in het binaire logboek. Wat er gebeurt, is dat MySQL 8.0 nu een manier heeft om informatie op te slaan over welke rijen werden beïnvloed door een bepaalde transactie (de zogenaamde schrijfset), en het vergelijkt schrijfsets van verschillende transacties. Dit maakt het mogelijk om die transacties te identificeren die niet werkten op dezelfde subset van rijen en daarom kunnen deze parallel worden toegepast. Dit kan het mogelijk maken om het parallellisatieniveau meerdere keren te verhogen in vergelijking met de implementatie van MySQL 5.7. Wat u in gedachten moet houden, is dat een slave uiteindelijk een andere weergave van de gegevens zal zien, een weergave die nooit op de master is verschenen. Transacties kunnen namelijk in een andere volgorde worden toegepast dan op de master. Dit zou echter geen probleem moeten zijn. De huidige implementatie van multithreaded replicatie in MySQL 5.7 kan dit probleem ook veroorzaken, tenzij u slave-preserve-commit-order expliciet inschakelt.
Om dit nieuwe gedrag te controleren, een variabele binlog_transaction_dependency_tracking is geïntroduceerd. Het kan drie waarden aannemen:
- COMMIT_ORDER:dit is de standaard, het gebruikt het standaardmechanisme dat beschikbaar is in MySQL 5.7.
- WRITESET:het maakt een betere parallellisatie mogelijk en de master begint de writeset-gegevens op te slaan in een binair logboek.
- WRITESET_SESSION:Dit zorgt ervoor dat transacties op volgorde op de slave worden uitgevoerd en het probleem met een slave die een databasestatus ziet die nooit op de master werd gezien, wordt geëlimineerd. Het vermindert parallellisatie, maar kan nog steeds een betere doorvoer bieden dan de standaardinstellingen.
Benchmark
In juli schreef Vitor Oliveira op mysqlhighavailability.com een bericht waarin hij probeerde de prestaties van nieuwe modi te meten. Hij gebruikte het beste scenario - helemaal geen duurzaamheid, om het verschil tussen oude en nieuwe modi te laten zien. We hebben besloten om dezelfde aanpak te gebruiken, dit keer in een meer realistische opzet:binair logboek ingeschakeld met log_slave_updates. Duurzaamheidsinstellingen werden standaard gelaten (dus sync_binlog=1 - dat is de nieuwe standaard in MySQL 8.0, doublewrite buffer ingeschakeld, InnoDB checksums ingeschakeld etc.) Enige uitzondering in duurzaamheid was innodb_flush_log_at_trx_commit ingesteld op 2.
We gebruikten m4.2xl-instanties, 32G, 8 cores (dus slave_parallel_workers was ingesteld op 8). We gebruikten ook sysbench, het oltp_read_write.lua-script. 16 miljoen rijen in 32 tabellen werden opgeslagen op een gp2-volume van 1000 GB (dat is 3000 IOPS). We hebben de prestaties van alle modi getest voor 1, 2, 4, 8, 16 en 32 gelijktijdige sysbench-verbindingen. Het proces was als volgt:stop slave, voer 100.000 transacties uit, start slave en bereken hoe lang het duurt om de slave-lag te wissen.
Allereerst weten we niet echt wat er gebeurde toen sysbench werd uitgevoerd met slechts 1 thread. Elke test werd vijf keer uitgevoerd na een warming-up. Deze specifieke configuratie is twee keer getest - de resultaten zijn stabiel:single-threaded workload was het snelst. We zullen het verder onderzoeken om te begrijpen wat er is gebeurd.
Afgezien daarvan zijn de rest van de resultaten in lijn met wat we hadden verwacht. COMMIT_ORDER is de langzaamste, vooral voor weinig verkeer, 2-8 threads. WRITESET_SESSION presteert doorgaans beter dan COMMIT_ORDER, maar is langzamer dan WRITESET voor weinig gelijktijdig verkeer.
Hoe kan het mij helpen?
Het eerste voordeel ligt voor de hand:als uw werklast aan de trage kant is, maar uw slaven de neiging hebben om terug te vallen bij replicatie, kunnen ze profiteren van verbeterde replicatieprestaties zodra de master wordt geüpgraded naar 8.0. Twee opmerkingen hier:ten eerste - deze functie is achterwaarts compatibel en 5.7-slaves kunnen er ook van profiteren. Ten tweede - een herinnering dat 8.0 zich nog in de bètafase bevindt, we raden je niet aan om bètasoftware te gebruiken tijdens de productie, hoewel dit in hoge nood een optie is om te testen. Deze functie kan u niet alleen helpen wanneer uw slaven achterblijven. Ze zijn misschien volledig ingehaald, maar wanneer u een nieuwe slaaf maakt of een bestaande opnieuw inricht, loopt die slaaf achter. De mogelijkheid om de "WRITESET"-modus te gebruiken, zal het proces van het inrichten van een nieuwe host veel sneller maken.
Al met al zal deze functie een veel grotere impact hebben dan u misschien denkt. Gezien alle benchmarks die achteruitgang in prestaties laten zien wanneer MySQL verkeer met een lage gelijktijdigheid verwerkt, is alles wat kan helpen om de replicatie in dergelijke omgevingen te versnellen een enorme verbetering.
Als u tussenliggende masters gebruikt, is dit ook een functie om naar te zoeken. Elke tussenliggende master voegt wat serialisatie toe aan de manier waarop transacties worden afgehandeld en uitgevoerd - in de echte wereld zal de werklast op een tussenliggende master bijna altijd minder parallel zijn dan op de master. Het gebruik van schrijfsets om betere parallellisatie mogelijk te maken, verbetert niet alleen de parallellisatie op de tussenliggende master, maar kan ook de parallellisatie op al zijn slaven verbeteren. Het is zelfs mogelijk (hoewel het serieuze tests zou vergen om te controleren of alle onderdelen correct passen) om een 8.0 intermediate master te gebruiken om de replicatieprestaties van uw slaves te verbeteren (houd er rekening mee dat MySQL 5.7-slave writeset-gegevens kan begrijpen en gebruiken, hoewel het kan het niet zelf genereren). Natuurlijk klinkt het repliceren van 8.0 naar 5.7 behoorlijk lastig (en dat is niet alleen omdat 8.0 nog steeds bèta is). Onder bepaalde omstandigheden kan dit werken en het CPU-gebruik op uw 5.7-slaves versnellen.
Andere wijzigingen in MySQL-replicatie
De introductie van schrijfsets, hoewel dit de meest interessante is, is niet de enige wijziging die is doorgevoerd in MySQL-replicatie in MySQL 8.0. Laten we nog enkele andere, ook belangrijke veranderingen doornemen. Als u toevallig een master gebruikt die ouder is dan MySQL 5.0, ondersteunt 8.0 het binaire logformaat niet. We verwachten niet veel van dergelijke opstellingen te zien, maar als je een heel oude MySQL met replicatie gebruikt, is het zeker een moment om te upgraden.
Standaardwaarden zijn gewijzigd om ervoor te zorgen dat replicatie zo crashveilig mogelijk is:master_info_repository en relay_log_info_repository zijn ingesteld op TABLE. Expire_log_days is ook gewijzigd - nu is de standaardwaarde 30. Naast expire_log_days , er is een nieuwe variabele toegevoegd, binlog_expire_log_seconds , wat een fijnmaziger beleid voor het roteren van binlogs mogelijk maakt. Er zijn enkele extra tijdstempels toegevoegd aan het binaire logboek om de waarneembaarheid van de replicatievertraging te verbeteren, door microseconde granulariteit te introduceren.
Dit is in ieder geval geen volledige lijst van wijzigingen en functies met betrekking tot MySQL-replicatie. Als je meer wilt weten, kun je de MySQL-wijzigingslogboeken bekijken. Zorg ervoor dat je ze allemaal hebt bekeken - tot nu toe zijn er functies toegevoegd in alle 8.0-versies.
Zoals u kunt zien, verandert MySQL-replicatie nog steeds en wordt het steeds beter. Zoals we in het begin al zeiden, het moet een langzaam proces zijn, maar het is echt geweldig om te zien wat er in het verschiet ligt. Het is ook leuk om te zien dat het werk voor groepsreplicatie naar beneden druppelt en opnieuw wordt gebruikt in de "gewone" MySQL-replicatie.