Miks võib olla vajalik poolsünkrone replikatsioon?

Tere kõigile. Siin on Vladislav Rodin. Praegu õpetan OTUS-i platvormil kursusi, mis on pühendatud tarkvara arhitektuurile ja kõrge koormusega tarkvara arhitektuurile. Uue kursuse voolu alustamise eelõhtul «Kõrge koormuse arhitekt» otsustasin kirjutada väikese autoriartikli, millega tahan teiega jagada.

Miks võib olla vajalik poolsünkrone replikatsioon?

Sissejuhatus

Kuna HDD-d suudavad teostada vaid umbes 400-700 operatsiooni sekundis (mis ei ole võrreldav tüüpiliste rps-dega, mis langevad kõrge koormusega süsteemi peale), on klassikaline kettabaas arhitektuuri kitsas koht. Seetõttu tuleb erilist tähelepanu pöörata selle salvestuslahenduse skaleerimise mustritele.

Praegu on olemas 2 andmebaasi skaleerimise mustrit: replikatsioon ja shardimine. Shardimine võimaldab skaleerida kirjutamise operatsiooni ja seega vähendada rps-i, mis langeb ühe teie klastriservi peale. Replikatsioon võimaldab teha sama, kuid lugemise operatsioonide puhul. Sellele mustrile on pühendatud ka käesolev artikkel.

Replikatsioon

Kui vaadata replikatsioonile üldiselt, siis see on lihtne asi: teil oli üks server, kus andmed asusid, ja then see server ei suutnud enam andmete lugemise koormusega hakkama saada. Te lisate mõned serverid, sünkroniseerite andmed kõigil serveritel ja kasutaja võib lugeda mis tahes teie klastriservist.

Hoolimata näilisest lihtsusest on olemas mitmeid erinevate rakenduste klassifitseerimise variante:

  • Klastri rollide järgi (master-master või master-slave)
  • Edukohase objektide edastamise järgi (row-based, statement-based või mixed)
  • Sõlmede sünkroniseerimise mehhanismi järgi

Täna käsitleme just 3. punkti.

Kuidas toimuvad tehingu kinnitused

See teema ei ole otseselt seotud replikatsiooniga, selle kohta võiks kirjutada eraldi artikli, kuid kuna tehingu kinnitamise mehhanismi mõistmine on edasise lugemise jaoks hädavajalik, lubage mul meenutada kõige olulisemaid asju. Tehingu kinnitamine toimub 3 etapis:

  1. Tehingu salvestamine andmebaasi päevikusse.
  2. Tehingu rakendamine andmebaasi mootori poolt.
  3. Kliendile kinnituse tagastamine tehingu eduka rakendamise kohta.

Erinevates andmebaasides võivad selle algoritmi osas esineda nüansid: näiteks MySQL-i InnoDB mootoris on 2 žurnali: üks replikatsiooni jaoks (binaarne logi) ja teine ACID-i säilitamiseks (undo/redolog), samas kui PostgreSQL-is on üks žurnal, mis täidab mõlemat funktsiooni (write ahead log = WAL). Kuid ülal on esitatud just üldine kontseptsioon, mis lubab neid nüansse mitte arvesse võtta.

Sünkroonne (sync) replikatsioon

Lisame tehingu commit algoritmi loogika replitseerimise jaoks saadud muudatuste osas:

  1. Tehingu salvestamine andmebaasi päevikusse.
  2. Tehingu rakendamine andmebaasi mootori poolt.
  3. Andmete saatmine kõigile replikatele.
  4. Kõigilt replitelt kinnituse saamine tehingu täitmise kohta.
  5. Kliendile kinnituse tagastamine tehingu eduka rakendamise kohta.

Selle lähenemise korral saame mitmeid puudusi:

  • klient ootab muudatuste rakendamist kõigil replitel.
  • klastris sõlmede arvu suurenedes vähendame tõenäosust, et kirjutamise operatsioon õnnestub.

Kui esimese punktiga on kõik enam-vähem selge, siis teise punkti põhjused tasub selgitada. Kui sünkroonses replikatsioonis ei saa me kinnitust vähemalt ühe sõlme poolt, tühistame tehingu. Seega, suurendades sõlmede arvu klastris, suurendate tõenäosust, et kirjaoperatsioon ebaõnnestub.

Kas saame oodata kinnitust vaid mingi protsendi sõlmedelt, näiteks 51% (kvoorum)? Jah, saame, kuid klassikalises variandis on vajalik kinnituse saamine kõigilt sõlmedelt, kuna just nii suudame tagada andmete täieliku konsistentsuse klastris, mis on sellise replikatsiooni selge eelis.

Asünkroonne (async) replikatsioon

Muudame eelnevat algoritmi. Andmeid replitel saadame me "kunagi hiljem" ja "kunagi hiljem" rakendatakse muutused replitel:

  1. Tehingu salvestamine andmebaasi päevikusse.
  2. Tehingu rakendamine andmebaasi mootori poolt.
  3. Kliendile kinnituse tagastamine tehingu eduka rakendamise kohta.
  4. Andmete saatmine replitale ja nende rakendamine.

See lähenemine viib selleni, et klaster töötab kiiresti, kuna me ei hoia klienti ootamas, kuni andmed jõuavad repliteni ja need ka kinnitatakse.

Kuid tingimus, et andmeid saadetakse replitel "kunagi hiljem", võib viia tehingu kadumiseni, sealhulgas ka kasutajale kinnitatud tehingu kadumiseni, kuna kui andmed ei jõudnud repliteni, saadeti kliendile kinnitamine operatsiooni edukuse kohta, ning kui sõlme, kuhu muudatused jõudsid, HDD purunes, kaotame me tehingu, mis võib põhjustada väga ebameeldivaid tagajärgi.

Pool-sünkroonne (semisync) replikatsioon

Lõpuks jõudsime pool-sünkroonse replikatsiooni juurde. See replikatsiooni tüüp ei ole väga tuntud ega levinud, kuid see on huvitav, kuna suudab ühendata nii sünkroonse kui ka asünkroonse replikatsiooni eelised.

Püüame kombineerida kaht eelmist lähenemist. Me ei hoia klienti kaua kinni, kuid nõuame, et andmed replitseeruksid:

  1. Tehingu salvestamine andmebaasi päevikusse.
  2. Tehingu rakendamine andmebaasi mootori poolt.
  3. Andmete saatmine replikatele.
  4. Kinnituse saamine replikalt muutuste vastuvõtmise kohta (need rakendatakse "mõnes mõttes hiljem").
  5. Kliendile kinnituse tagastamine tehingu eduka rakendamise kohta.

Pange tähele, et sellise algoritmi puhul toimub tehingu kaotus ainult siis, kui z nii muudatuste vastuvõtva sõlme kui ka koopia-sõlme kokkuvarisemine. Sellise vea tõenäosus peetakse väikseks ning need riskid on vastuvõetavad.

Kuid selle lähenemise puhul on võimalik vaimu lugemise risk. Kujutage ette järgmist stsenaariumi: 4. sammil ei saanud me kinnitust üheltki replikalt. Peame selle tehingu tagasi keerama ja kliendile kinnitust mitte andma. Kuna andmed rakendati 2. sammil, tekib ajavahe 2. sammu lõpu ja tehingu tagasi pööramise vahel, mil paralleelsed tehingud võivad näha neid muudatusi, mida andmebaasis ei peaks olema.

Lose-less pool-sünkroonne replikatsioon

Kui veidi mõelda, saame vahetada algoritmi samme omavahel ja lahendada vaimu lugemise probleemi antud stsenaariumis:

  1. Tehingu salvestamine andmebaasi päevikusse.
  2. Andmete saatmine replikale.
  3. Kinnituse saamine replikalt muutuste vastuvõtmise kohta (need rakendatakse "mõnes mõttes hiljem").
  4. Tehingu rakendamine andmebaasi mootori poolt.
  5. Kliendile kinnituse tagastamine tehingu eduka rakendamise kohta.

Nüüd kinnitame muudatused ainult siis, kui need on replitseerunud.

Kokkuvõte

Kuna alati ei ole ideaalset lahendust, on olemas lahenduste kogum, millest igaühel on oma eelised ja puudused ning mis sobib erinevate ülesannete lahendamiseks. See kehtib ka replikatsiooni andmebaaside sünkroniseerimise mehhanismi valiku kohta. Pool-sünkroonse replikatsiooni eeliste kogum on piisavalt muljetavaldav ja huvitav, et seda võiks pidada tähelepanu väärtuseks, hoolimata selle vähesest levikust.

Sellega on kõik. Näeme järgmisel korral kursusel!

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster