Miks võib vaja minna poolsünkroonset replikatsiooni?

Tere kõigile. Vladislav Rodin võtab ühendust. Õpetan praegu OTUS-es tarkvaraarhitektuuri ja kõrge stressiga tarkvaraarhitektuuri kursusi. Uue kursuse voo alguse ootuses "Kõrge koormusega arhitekt" Otsustasin kirjutada lühikese originaalmaterjali, mida tahan teiega jagada.

Miks võib vaja minna poolsünkroonset replikatsiooni?

Sissejuhatus

Kuna HDD suudab teha vaid umbes 400-700 toimingut sekundis (mis on võrreldamatu suure koormusega süsteemi tüüpiliste rps-idega), on klassikaline kettaandmebaas arhitektuuri kitsaskoht. Seetõttu on vaja pöörata erilist tähelepanu selle salvestusruumi skaleerimismustritele.

Praegu on 2 andmebaasi skaleerimise mustrit: replikatsioon ja sharding. Jagamine võimaldab teil kirjutustoimingut skaleerida ja selle tulemusena vähendada rps-i kirjutamise kohta serveri kohta teie klastris. Replikatsioon võimaldab teha sama asja, kuid lugemistoimingutega. See artikkel on sellele mustrile pühendatud.

replikatsioon

Kui vaadata replikatsiooni väga kõrgel tasemel, on see lihtne: teil oli üks server, sellel olid andmed ja siis ei saanud see server enam nende andmete lugemise koormusega toime. Lisate veel paar serverit, sünkroonite andmed kõigis serverites ja kasutaja saab lugeda mis tahes teie klastri serverist.

Vaatamata näilisele lihtsusele on selle skeemi erinevate rakenduste klassifitseerimiseks mitu võimalust:

  • Rollide järgi klastris (ülem-ülem või ülem-alluv)
  • Saadetud objektide järgi (reapõhine, lausepõhine või segatud)
  • Vastavalt sõlmede sünkroniseerimismehhanismile

Täna käsitleme punkti 3.

Kuidas tehingu sooritamine toimub?

See teema ei ole otseselt replikatsiooniga seotud, selle kohta saab kirjutada eraldi artikli, kuid kuna edasine lugemine on ilma tehingute sõlmimise mehhanismist mõistmata mõttetu, tuletan meelde kõige elementaarsemad asjad. Tehingu sidumine toimub kolmes etapis:

  1. Tehingu logimine andmebaasi logisse.
  2. Tehingu kasutamine andmebaasimootoris.
  3. Kliendile kinnituse tagastamine, et tehing on edukalt rakendatud.

Erinevates andmebaasides võib sellel algoritmil olla nüansse: näiteks MySQL andmebaasi InnoDB mootoris on 2 logi: üks replikatsiooni jaoks (binaarlogi) ja teine ​​ACID säilitamiseks (undo/redo log), samas kui PostgreSQL-is on üks logi, mis täidab mõlemat funktsiooni (kirjuta ette logi = WAL). Kuid ülaltoodud on just üldkontseptsioon, mis võimaldab selliseid nüansse mitte arvestada.

Sünkroonne (sünkroonne) replikatsioon

Lisame loogika vastuvõetud muudatuste kopeerimiseks tehingu kinnistamisalgoritmis:

  1. Tehingu logimine andmebaasi logisse.
  2. Tehingu kasutamine andmebaasimootoris.
  3. Andmete saatmine kõigile koopiatele.
  4. Kõigist koopiatest kinnituse saamine, et tehing on nendega lõpule viidud.
  5. Kliendile kinnituse tagastamine, et tehing on edukalt rakendatud.

Selle lähenemisviisiga saame mitmeid puudusi:

  • klient ootab muudatuste rakendamist kõikidele koopiatele.
  • kui sõlmede arv klastris suureneb, väheneb tõenäosus, et kirjutamisoperatsioon õnnestub.

Kui 1. punktiga on kõik enam-vähem selge, siis 2. punkti põhjused on selgitamist väärt. Kui sünkroonse replikatsiooni käigus me vähemalt ühelt sõlmelt vastust ei saa, tühistame tehingu. Seega, suurendades klastris olevate sõlmede arvu, suurendate tõenäosust, et kirjutamisoperatsioon ebaõnnestub.

Kas saame oodata kinnitust ainult teatud protsendilt sõlmedest, näiteks alates 51% (kvoorum)? Jah, saame, kuid klassikalises versioonis on vaja kinnitust kõigist sõlmedest, sest nii saame tagada klastris täieliku andmete järjepidevuse, mis on seda tüüpi replikatsiooni vaieldamatu eelis.

Asünkroonne (asünkroonne) replikatsioon

Muudame eelmist algoritmi. Saadame andmed koopiatele “mõnikord hiljem” ja “mõnikord hiljem” rakendatakse muudatused koopiatele:

  1. Tehingu logimine andmebaasi logisse.
  2. Tehingu kasutamine andmebaasimootoris.
  3. Kliendile kinnituse tagastamine, et tehing on edukalt rakendatud.
  4. Andmete saatmine koopiatele ja nendele muudatuste rakendamine.

Selline lähenemine viib selleni, et klaster töötab kiiresti, sest me ei jäta klienti ootama, kuni andmed jõuavad koopiatesse ja isegi pühenduvad.

Kuid tingimus, et andmed kopeeritakse kunagi hiljem, võib viia tehingu kadumiseni ja kasutaja poolt kinnitatud tehingu kaotamiseni, sest kui andmeid ei olnud aega paljundada, siis kinnitus kliendile. operatsiooni õnnestumise kohta saadeti ja sõlm, kuhu muudatused saabusid, jooksis HDD kokku, kaotame tehingu, mis võib kaasa tuua väga ebameeldivaid tagajärgi.

Poolsünkroonitud replikatsioon

Lõpuks jõuame poolsünkroonse replikatsioonini. Seda tüüpi replikatsioon ei ole väga tuntud või väga levinud, kuid see pakub märkimisväärset huvi, kuna see võib ühendada nii sünkroonse kui ka asünkroonse replikatsiooni eelised.

Proovime ühendada 2 eelmist lähenemist. Me ei hoia klienti kaua, kuid nõuame andmete kopeerimist:

  1. Tehingu logimine andmebaasi logisse.
  2. Tehingu kasutamine andmebaasimootoris.
  3. Andmete saatmine koopiatele.
  4. Koopialt kinnituse saamine, et muudatused on kätte saadud (need rakendatakse “mõnikord hiljem”).
  5. Kliendile kinnituse tagastamine, et tehing on edukalt rakendatud.

Pange tähele, et selle algoritmi puhul tekib tehingute kadu ainult siis, kui nii muudatusi vastuvõttev sõlm kui ka koopiasõlm ebaõnnestuvad. Sellise rikke tõenäosust peetakse väikeseks ja neid riske aktsepteeritakse.

Kuid selle lähenemisviisi korral on võimalik fantoomlugemiste oht. Kujutagem ette järgmist stsenaariumi: toimingus 4 ei saanud me kinnitust üheltki koopialt. Peame selle tehingu tagasi võtma ja mitte kliendile kinnitust tagastama. Kuna andmeid rakendati etapis 2, on 2. etapi lõpu ja tehingu tagasipööramise vahel ajavahe, mille jooksul paralleelsed tehingud näevad muudatusi, mida andmebaasis ei tohiks olla.

Kaotusteta poolsünkroonitud replikatsioon

Kui mõtlete veidi, saate lihtsalt algoritmi samme ümber pöörata ja lahendada fantoomlugemise probleemi järgmise stsenaariumi järgi:

  1. Tehingu logimine andmebaasi logisse.
  2. Replica andmete saatmine.
  3. Koopialt kinnituse saamine, et muudatused on kätte saadud (need rakendatakse “mõnikord hiljem”).
  4. Tehingu kasutamine andmebaasimootoris.
  5. Kliendile kinnituse tagastamine, et tehing on edukalt rakendatud.

Nüüd teeme muudatused ainult siis, kui need on paljundatud.

Väljund

Nagu ikka, ideaalseid lahendusi pole olemas, on lahenduste komplekt, millest igaühel on oma plussid ja miinused ning mis sobivad erinevate probleemide klasside lahendamiseks. See kehtib absoluutselt kopeeritud andmebaasis andmete sünkroonimise mehhanismi valimisel. Poolsünkroonse replikatsiooni eeliste kogum on piisavalt kindel ja huvitav, et seda võib vaatamata madalale levimusele pidada tähelepanu väärivaks.

See on kõik. Kohtumiseni kl muidugi!

Allikas: www.habr.com

Lisa kommentaar