NewSQL = NoSQL+ACID

NewSQL = NoSQL+ACID
Vēl nesen Odnoklassniki uzglabāja aptuveni 50 TB datu, kas tika apstrādāti reāllaikā SQL serverÄ«. Šādam apjomam ir gandrÄ«z neiespējami nodroÅ”ināt ātru un uzticamu un pat datu centra kļūmju tolerantu piekļuvi, izmantojot SQL DBVS. Parasti Ŕādos gadÄ«jumos tiek izmantota viena no NoSQL krātuvēm, taču ne visu var pārsÅ«tÄ«t uz NoSQL: dažām entÄ«tijām ir nepiecieÅ”amas ACID darÄ«jumu garantijas.

Tas lika mums izmantot NewSQL krātuvi, tas ir, DBVS, kas nodroÅ”ina NoSQL sistēmu kļūdu toleranci, mērogojamÄ«bu un veiktspēju, bet tajā paŔā laikā saglabā klasiskajām sistēmām pazÄ«stamās ACID garantijas. Å Ä«s jaunās klases industriālo sistēmu ir maz strādājoÅ”u, tāpēc paÅ”i ieviesām Ŕādu sistēmu un nodevām komerciālā ekspluatācijā.

Kā tas darbojas un kas notika - lasiet zem griezuma.

Å odien Odnoklassniki ikmēneÅ”a auditorija ir vairāk nekā 70 miljoni unikālo apmeklētāju. Mēs Esam pirmajā pieciniekā lielākajiem sociālajiem tÄ«kliem pasaulē un starp divdesmit vietnēm, kurās lietotāji pavada visvairāk laika. OK infrastruktÅ«ra apstrādā ļoti lielas slodzes: vairāk nekā miljons HTTP pieprasÄ«jumu sekundē katrā priekÅ”pusē. Vairāk nekā 8000 vienÄ«bu serveru flotes daļas atrodas tuvu viena otrai - četros Maskavas datu centros, kas pieļauj tÄ«kla latentumu starp tiem mazāku par 1 ms.

Mēs izmantojam Cassandra kopÅ” 2010. gada, sākot ar versiju 0.6. MÅ«sdienās darbojas vairāki desmiti kopu. Ātrākais klasteris apstrādā vairāk nekā 4 miljonus operāciju sekundē, bet lielākais glabā 260 TB.

Tomēr tās visas ir parastās NoSQL kopas, ko izmanto glabāŔanai vāji koordinēts datus. Mēs vēlējāmies aizstāt galveno konsekvento krātuvi Microsoft SQL Server, kas tika izmantota kopÅ” Odnoklassniki dibināŔanas. Krātuve sastāvēja no vairāk nekā 300 SQL Server Standard Edition maŔīnām, kas saturēja 50 TB datu - biznesa vienÄ«bas. Å ie dati tiek modificēti kā daļa no ACID darÄ«jumiem un ir nepiecieÅ”ami augsta konsistence.

Lai izplatÄ«tu datus pa SQL Server mezgliem, mēs izmantojām gan vertikālo, gan horizontālo sadalÄ«Å”ana (skaldÄ«Å”ana). Vēsturiski mēs izmantojām vienkārÅ”u datu sadalÄ«Å”anas shēmu: katra entÄ«tija bija saistÄ«ta ar marÄ·ieri ā€” entÄ«tijas ID funkciju. EntÄ«tijas ar vienu un to paÅ”u pilnvaru tika ievietotas tajā paŔā SQL serverÄ«. Galvenās un detaļas attiecÄ«bas tika ieviestas tā, lai galvenā un pakārtotā ieraksta marÄ·ieri vienmēr sakristu un atrastos vienā serverÄ«. Sociālajā tÄ«klā gandrÄ«z visi ieraksti tiek Ä£enerēti lietotāja vārdā ā€“ tas nozÄ«mē, ka visi lietotāja dati vienas funkcionālās apakÅ”sistēmas ietvaros tiek glabāti vienā serverÄ«. Tas nozÄ«mē, ka biznesa darÄ«jums gandrÄ«z vienmēr ietvēra tabulas no viena SQL servera, kas ļāva nodroÅ”ināt datu konsekvenci, izmantojot lokālās ACID transakcijas, neizmantojot lēns un neuzticams izplatÄ«ti ACID darÄ«jumi.

Pateicoties sadalīŔanai un SQL paātrināŔanai:

  • Mēs neizmantojam sveŔās atslēgas ierobežojumus, jo sadalot entÄ«tijas ID var atrasties citā serverÄ«.
  • Mēs neizmantojam saglabātās procedÅ«ras un trigerus DBVS CPU papildu slodzes dēļ.
  • Mēs neizmantojam JOIN visu iepriekÅ”minēto un daudzu nejauÅ”u nolasÄ«jumu dēļ no diska.
  • Ārpus darÄ«juma mēs izmantojam Read Uncommitted izolācijas lÄ«meni, lai samazinātu strupceļus.
  • Veicam tikai Ä«sus darÄ«jumus (vidēji Ä«sākus par 100 ms).
  • Mēs neizmantojam vairāku rindu UPDATE un DELETE lielā strupceļu skaita dēļ - vienlaikus atjaunojam tikai vienu ierakstu.
  • Mēs vienmēr veicam vaicājumus tikai indeksiem ā€“ vaicājums ar pilnu tabulu skenÄ“Å”anas plānu mums nozÄ«mē datu bāzes pārslogoÅ”anu un tās neveiksmi.

Šīs darbības ļāva mums izspiest gandrīz maksimālu veiktspēju no SQL serveriem. Tomēr problēmas kļuva arvien vairāk un vairāk. Apskatīsim tos.

Problēmas ar SQL

  • Tā kā mēs izmantojām paÅ”u rakstÄ«tu sadalÄ«Å”anu, administratori manuāli pievienoja jaunus fragmentus. Visu Å”o laiku mērogojamās datu kopijas neapkalpoja pieprasÄ«jumus.
  • Pieaugot ierakstu skaitam tabulā, ievietoÅ”anas un modifikācijas ātrums samazinās; pievienojot indeksus esoÅ”ai tabulai, ātrums samazinās par koeficientu; indeksu izveide un atkārtota izveide notiek ar dÄ«kstāvi.
  • Neliels Windows for SQL Server skaits ražoÅ”anā apgrÅ«tina infrastruktÅ«ras pārvaldÄ«bu

Bet galvenā problēma ir

kļūdu tolerance

Klasiskajam SQL serverim ir slikta kļūdu tolerance. Pieņemsim, ka jums ir tikai viens datu bāzes serveris, un tas neizdodas reizi trijos gados. Å ajā laikā vietne nedarbojas uz 20 minÅ«tēm, kas ir pieņemami. Ja jums ir 64 serveri, vietne nedarbojas reizi trÄ«s nedēļās. Un, ja jums ir 200 serveri, vietne nedarbojas katru nedēļu. Tā ir problēma.

Ko var darīt, lai uzlabotu SQL servera kļūdu toleranci? Wikipedia aicina mūs veidot ļoti pieejams klasteris: kur jebkuras sastāvdaļas atteices gadījumā ir rezerves.

Tas prasa dārgu iekārtu parku: daudzas dublÄ“Å”anās, optiskā Ŕķiedra, kopÄ«ga krātuve, un rezerves iekļauÅ”ana nedarbojas droÅ”i: aptuveni 10% pārslēgÅ”anu beidzas ar rezerves mezgla atteici kā vilcienam aiz galvenā mezgla.

Bet galvenais Ŕāda ļoti pieejamā klastera trūkums ir nulles pieejamība, ja datu centrs, kurā tas atrodas, nedarbojas. Odnoklassniki ir četri datu centri, un mums ir jānodroŔina darbība pilnīgas kļūmes gadījumā vienā no tiem.

Å im nolÅ«kam mēs varētu izmantot Multi-Master SQL serverÄ« iebÅ«vēta replikācija. Å is risinājums ir daudz dārgāks programmatÅ«ras izmaksu dēļ un cieÅ” no labi zināmām problēmām ar replikāciju - neparedzamu darÄ«jumu aizkavi ar sinhrono replikāciju un replikāciju (un lÄ«dz ar to zaudēto modifikāciju) pielietoÅ”anas aizkavÄ“Å”anos ar asinhrono replikāciju. Noklusētais manuāla konfliktu risināŔana padara Å”o iespēju mums pilnÄ«gi nepiemērojamu.

Visām Ŕīm problēmām bija nepiecieÅ”ams radikāls risinājums, un mēs sākām tās detalizēti analizēt. Å eit jāiepazÄ«stas ar to, ar ko SQL Server galvenokārt nodarbojas ā€“ ar transakcijām.

VienkārŔs darījums

ApskatÄ«sim vienkārŔāko darÄ«jumu no lietiŔķā SQL programmētāja viedokļa: fotoattēla pievienoÅ”ana albumam. Albumi un fotogrāfijas tiek glabāti dažādās plāksnēs. Albumam ir publisks foto skaitÄ«tājs. Tad Ŕāds darÄ«jums tiek sadalÄ«ts Ŕādos posmos:

  1. Mēs bloķējam albumu ar atslēgu.
  2. Izveidojiet ierakstu fotoattēlu tabulā.
  3. Ja fotoattēlam ir publisks statuss, pievienojiet albumam publisku fotoattēlu skaitītāju, atjauniniet ierakstu un veiciet darījumu.

Vai pseidokodā:

TX.start("Albums", id);
Album album = albums.lock(id);
Photo photo = photos.create(ā€¦);

if (photo.status == PUBLIC ) {
    album.incPublicPhotosCount();
}
album.update();

TX.commit();

Mēs redzam, ka visizplatÄ«tākais biznesa darÄ«juma scenārijs ir datu nolasÄ«Å”ana no datu bāzes lietojumprogrammu servera atmiņā, kaut kas jāmaina un jaunās vērtÄ«bas tiek saglabātas atpakaļ datu bāzē. Parasti Ŕādā darÄ«jumā mēs atjaunojam vairākas entÄ«tijas, vairākas tabulas.

Veicot darÄ«jumu, vienlaikus var notikt to paÅ”u datu modifikācijas no citas sistēmas. Piemēram, Antispam var nolemt, ka lietotājs ir kaut kā aizdomÄ«gs un tāpēc visas lietotāja fotogrāfijas vairs nedrÄ«kst bÅ«t publiski pieejamas, tās jānosÅ«ta moderÄ“Å”anai, kas nozÄ«mē mainÄ«t photo.status uz kādu citu vērtÄ«bu un izslēgt atbilstoÅ”os skaitÄ«tājus. AcÄ«mredzot, ja Ŕī darbÄ«ba notiek bez garantijām par pielietojuma atomitāti un konkurējoÅ”o modifikāciju izolāciju, kā tas ir ACID, tad rezultāts nebÅ«s tas, kas vajadzÄ«gs - vai nu foto skaitÄ«tājs rādÄ«s nepareizu vērtÄ«bu, vai arÄ« visas fotogrāfijas netiks nosÅ«tÄ«tas moderÄ“Å”anai.

Visā Odnoklassniki pastāvÄ“Å”anas laikā ir rakstÄ«ts daudz lÄ«dzÄ«gu kodu, kas viena darÄ«juma ietvaros manipulē ar dažādām biznesa vienÄ«bām. Pamatojoties uz pieredzi migrācijā uz NoSQL no GalÄ«gā konsekvence Mēs zinām, ka lielākais izaicinājums (un laika ieguldÄ«jums) ir koda izstrāde, lai saglabātu datu konsekvenci. Tāpēc mēs uzskatÄ«jām, ka galvenā prasÄ«ba jaunajai krātuvei ir nodroÅ”ināt reālus ACID darÄ«jumus lietojumprogrammu loÄ£ikai.

Citas, ne mazāk svarīgas prasības bija:

  • Ja datu centrs neizdodas, ir jābÅ«t pieejamai gan lasÄ«Å”anai, gan rakstÄ«Å”anai jaunajā krātuvē.
  • Saglabājot paÅ”reizējo attÄ«stÄ«bas ātrumu. Tas ir, strādājot ar jaunu repozitoriju, koda daudzumam jābÅ«t aptuveni vienādam, nevajadzētu neko pievienot repozitorijam, izstrādāt algoritmus konfliktu risināŔanai, sekundāro indeksu uzturÄ“Å”anai utt.
  • Jaunās krātuves ātrumam bija jābÅ«t diezgan lielam gan nolasot datus, gan apstrādājot transakcijas, kas faktiski nozÄ«mēja, ka nebija piemērojami akadēmiski stingri, universāli, bet lēni risinājumi, kā, piemēram, divu fāžu saistÄ«bas.
  • Automātiska mērogoÅ”ana lidojuma laikā.
  • Izmantojot parastos lētos serverus, bez nepiecieÅ”amÄ«bas iegādāties eksotisku aparatÅ«ru.
  • Krātuves izstrādes iespēja uzņēmuma izstrādātājiem. Citiem vārdiem sakot, prioritāte tika pieŔķirta patentētiem vai atvērtā pirmkoda risinājumiem, vēlams Java.

Lēmumi, lēmumi

Analizējot iespējamos risinājumus, mēs nonācām pie divām iespējamām arhitektūras izvēlēm:

Pirmais ir izmantot jebkuru SQL serveri un ieviest nepiecieÅ”amo kļūdu toleranci, mērogoÅ”anas mehānismu, kļūmjpārlēces kopu, konfliktu risināŔanu un izplatÄ«tus, uzticamus un ātrus ACID darÄ«jumus. Mēs novērtējām Å”o iespēju kā ļoti nenozÄ«mÄ«gu un darbietilpÄ«gu.

Otrā iespēja ir paņemt gatavu NoSQL krātuvi ar ieviestu mērogoÅ”anu, kļūmjpārlēces klasteri, konfliktu risināŔanu un paÅ”am ieviest transakcijas un SQL. No pirmā acu uzmetiena pat SQL ievieÅ”anas uzdevums, nemaz nerunājot par ACID darÄ«jumiem, izskatās pēc uzdevuma, kas prasÄ«s vairākus gadus. Bet tad mēs sapratām, ka praksē izmantojamā SQL funkciju kopa ir tik tālu no ANSI SQL Kasandra CQL tālu no ANSI SQL. Vēl tuvāk apskatot CQL, mēs sapratām, ka tas ir diezgan tuvu tam, kas mums nepiecieÅ”ams.

Kasandra un CQL

Tātad, kas ir interesants Kasandrā, kādas ir tās iespējas?

Pirmkārt, Å”eit varat izveidot tabulas, kas atbalsta dažādus datu tipus; primārajā atslēgā varat veikt SELECT vai UPDATE.

CREATE TABLE photos (id bigint KEY, owner bigint,ā€¦);
SELECT * FROM photos WHERE id=?;
UPDATE photos SET ā€¦ WHERE id=?;

Lai nodroÅ”inātu replikas datu konsekvenci, Cassandra izmanto kvoruma pieeja. VisvienkārŔākajā gadÄ«jumā tas nozÄ«mē, ka tad, kad trÄ«s vienas rindas kopijas tiek ievietotas dažādos klastera mezglos, rakstÄ«Å”ana tiek uzskatÄ«ta par veiksmÄ«gu, ja lielākā daļa mezglu (tas ir, divi no trim) apstiprina Ŕīs rakstÄ«Å”anas darbÄ«bas panākumus. . Rindas dati tiek uzskatÄ«ti par konsekventiem, ja lasÄ«Å”anas laikā lielākā daļa mezglu tika aptaujāti un apstiprināti. Tādējādi ar trim replikām pilnÄ«ga un tÅ«lÄ«tēja datu konsekvence tiek garantēta, ja viens mezgls neizdodas. Å Ä« pieeja ļāva mums ieviest vēl uzticamāku shēmu: vienmēr sÅ«tiet pieprasÄ«jumus uz visām trim replikām, gaidot atbildi no divām ātrākajām. TreŔās kopijas novēlotā atbilde Å”ajā gadÄ«jumā tiek atmesta. Mezglā, kas novēloti reaģē, var bÅ«t nopietnas problēmas - bremzes, atkritumu savākÅ”ana JVM, tieÅ”a atmiņas atgÅ«Å”ana Linux kodolā, aparatÅ«ras kļūme, atvienoÅ”ana no tÄ«kla. Taču tas nekādā veidā neietekmē klienta darbÄ«bas vai datus.

Tiek izsaukta pieeja, kad mēs sazināmies ar trim mezgliem un saņemam atbildi no diviem spekulācijas: pieprasÄ«jums pēc papildu replikām tiek nosÅ«tÄ«ts pat pirms tas ā€œnokrÄ«tā€.

Vēl viens Cassandra ieguvums ir Batchlog ā€” mehānisms, kas nodroÅ”ina, ka jÅ«su veikto izmaiņu grupa tiek pilnÄ«bā piemērota vai netiek piemērota vispār. Tas ļauj mums atrisināt A SKĀBĒ - atomiskums ārpus kastes.

Vistuvāk darÄ«jumiem Kasandrā ir tā sauktie ā€œviegli darÄ«jumi". Bet tie ir tālu no ā€œÄ«stiemā€ ACID darÄ«jumiem: patiesÄ«bā Ŕī ir iespēja to izdarÄ«t CAS uz datiem tikai no viena ieraksta, izmantojot vienprātÄ«bu, izmantojot smagsvara Paxos protokolu. Tāpēc Ŕādu darÄ«jumu ātrums ir zems.

Kas mums pietrūka Kasandrā

Tātad mums bija jāievieÅ” reāli ACID darÄ«jumi Kasandrā. Izmantojot to, mēs varētu viegli ieviest divas citas ērtas klasiskās DBVS funkcijas: konsekventus ātrus indeksus, kas ļautu veikt datu atlasi ne tikai pēc primārās atslēgas, un parastu monotonu automātiski pieaugoÅ”u ID Ä£eneratoru.

C*Viens

Tādējādi radās jauna DBVS C*Viens, kas sastāv no trīs veidu servera mezgliem:

  • UzglabāŔana ā€“ (gandrÄ«z) standarta Cassandra serveri, kas atbild par datu glabāŔanu lokālajos diskos. Pieaugot datu slodzei un apjomam, to daudzumu var viegli mērogot lÄ«dz desmitiem un simtiem.
  • DarÄ«jumu koordinatori - nodroÅ”ina darÄ«jumu izpildi.
  • Klienti ir lietojumprogrammu serveri, kas Ä«steno biznesa operācijas un iniciē darÄ«jumus. Šādu klientu var bÅ«t tÅ«kstoÅ”iem.

NewSQL = NoSQL+ACID

Visu veidu serveri ir daļa no kopējā klastera, izmanto iekŔējo Cassandra ziņojumu protokolu, lai sazinātos savā starpā un tenkas klasteru informācijas apmaiņai. Ar Heartbeat serveri uzzina par savstarpējām kļūmēm, uztur vienotu datu shēmu ā€“ tabulas, to struktÅ«ru un replikāciju; sadalÄ«Å”anas shēma, klasteru topoloÄ£ija utt.

Klienti

NewSQL = NoSQL+ACID

Standarta draiveru vietā tiek izmantots Fat Client režīms. Šāds mezgls neuzglabā datus, bet var darboties kā pieprasÄ«juma izpildes koordinators, tas ir, Klients pats darbojas kā savu pieprasÄ«jumu koordinators: tas vaicā krātuves replikas un atrisina konfliktus. Tas ir ne tikai uzticamāks un ātrāks par standarta draiveri, kas prasa saziņu ar attālo koordinatoru, bet arÄ« ļauj kontrolēt pieprasÄ«jumu pārsÅ«tÄ«Å”anu. Ārpus klienta atvērtā darÄ«juma pieprasÄ«jumi tiek nosÅ«tÄ«ti uz krātuvēm. Ja klients ir atvēris darÄ«jumu, tad visi pieprasÄ«jumi darÄ«juma ietvaros tiek nosÅ«tÄ«ti darÄ«juma koordinatoram.
NewSQL = NoSQL+ACID

C*One darījumu koordinators

Koordinators ir tas, ko mēs ieviesām C*One no nulles. Tā ir atbildÄ«ga par darÄ«jumu pārvaldÄ«bu, slēdzenēm un darÄ«jumu piemēroÅ”anas secÄ«bu.

Katram apkalpotajam darÄ«jumam koordinators Ä£enerē laikspiedolu: katrs nākamais darÄ«jums ir lielāks par iepriekŔējo darÄ«jumu. Tā kā Kasandras konfliktu risināŔanas sistēma ir balstÄ«ta uz laikspiedoliem (no diviem konfliktējoÅ”iem ierakstiem tiek uzskatÄ«ts tas, kuram ir jaunākais laikspiedols), konflikts vienmēr tiks atrisināts par labu nākamajam darÄ«jumam. Tā mēs Ä«stenojām Lamport pulkstenis - lēts veids, kā atrisināt konfliktus sadalÄ«tā sistēmā.

Slēdzenes

Lai nodroÅ”inātu izolāciju, mēs nolēmām izmantot vienkārŔāko metodi - pesimistiskās slēdzenes, kuru pamatā ir ieraksta primārā atslēga. Citiem vārdiem sakot, darÄ«jumā ieraksts vispirms ir jābloķē, tikai pēc tam jālasa, jāmaina un jāsaglabā. Tikai pēc veiksmÄ«gas apņemÅ”anās ierakstu var atbloķēt, lai to varētu izmantot konkurējoÅ”i darÄ«jumi.

Šādas bloÄ·Ä“Å”anas ievieÅ”ana neizplatÄ«tā vidē ir vienkārÅ”a. SadalÄ«tā sistēmā ir divas galvenās iespējas: vai nu ieviest klasterÄ« izplatÄ«to bloÄ·Ä“Å”anu, vai izplatÄ«t transakcijas, lai transakcijas, kas ietver vienu un to paÅ”u ierakstu, vienmēr apkalpotu viens un tas pats koordinators.

Tā kā mūsu gadījumā dati jau ir sadalīti starp lokālo transakciju grupām SQL, tika nolemts koordinatoriem pieŔķirt lokālās transakciju grupas: viens koordinators veic visus darījumus ar marķieriem no 0 līdz 9, otrs - ar marķieriem no 10 līdz 19, un tā tālāk. Rezultātā katra koordinatora instance kļūst par darījumu grupas galveno.

Pēc tam slēdzenes koordinatora atmiņā var ieviest banālas HashMap veidā.

Koordinatora kļūmes

Tā kā viens koordinators apkalpo tikai darījumu grupu, ir ļoti svarīgi ātri noteikt tā neveiksmes faktu, lai otrais darījuma izpildes mēģinājums beigtos. Lai to padarītu ātru un uzticamu, mēs izmantojām pilnībā savienotu kvoruma dzirdes protokolu:

Katrā datu centrā ir vismaz divi koordinatora mezgli. Periodiski katrs koordinators nosūta sirdsdarbības ziņojumu citiem koordinatoriem un informē viņus par tā darbību, kā arī par to, kādus sirdsdarbības ziņojumus tas pēdējo reizi saņēmis no kuriem koordinatoriem klasterī.

NewSQL = NoSQL+ACID

Saņemot lÄ«dzÄ«gu informāciju no citiem kā daļu no saviem sirdsdarbÄ«bas ziņojumiem, katrs koordinators pats izlemj, kuri klastera mezgli darbojas un kuri ne, vadoties pēc kvoruma principa: ja mezgls X ir saņēmis informāciju no lielākās daļas klastera mezglu par normālu darbÄ«bu. ziņojumu saņemÅ”ana no mezgla Y, tad darbojas , Y. Un otrādi, tiklÄ«dz lielākā daļa ziņo par trÅ«kstoÅ”iem ziņojumiem no mezgla Y, tad Y ir atteicies. Interesanti, ka, ja kvorums informē mezglu X, ka tas vairs nesaņem ziņojumus no tā, tad pats mezgls X uzskatÄ«s sevi par neveiksmÄ«gu.

SirdsdarbÄ«bas ziņojumi tiek sÅ«tÄ«ti ar augstu frekvenci, apmēram 20 reizes sekundē, ar 50 ms periodu. Java ir grÅ«ti garantēt lietojumprogrammas atbildi 50 ms laikā, jo atkritumu savācēja radÄ«tās pauzes ir lÄ«dzÄ«gas. Mēs varējām sasniegt Å”o reakcijas laiku, izmantojot G1 atkritumu savācēju, kas ļauj mums norādÄ«t mērÄ·i GC paužu ilgumam. Tomēr dažreiz, diezgan reti, kolektora pauzes pārsniedz 50 ms, kas var novest pie kļūdainas kļūdas noteikÅ”anas. Lai tas nenotiktu, koordinators neziņo par attālā mezgla atteici, kad no tā pazÅ«d pirmais sirdsdarbÄ«bas ziņojums, tikai tad, ja pazuduÅ”i vairāki pēc kārtas.Tā mums izdevās atklāt koordinatora mezgla atteici 200. jaunkundze.

Bet nepietiek, lai ātri saprastu, kurŔ mezgls ir pārtraucis darboties. Mums kaut kas ir jādara lietas labā.

Rezervācija

Klasiskā shēma paredz, ka galvenās neveiksmes gadÄ«jumā tiek sāktas jaunas vēlÄ“Å”anas, izmantojot vienu no moderns universāls algoritmi. Tomēr Ŕādiem algoritmiem ir labi zināmas problēmas ar laika konverÄ£enci un paÅ”a vēlÄ“Å”anu procesa ilgumu. Mēs varējām izvairÄ«ties no Ŕādas papildu kavÄ“Å”anās, izmantojot koordinatora aizstāŔanas shēmu pilnÄ«bā savienotā tÄ«klā:

NewSQL = NoSQL+ACID

Pieņemsim, ka vēlamies izpildÄ«t darÄ«jumu grupā 50. IepriekÅ” noteiksim aizstāŔanas shēmu, tas ir, kuri mezgli veiks darÄ«jumus grupā 50 galvenā koordinatora atteices gadÄ«jumā. MÅ«su mērÄ·is ir uzturēt sistēmas funkcionalitāti datu centra kļūmes gadÄ«jumā. Noteiksim, ka pirmā rezerve bÅ«s mezgls no cita datu centra, bet otrā rezerve bÅ«s mezgls no treŔā. Å Ä« shēma tiek atlasÄ«ta vienreiz un nemainās, lÄ«dz mainās klastera topoloÄ£ija, tas ir, lÄ«dz tajā ienāk jauni mezgli (kas notiek ļoti reti). Jauna aktÄ«vā meistara izvēles procedÅ«ra, ja vecais neizdodas, vienmēr bÅ«s Ŕāda: pirmā rezerve kļūs par aktÄ«vo meistaru, un, ja tā ir pārtraukusi darboties, otrā rezerve kļūs par aktÄ«vo meistaru.

Šī shēma ir uzticamāka par universālo algoritmu, jo, lai aktivizētu jaunu meistaru, pietiek noteikt vecā kļūmi.

Bet kā klienti sapratÄ«s, kurÅ” meistars Å”obrÄ«d strādā? Nav iespējams nosÅ«tÄ«t informāciju tÅ«kstoÅ”iem klientu 50 ms laikā. Iespējama situācija, kad klients nosÅ«ta pieprasÄ«jumu atvērt darÄ«jumu, vēl nezinot, ka Å”is meistars vairs nedarbojas, un pieprasÄ«juma noildze beigsies. Lai tas nenotiktu, klienti spekulatÄ«vi nosÅ«ta pieprasÄ«jumu atvērt darÄ«jumu grupas meistaram un abām viņa rezervēm uzreiz, taču uz Å”o pieprasÄ«jumu atbildēs tikai tas, kurÅ” uz doto brÄ«di ir aktÄ«vais saimnieks. Visu turpmāko saziņu darÄ«juma ietvaros klients veiks tikai ar aktÄ«vo meistaru.

Rezerves meistari saņemtos pieprasÄ«jumus par darÄ«jumiem, kas nav viņu paÅ”u, ievieto nedzimuÅ”o transakciju rindā, kur tos kādu laiku glabā. Ja aktÄ«vais galvenais nomirst, jaunais galvenais apstrādā pieprasÄ«jumus atvērt transakcijas no savas rindas un atbild klientam. Ja klients jau ir atvēris darÄ«jumu ar vecmeistaru, tad otrā atbilde tiek ignorēta (un, acÄ«mredzot, Ŕāds darÄ«jums netiks pabeigts un klients to atkārtos).

Kā notiek darījums

Pieņemsim, ka klients nosÅ«tÄ«ja koordinatoram pieprasÄ«jumu atvērt darÄ«jumu Ŕādai un tādai entÄ«tijai ar Ŕādu un tādu primāro atslēgu. Koordinators bloķē Å”o entÄ«tiju un ievieto to atmiņā bloÄ·Ä“Å”anas tabulā. Ja nepiecieÅ”ams, koordinators nolasa Å”o entÄ«tiju no krātuves un saglabā iegÅ«tos datus darÄ«juma stāvoklÄ« koordinatora atmiņā.

NewSQL = NoSQL+ACID

Ja klients vēlas mainÄ«t datus darÄ«jumā, tas koordinatoram nosÅ«ta pieprasÄ«jumu modificēt entÄ«tiju, un koordinators ievieto jaunos datus transakcijas statusa tabulā atmiņā. Tādējādi ierakstÄ«Å”ana tiek pabeigta ā€” krātuvē netiek veikts ieraksts.

NewSQL = NoSQL+ACID

Kad klients aktīvā darījuma ietvaros pieprasa savus mainītos datus, koordinators rīkojas Ŕādi:

  • ja ID jau ir darÄ«jumā, tad dati tiek ņemti no atmiņas;
  • ja atmiņā nav ID, tad trÅ«kstoÅ”ie dati tiek nolasÄ«ti no uzglabāŔanas mezgliem, apvienoti ar jau atmiņā esoÅ”ajiem, un rezultāts tiek nodots klientam.

Tādējādi klients var lasÄ«t savas izmaiņas, bet citi klienti Ŕīs izmaiņas neredz, jo tās tiek saglabātas tikai koordinatora atmiņā, tās vēl neatrodas Cassandra mezglos.

NewSQL = NoSQL+ACID

Kad klients nosÅ«ta saistÄ«bu izpildi, statusu, kas bija pakalpojuma atmiņā, koordinators saglabā reÄ£istrētā paketē un nosÅ«ta kā reÄ£istrētu partiju uz Cassandra krātuvi. Veikali dara visu nepiecieÅ”amo, lai Ŕī pakete tiktu atomiski (pilnÄ«bā) uzklāta, un atgriež atbildi koordinatoram, kurÅ” atbrÄ«vo slēdzenes un apstiprina klientam darÄ«juma veiksmÄ«gu izpildi.

NewSQL = NoSQL+ACID

Un, lai atsauktu, koordinatoram ir tikai jāatbrīvo atmiņa, ko aizņem darījuma stāvoklis.

IepriekÅ” minēto uzlabojumu rezultātā mēs ieviesām ACID principus:

  • Atomiskums. Tā ir garantija, ka neviens darÄ«jums netiks daļēji ierakstÄ«ts sistēmā; vai nu tiks pabeigtas visas tās apakÅ”operācijas, vai arÄ« netiks pabeigta neviena. Mēs ievērojam Å”o principu, izmantojot reÄ£istrēto partiju Cassandra.
  • Konsekvence. Katrs veiksmÄ«gs darÄ«jums pēc definÄ«cijas reÄ£istrē tikai derÄ«gus rezultātus. Ja pēc darÄ«juma atvērÅ”anas un daļu darbÄ«bu veikÅ”anas tiek atklāts, ka rezultāts ir nederÄ«gs, tiek veikta atcelÅ”ana.
  • Izolācija. Kad darÄ«jums tiek izpildÄ«ts, vienlaicÄ«giem darÄ«jumiem nevajadzētu ietekmēt tā iznākumu. KonkurējoÅ”ie darÄ«jumi tiek izolēti, izmantojot koordinatora pesimistiskus slēdzenes. LasÄ«Å”anai ārpus darÄ«juma izolācijas princips tiek ievērots Read Committed lÄ«menÄ«.
  • Stabilitāte. NeatkarÄ«gi no problēmām zemākos lÄ«meņos ā€” sistēmas aptumÅ”oÅ”ana, aparatÅ«ras kļūme ā€” veiksmÄ«gi pabeigta darÄ«juma rezultātā veiktajām izmaiņām ir jāpaliek saglabātām, kad darbÄ«ba tiek atsākta.

LasÄ«Å”ana pēc indeksiem

Ņemsim vienkārÅ”u tabulu:

CREATE TABLE photos (
id bigint primary key,
owner bigint,
modified timestamp,
ā€¦)

Tam ir ID (primārā atslēga), Ä«paÅ”nieks un modifikācijas datums. Jums ir jāiesniedz ļoti vienkārÅ”s pieprasÄ«jums - atlasiet datus par Ä«paÅ”nieku ar maiņas datumu ā€œpar pēdējo dienuā€.

SELECT *
WHERE owner=?
AND modified>?

Lai Ŕāds vaicājums tiktu ātri apstrādāts, klasiskajā SQL DBVS ir jāveido indekss pa kolonnām (Ä«paÅ”nieks, modificēts). Mēs to varam izdarÄ«t pavisam vienkārÅ”i, jo tagad mums ir ACID garantijas!

Indeksi C*One

Ir avota tabula ar fotogrāfijām, kurās ieraksta ID ir primārā atslēga.

NewSQL = NoSQL+ACID

Indeksam C*One izveido jaunu tabulu, kas ir oriģināla kopija. Atslēga ir tāda pati kā indeksa izteiksme, un tajā ir iekļauta arī ieraksta primārā atslēga no avota tabulas:

NewSQL = NoSQL+ACID

Tagad vaicājumu ā€œÄ«paÅ”nieks par pēdējo dienuā€ var pārrakstÄ«t kā atlasi no citas tabulas:

SELECT * FROM i1_test
WHERE owner=?
AND modified>?

Datu konsekvenci avota tabulas fotoattēlos un indeksu tabulā i1 automātiski uztur koordinators. Pamatojoties tikai uz datu shēmu, kad tiek saņemtas izmaiņas, koordinators Ä£enerē un saglabā izmaiņas ne tikai galvenajā tabulā, bet arÄ« kopijās. Ar indeksu tabulu netiek veiktas nekādas papildu darbÄ«bas, žurnāli netiek lasÄ«ti un netiek izmantoti bloķētāji. Tas nozÄ«mē, ka indeksu pievienoÅ”ana gandrÄ«z nepatērē resursus un praktiski neietekmē modifikāciju ievieÅ”anas ātrumu.

Izmantojot ACID, mēs varējām ieviest SQL lÄ«dzÄ«gus indeksus. Tie ir konsekventi, mērogojami, ātri, saliekami un iebÅ«vēti CQL vaicājumu valodā. Lai atbalstÄ«tu indeksus, nav nepiecieÅ”amas nekādas izmaiņas lietojumprogrammas kodā. Viss ir tikpat vienkārÅ”i kā SQL. Un pats galvenais, indeksi neietekmē sākotnējās darÄ«jumu tabulas modifikāciju izpildes ātrumu.

Kas notika

Mēs izstrādājām C*One pirms trim gadiem un uzsākām to komerciālā darbībā.

Ko mēs galu galā ieguvām? Novērtēsim to, izmantojot fotoattēlu apstrādes un uzglabāŔanas apakÅ”sistēmas piemēru, kas ir viens no svarÄ«gākajiem datu veidiem sociālajā tÄ«klā. Mēs nerunājam par paÅ”u fotogrāfiju korpusiem, bet gan par visa veida metainformāciju. Tagad Odnoklassniki ir aptuveni 20 miljardi Ŕādu ierakstu, sistēma apstrādā 80 tÅ«kstoÅ”us lasÄ«Å”anas pieprasÄ«jumu sekundē, lÄ«dz 8 tÅ«kstoÅ”iem ACID darÄ«jumu sekundē, kas saistÄ«ti ar datu modifikāciju.

Kad mēs izmantojām SQL ar replikācijas koeficientu = 1 (bet RAID 10), fotoattēlu metainformācija tika glabāta ļoti pieejamā 32 maŔīnu klasterÄ«, kurā darbojas Microsoft SQL Server (plus 11 dublējumkopijas). Dublējumu glabāŔanai tika atvēlēti arÄ« 10 serveri. Kopā 50 dārgas maŔīnas. Tajā paŔā laikā sistēma darbojās ar nominālo slodzi, bez rezerves.

Pēc migrÄ“Å”anas uz jauno sistēmu saņēmām replikācijas koeficientu = 3 ā€“ kopiju katrā datu centrā. Sistēma sastāv no 63 Cassandra uzglabāŔanas mezgliem un 6 koordinatora maŔīnām, kopā 69 serveriem. Taču Ŕīs maŔīnas ir daudz lētākas, to kopējās izmaksas ir aptuveni 30% no SQL sistēmas izmaksām. Tajā paŔā laikā slodze tiek saglabāta 30%.

IevieÅ”ot C*One, samazinājās arÄ« latentums: SQL sistēmā rakstÄ«Å”anas darbÄ«ba aizņēma aptuveni 4,5 ms. C*One - apmēram 1,6 ms. DarÄ«juma ilgums vidēji ir mazāks par 40 ms, commit tiek pabeigts 2 ms, lasÄ«Å”anas un rakstÄ«Å”anas ilgums ir vidēji 2 ms. 99. procentile - tikai 3-3,1 ms, taimautu skaits ir samazinājies 100 reizes - tas viss ir saistÄ«ts ar plaÅ”o spekulāciju izmantoÅ”anu.

LÄ«dz Å”im lielākā daļa SQL Server mezglu ir pārtraukti; jauni produkti tiek izstrādāti, tikai izmantojot C*One. Mēs pielāgojām C*One darbam mÅ«su mākonÄ« viens mākonis, kas ļāva paātrināt jaunu klasteru izvietoÅ”anu, vienkārÅ”ot konfigurāciju un automatizēt darbÄ«bu. Bez pirmkoda to izdarÄ«t bÅ«tu daudz grÅ«tāk un apgrÅ«tinoŔāk.

Tagad mēs strādājam pie pārējās mÅ«su krātuves pārvietoÅ”anas uz mākoni, taču tas ir pavisam cits stāsts.

Avots: www.habr.com

Pievieno komentāru