Pse mund të keni nevojë për përsëritje gjysmë sinkron?

Pershendetje te gjitheve. Vladislav Rodin është në kontakt. Aktualisht jap kurse mbi Arkitekturën e Softuerit dhe Arkitekturën e Softuerit me stres të lartë në OTUS. Në pritje të fillimit të një rrjedhe të re kursi "Arkitekt me ngarkesë të lartë" Vendosa të shkruaj një pjesë të shkurtër të materialit origjinal që dua ta ndaj me ju.

Pse mund të keni nevojë për përsëritje gjysmë sinkron?

Paraqitje

Për shkak të faktit se HDD mund të kryejë vetëm rreth 400-700 operacione në sekondë (që është e pakrahasueshme me rps tipike në një sistem me ngarkesë të lartë), baza e të dhënave klasike të diskut është pengesa e arkitekturës. Prandaj, është e nevojshme t'i kushtohet vëmendje e veçantë modeleve të shkallëzimit të kësaj ruajtjeje.

Aktualisht, ekzistojnë 2 modele të shkallëzimit të bazës së të dhënave: përsëritja dhe copëtimi. Sharding ju lejon të shkallëzoni operacionin e shkrimit dhe, si rezultat, të zvogëloni rps për shkrim për server në grupin tuaj. Replikimi ju lejon të bëni të njëjtën gjë, por me operacione leximi. Ky artikull i kushtohet pikërisht këtij modeli.

Replikimi

Nëse e shikoni replikimin në një nivel shumë të lartë, është një gjë e thjeshtë: kishit një server, kishte të dhëna në të dhe më pas ky server nuk mund të përballonte më ngarkesën e leximit të këtyre të dhënave. Ju shtoni disa serverë të tjerë, sinkronizoni të dhënat në të gjithë serverët dhe përdoruesi mund të lexojë nga çdo server në grupin tuaj.

Megjithë thjeshtësinë e tij të dukshme, ekzistojnë disa opsione për klasifikimin e zbatimeve të ndryshme të kësaj skeme:

  • Sipas roleve në grup (mjeshtër-zot ose mjeshtër-skllav)
  • Sipas objekteve të dërguara (të bazuara në rresht, të bazuar në deklarata ose të përziera)
  • Sipas mekanizmit të sinkronizimit të nyjeve

Sot do të merremi me pikën 3.

Si ndodh një detyrim transaksioni?

Kjo temë nuk lidhet drejtpërdrejt me përsëritjen; ​​mund të shkruhet një artikull i veçantë, por meqenëse leximi i mëtejshëm është i padobishëm pa kuptuar mekanizmin e kryerjes së transaksionit, më lejoni t'ju kujtoj gjërat më themelore. Një angazhim transaksioni ndodh në 3 faza:

  1. Regjistrimi i një transaksioni në regjistrin e bazës së të dhënave.
  2. Përdorimi i një transaksioni në një motor të dhënash.
  3. Kthimi i konfirmimit te klienti se transaksioni është zbatuar me sukses.

Në baza të ndryshme të dhënash, ky algoritëm mund të ketë nuanca: për shembull, në motorin InnoDB të bazës së të dhënave MySQL ka 2 regjistra: një për replikim (log binar), dhe tjetri për mirëmbajtjen e ACID (zhbërë/ribërë log), ndërsa në PostgreSQL ekziston një regjistër që kryen të dy funksionet (shkruaj log përpara = WAL). Por ajo që është paraqitur më sipër është pikërisht koncepti i përgjithshëm, i cili lejon që nuanca të tilla të mos merren parasysh.

Replikim sinkron (sinkronik).

Le të shtojmë logjikën për të përsëritur ndryshimet e marra në algoritmin e kryerjes së transaksionit:

  1. Regjistrimi i një transaksioni në regjistrin e bazës së të dhënave.
  2. Përdorimi i një transaksioni në një motor të dhënash.
  3. Dërgimi i të dhënave për të gjitha kopjet.
  4. Marrja e konfirmimit nga të gjitha kopjet se një transaksion është kryer mbi to.
  5. Kthimi i konfirmimit te klienti se transaksioni është zbatuar me sukses.

Me këtë qasje kemi një sërë disavantazhesh:

  • klienti pret që ndryshimet të zbatohen në të gjitha kopjet.
  • ndërsa numri i nyjeve në grup rritet, ne ulim gjasat që operacioni i shkrimit të jetë i suksesshëm.

Nëse gjithçka është pak a shumë e qartë me pikën 1, atëherë arsyet për pikën e dytë ia vlen të shpjegohen. Nëse gjatë replikimit sinkron nuk marrim përgjigje nga të paktën një nyje, ne e kthejmë transaksionin prapa. Kështu, duke rritur numrin e nyjeve në grup, ju rritni gjasat që një operacion shkrimi të dështojë.

A mund të presim për konfirmim vetëm nga një përqindje e caktuar e nyjeve, për shembull, nga 51% (kuorumi)? Po, mundemi, por në versionin klasik kërkohet konfirmimi nga të gjitha nyjet, sepse kështu mund të sigurojmë konsistencë të plotë të të dhënave në grup, që është një avantazh i padyshimtë i këtij lloji të replikimit.

Replikimi asinkron (asinkron).

Le të modifikojmë algoritmin e mëparshëm. Ne do t'u dërgojmë të dhëna kopjeve "disa më vonë" dhe "disa më vonë" ndryshimet do të zbatohen në kopjet:

  1. Regjistrimi i një transaksioni në regjistrin e bazës së të dhënave.
  2. Përdorimi i një transaksioni në një motor të dhënash.
  3. Kthimi i konfirmimit te klienti se transaksioni është zbatuar me sukses.
  4. Dërgimi i të dhënave në kopje dhe aplikimi i ndryshimeve në to.

Kjo qasje çon në faktin se grupi funksionon shpejt, sepse ne nuk e mbajmë klientin në pritje që të dhënat të arrijnë në kopje dhe madje të angazhohen.

Por kushti i hedhjes së të dhënave në kopje "disa më vonë" mund të çojë në humbjen e një transaksioni dhe në humbjen e një transaksioni të konfirmuar nga përdoruesi, sepse nëse të dhënat nuk kishin kohë për t'u përsëritur, një konfirmim për klientin. në lidhje me suksesin e operacionit u dërgua, dhe nyja në të cilën mbërritën ndryshimet u rrëzua HDD, ne humbasim transaksionin, gjë që mund të çojë në pasoja shumë të pakëndshme.

Përsëritje gjysmësinkronike

Më në fund arrijmë te replikimi gjysmësinkron. Ky lloj replikimi nuk është shumë i njohur ose shumë i zakonshëm, por është me interes të konsiderueshëm sepse mund të kombinojë avantazhet e replikimit sinkron dhe asinkron.

Le të përpiqemi të kombinojmë 2 qasjet e mëparshme. Ne nuk do ta mbajmë klientin për një kohë të gjatë, por do të kërkojmë që të dhënat të përsëriten:

  1. Regjistrimi i një transaksioni në regjistrin e bazës së të dhënave.
  2. Përdorimi i një transaksioni në një motor të dhënash.
  3. Dërgimi i të dhënave në kopje.
  4. Marrja e konfirmimit nga kopja se ndryshimet janë marrë (ato do të aplikohen "disa më vonë").
  5. Kthimi i konfirmimit te klienti se transaksioni është zbatuar me sukses.

Ju lutemi vini re se me këtë algoritëm, humbja e transaksionit ndodh vetëm nëse si nyja që merr ndryshimet, ashtu edhe nyja replika dështojnë. Probabiliteti i një dështimi të tillë konsiderohet i ulët dhe këto rreziqe pranohen.

Por me këtë qasje ekziston rreziku i leximit fantazmë. Le të imagjinojmë skenarin e mëposhtëm: në hapin 4, nuk morëm konfirmim nga asnjë kopje. Ne duhet ta rikthejmë këtë transaksion dhe të mos kthejmë një konfirmim te klienti. Meqenëse të dhënat u aplikuan në hapin 2, ekziston një hendek kohor midis fundit të hapit 2 dhe rikthimit të transaksionit, gjatë të cilit transaksionet paralele mund të shohin ndryshime që nuk duhet të jenë në bazën e të dhënave.

Përsëritje gjysmësinkronike pa humbje

Nëse mendoni pak, thjesht mund të ndryshoni hapat e algoritmit dhe të rregulloni problemin e leximeve fantazmë në këtë skenar:

  1. Regjistrimi i një transaksioni në regjistrin e bazës së të dhënave.
  2. Dërgimi i të dhënave të kopjeve.
  3. Marrja e konfirmimit nga kopja se ndryshimet janë marrë (ato do të aplikohen "disa më vonë").
  4. Përdorimi i një transaksioni në një motor të dhënash.
  5. Kthimi i konfirmimit te klienti se transaksioni është zbatuar me sukses.

Tani ne kryejmë ndryshime vetëm nëse ato janë përsëritur.

Prodhim

Si gjithmonë, nuk ka zgjidhje ideale; ekziston një grup zgjidhjesh, secila prej të cilave ka avantazhet dhe disavantazhet e veta dhe është e përshtatshme për zgjidhjen e klasave të ndryshme të problemeve. Kjo është absolutisht e vërtetë për zgjedhjen e një mekanizmi për sinkronizimin e të dhënave në një bazë të dhënash të përsëritur. Grupi i avantazheve që ka replikimi gjysmësinkron është mjaftueshëm solid dhe interesant saqë mund të konsiderohet i denjë për vëmendje, pavarësisht nga përhapja e tij e ulët.

Kjo eshte e gjitha. Shihemi në kurs!

Burimi: www.habr.com

Shto një koment