Håndtering af store transaktioner var altid et smertepunkt i Galera Cluster. Den måde, hvorpå Galera-skrivesæt-certificering fungerer, forårsager problemer, når transaktioner er lange, eller når en enkelt række ofte ændres på flere noder. Som følge heraf skal transaktioner rulles tilbage og prøves igen, hvilket forårsager præstationsfald. Heldigvis er dette problem blevet løst i Galera 4, en ny udgivelse af Galera fra Codership. Dette bibliotek bruges i MariaDB 10.4, så installation af MariaDB 10.4 er den nemmeste måde at teste de nyligt introducerede funktioner på. I dette blogindlæg vil vi tage et kig på, hvordan streaming-replikeringen kan bruges til at afhjælpe problemer, som plejede at være et standardproblem i tidligere Galera-versioner.
Vi vil bruge tre noder af MariaDB Galera cluster version 10.4.6, som kommer med Galera version af 26.4.2.
MariaDB [(none)]> show global status like 'wsrep_provider%';
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <[email protected]> |
| wsrep_provider_version | 26.4.2(r4498) |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.001 sec)
Der er tre hovedsmertepunkter, som streaming replikation er beregnet til at håndtere:
- Lange transaktioner
- Store transaktioner
- Hot spots i tabeller
Lad os overveje dem én efter én og se, hvordan streaming-replikering kan hjælpe os med at håndtere dem, men lad os først fokusere på skrivesæt-certificeringen - den grundlæggende årsag til, at disse problemer dukker op.
Writeset-certificering i Galera Cluster
Galera-klyngen består af flere skrivbare noder. Hver transaktion, der udføres på Galera-klyngen, danner et skrivesæt. Hvert skrivesæt skal sendes til alle noder i klyngen for certificering - en proces, der sikrer, at alle noder kan anvende en given transaktion. Skrivesæt skal udføres på alle klyngens noder, så hvis der er nogen konflikt, kan transaktionen ikke udføres. Hvad er typiske årsager til, at transaktionen ikke kan forpligtes? Nå, de tre punkter, vi nævnte tidligere:
- Lange transaktioner - længere tid tager transaktionen, mere sandsynligt er det, at en anden node i mellemtiden vil udføre opdateringer, som til sidst vil være i konflikt med skrivesættet og forhindre det i at bestå certificeringen
- Store transaktioner - for det første er store transaktioner også længere end små, så det udløser det første problem. Andet problem, strengt relateret til de store transaktioner, er omfanget af ændringerne. Flere rækker vil blive opdateret, mere sandsynligt er det, at noget skrivning på en anden knude vil resultere i en konflikt, og hele transaktionen skal rulles tilbage.
- Hot spots i tabeller - mere sandsynligt vil en given række blive opdateret, mere sandsynligt vil en sådan opdatering ske samtidigt på flere noder, hvilket resulterer i, at nogle af transaktionerne skal rulles tilbage
Hovedproblemet her er, at Galera ikke introducerer nogen låsning på andre noder end den oprindelige node, hvor transaktionen blev åbnet. Certificeringsprocessen er baseret på et håb om, at hvis en node kunne udføre en transaktion, skulle andre også være i stand til at gøre det. Det er sandt, men som vi diskuterede, er der hjørnetilfælde, hvor sandsynligheden for, at dette sker, er væsentligt reduceret.
I Galera 4, med streaming-replikering, er adfærden ændret, og alle låse bliver taget i alle noderne. Transaktioner vil blive opdelt i dele, og hver del vil blive certificeret på alle noder. Efter vellykket certificering vil rækker blive låst på alle noder i klyngen. Der er et par variable, der styrer, hvordan dette præcist gøres - wsrep_trx_fragment_size og wsrep_trx_fragment_unit definerer, hvor stort fragmentet skal være, og hvordan det skal defineres. Det er meget finkornet kontrol:du kan definere fragmentenheder som bytes, sætninger eller rækker, hvilket gør det muligt at køre certificeringen for hver række, der er ændret i transaktionen. Lad os tage et kig på, hvordan du kan drage fordel af streaming-replikeringen i det virkelige liv.
Arbejde med streaming-replikeringen
Lad os overveje følgende scenarie. Vi skal køre en transaktion, der tager mindst 30 sekunder:
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Så, mens den kører, vil vi udføre SQL, der rører lignende rækker. Dette vil blive udført på en anden node:
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Hvad ville resultatet blive?
Den første transaktion rulles tilbage, så snart den anden er udført:
MariaDB [sbtest]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Query OK, 0 rows affected (0.001 sec)
Query OK, 667 rows affected (0.020 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.010 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.009 sec)
Rows matched: 667 Changed: 667 Warnings: 0
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
Query OK, 0 rows affected (0.001 sec)
Transaktionen på den anden node lykkedes:
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (0.002 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.004 sec)
Hvad vi kan gøre for at undgå det, er at bruge streaming-replikering til den første transaktion. Vi vil bede Galera om at certificere hver rækkeændring:
MariaDB [sbtest]> BEGIN; SET SESSION wsrep_trx_fragment_size=1 ; SET SESSION wsrep_trx_fragment_unit='rows' ; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT; SET SESSION wsrep_trx_fragment_size=0;
Query OK, 0 rows affected (0.001 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 667 rows affected (1.757 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.708 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.685 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Som du kan se, fungerede det denne gang fint. På den anden node:
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (33.942 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.026 sec)
Hvad der er interessant, kan du se, at UPDATEN tog næsten 34 sekunder at udføre - dette var forårsaget af det faktum, at den indledende transaktion, gennem streaming-replikeringen, låste alle ændrede rækker på alle noderne, og vores anden transaktion måtte vente til den første til at fuldføre, selvom begge transaktioner blev udført på forskellige noder.
Dette er dybest set det, når det kommer til streaming-replikeringen. Afhængigt af kravene og trafikken kan du bruge det på en mindre streng måde - vi certificerede hver række, men du kan ændre det til hver n'te række eller hver erklæring. Du kan endda bestemme mængden af data, der skal certificeres. Dette burde være nok til at matche kravene i dit miljø.
Der er et par ting mere, som vi gerne vil have dig til at huske og huske. Først og fremmest er streaming replikering på ingen måde en løsning, der bør bruges som standard. Dette er grunden til, at det som standard er deaktiveret. Den anbefalede brugssag er manuelt at beslutte om transaktioner, der ville drage fordel af streaming-replikeringen og aktivere den på sessionsniveau. Dette er grunden til, at vores eksempler slutter med:
SET SESSION wsrep_trx_fragment_size=0;
Denne erklæring (indstiller wsrep_trx_fragment_size til 0) deaktiverer streamingreplikering for den aktuelle session.
En anden ting, der er værd at huske - hvis du tilfældigvis bruger streaming-replikering, vil den bruge 'wsrep_streaming_log'-tabellen i 'mysql'-skemaet til vedvarende at gemme de data, der streamer. Ved at bruge denne tabel kan du få en idé om de data, der overføres på tværs af klyngen ved hjælp af streamingreplikering.
Til sidst forestillingen. Dette er også en af grundene til, at du ikke ønsker at bruge streaming replikering hele tiden. Hovedårsagen til det er låsning - med streaming-replikering skal du anskaffe rækkelåse på alle noderne. Dette tager tid at få låsene, og hvis du skulle rulle transaktionen tilbage, vil det også lægge pres på alle noder for at udføre tilbagerulningen. Vi kørte en meget hurtig test af den ydeevnepåvirkning, som streamingreplikeringen har. Miljøet er strengt taget en test, så antag ikke, at disse resultater er de samme på hardware i produktionskvalitet, det er mere op til dig at se, hvad indvirkningen kan være.
Vi testede fire scenarier:
- Baseline, sæt global wsrep_trx_fragment_size=0;
- set global wsrep_trx_fragment_unit='rows'; sæt global wsrep_trx_fragment_size=1;
- sæt globale wsrep_trx_fragment_unit='udsagn'; sæt global wsrep_trx_fragment_size=1;
- sæt globale wsrep_trx_fragment_unit='udsagn'; sæt global wsrep_trx_fragment_size=5;
Vi brugte sysbench r/w test:
sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=4 --events=0 --time=300 --mysql-host=10.0.0.141 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=3306 --tables=32 --report-interval=1 --skip-trx=off --table-size=100000 --db-ps-mode=disable run
Resultaterne er:
- Transaktioner:82,91 pr. sek., forespørgsler:1658,27 pr. sek. (100 %)
- Transaktioner:54,72 pr. sek., forespørgsler:1094,43 pr. sek. (66 %)
- Transaktioner:54,76 pr. sek., forespørgsler:1095,18 pr. sek. (66 %)
- Transaktioner:70,93 pr. sek., forespørgsler:1418,55 pr. sek. (86 %)
Som du kan se, er virkningen betydelig, ydeevnen falder endda med 33%.
Vi håber, du fandt dette blogindlæg informativt, og det gav dig nogle indsigter i streamingreplikeringen, der følger med Galera 4 og MariaDB 10.4. Vi forsøgte at dække brugstilfælde og potentielle ulemper i forbindelse med denne nye teknologi.