{"id":37956,"date":"2019-10-31T22:20:47","date_gmt":"2019-10-31T19:20:47","guid":{"rendered":"https:\/\/prohoster.info\/blog\/newsql-nosql-acid\/"},"modified":"2019-10-31T22:20:47","modified_gmt":"2019-10-31T19:20:47","slug":"newsql-nosql-acid","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/newsql-nosql-acid","title":{"rendered":"NewSQL = NoSQL+ACID","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/973145efa566bca10ffe7ba95733a1d5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nA\u017e doned\u00e1vna bolo v Odnoklassnikach pribli\u017ene 50 TB \u00fadajov spracov\u00e1van\u00fdch v re\u00e1lnom \u010dase ulo\u017een\u00fdch v SQL Serveri. Pre tak\u00fd objem je zabezpe\u010di\u0165 r\u00fdchly, spo\u013eahliv\u00fd a odoln\u00fd pr\u00edstup k DCP s pou\u017eit\u00edm SQL DB prakticky nemo\u017en\u00e9. Zvy\u010dajne sa v tak\u00fdchto pr\u00edpadoch pou\u017e\u00edvaj\u00fa jedno z NoSQL \u00falo\u017e\u00edsk, ale nie v\u0161etko sa d\u00e1 prenies\u0165 do NoSQL: niektor\u00e9 entity vy\u017eaduj\u00fa z\u00e1ruky ACID transakci\u00ed. <\/p>\n<p>To n\u00e1s priviedlo k pou\u017eitiu NewSQL \u00falo\u017e\u00edsk, teda DB, ktor\u00e1 poskytuje odolnos\u0165 vo\u010di chybe, \u0161k\u00e1lovate\u013enos\u0165 a r\u00fdchlos\u0165 NoSQL syst\u00e9mov, no z\u00e1rove\u0148 zachov\u00e1va tradi\u010dn\u00e9 ACID z\u00e1ruky klasick\u00fdch syst\u00e9mov. Funguj\u00facich priemyseln\u00fdch syst\u00e9mov tejto novej triedy je m\u00e1lo, preto sme tak\u00fd syst\u00e9m implementovali sami a spustili ho do priemyselnej prev\u00e1dzky. <\/p>\n<p>Ako to funguje a \u010do sa podarilo \u2014 \u010d\u00edtajte \u010falej.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nDnes mesa\u010dn\u00e1 n\u00e1v\u0161tevnos\u0165 \u201eOdnoklassnikov\u201c presahuje 70 mili\u00f3nov unik\u00e1tnych n\u00e1v\u0161tevn\u00edkov. My <noindex><a rel=\"nofollow\" href=\"https:\/\/www.similarweb.com\/top-websites\/category\/internet-and-telecom\/social-network\">sme v prvej p\u00e4\u0165ke<\/a><\/noindex> najv\u00e4\u010d\u0161\u00edch soci\u00e1lnych siet\u00ed sveta a v prvej dvadsiatke str\u00e1nok, na ktor\u00fdch u\u017e\u00edvatelia tr\u00e1via najviac \u010dasu. Infrastukt\u00fara \u201eOK\u201c spracov\u00e1va ve\u013emi vysok\u00e9 za\u0165a\u017eenia: viac ako mili\u00f3n HTTP po\u017eiadaviek\/s na fronty. \u010casti serverov\u00e9ho parku v po\u010dte viac ako 8000 kusov s\u00fa umiestnen\u00e9 bl\u00edzko seba \u2014 v \u0161tyroch moskovsk\u00fdch d\u00e1tov\u00fdch centr\u00e1ch, \u010do umo\u017e\u0148uje zabezpe\u010di\u0165 sie\u0165ov\u00fa latenciu menej ako 1 ms medzi nimi.<\/p>\n<p>Cassandra pou\u017e\u00edvame od roku 2010, po\u010dn\u00fac verziou 0.6. Dnes m\u00e1me v prev\u00e1dzke nieko\u013eko desiatok klastra. Najr\u00fdchlej\u0161\u00ed klastra spracov\u00e1va viac ako 4 mili\u00f3ny oper\u00e1ci\u00ed za sekundu, najv\u00e4\u010d\u0161\u00ed uchov\u00e1va 260 TB. <\/p>\n<p>To s\u00fa v\u0161ak be\u017en\u00e9 NoSQL klastry pou\u017e\u00edvan\u00e9 na ukladanie <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D0%BE%D0%B3%D0%BB%D0%B0%D1%81%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%B2_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%BC_%D1%81%D1%87%D1%91%D1%82%D0%B5\">slabo zladen\u00fdch<\/a><\/noindex> \u00fadajov. My sme sa v\u0161ak chceli nahradi\u0165 hlavn\u00e9 konzistentn\u00e9 \u00falo\u017eisko, Microsoft SQL Server, ktor\u00e9 sa pou\u017e\u00edvalo od zalo\u017eenia \u201eOdnoklassnikov\u201c. Ulo\u017eenie pozost\u00e1valo z viac ako 300 strojov SQL Server Standard Edition, na ktor\u00fdch sa nach\u00e1dzalo 50 TB \u00fadajov \u2014 obchodn\u00fdch ent\u00edt. Tieto \u00fadaje sa modifikuj\u00fa v r\u00e1mci ACID transakci\u00ed a vy\u017eaduj\u00fa <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">vysok\u00fa zladenos\u0165<\/a><\/noindex>.<\/p>\n<p>Na rozdelenie \u00fadajov po nodoch SQL Server sme pou\u017eili ako vertik\u00e1lne, tak aj horizont\u00e1lne <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Partition_(database)\">particionovanie<\/a><\/noindex> (sharding). Historicky jsme pou\u017e\u00edvali jednoduch\u00fd syst\u00e9m shardov\u00e1n\u00ed dat: ka\u017ed\u00e9 entit\u011b byl p\u0159i\u0159azen token \u2014 funkce z ID entity. Entity se stejn\u00fdm tokenem byly um\u00edst\u011bny na jeden SQL server. Vztah typu master-detail byl realizov\u00e1n tak, aby tokeny hlavn\u00edho a odvozen\u00e9ho z\u00e1znamu v\u017edy odpov\u00eddaly a nach\u00e1zely se na jednom serveru. V soci\u00e1ln\u00ed s\u00edti t\u00e9m\u011b\u0159 v\u0161echny z\u00e1znamy vznikaj\u00ed jm\u00e9nem u\u017eivatele \u2014 to znamen\u00e1, \u017ee v\u0161echna data u\u017eivatele v r\u00e1mci jednoho funk\u010dn\u00edho subsyst\u00e9mu jsou ulo\u017eena na jednom serveru. To znamen\u00e1, \u017ee v obchodn\u00ed transakci t\u00e9m\u011b\u0159 v\u017edy byly zapojeny tabulky jednoho SQL serveru, co\u017e umo\u017enilo zajistit konzistenci dat pomoc\u00ed lok\u00e1ln\u00edch ACID transakc\u00ed, bez nutnosti pou\u017eit\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">pomal\u00fdch a nespolehliv\u00fdch<\/a><\/noindex> distribuovan\u00fdch ACID tranzakc\u00ed.<\/p>\n<p>D\u00edky shardov\u00e1n\u00ed a pro urychlen\u00ed pr\u00e1ce SQL:<\/p>\n<ul>\n<li>Nepou\u017e\u00edv\u00e1me Foreign key constraints, proto\u017ee p\u0159i shardov\u00e1n\u00ed m\u016f\u017ee ID entity b\u00fdt na jin\u00e9m serveru.<\/li>\n<li>Nepou\u017e\u00edv\u00e1me ulo\u017een\u00e9 procedury a spou\u0161t\u011b\u010de kv\u016fli dodate\u010dn\u00e9 z\u00e1t\u011b\u017ei na CPU DBMS.<\/li>\n<li>Nepou\u017e\u00edv\u00e1me JOINy kv\u016fli v\u0161emu v\u00fd\u0161e uveden\u00e9mu a mnoha n\u00e1hodn\u00fdm \u010dten\u00edm z disku.<\/li>\n<li>Mimo transakci pro sn\u00ed\u017een\u00ed vz\u00e1jemn\u00e9ho blokov\u00e1n\u00ed pou\u017e\u00edv\u00e1me \u00farove\u0148 izolace Read Uncommitted.<\/li>\n<li>Prov\u00e1d\u00edme pouze kr\u00e1tk\u00e9 transakce (pr\u016fm\u011brn\u011b krat\u0161\u00ed ne\u017e 100 ms).<\/li>\n<li>Nepou\u017e\u00edv\u00e1me v\u00edce\u0159\u00e1dkov\u00e9 UPDATE a DELETE kv\u016fli velk\u00e9mu mno\u017estv\u00ed vz\u00e1jemn\u00e9ho blokov\u00e1n\u00ed \u2014 aktualizujeme pouze jeden z\u00e1znam.<\/li>\n<li>Dotazy v\u017edy prov\u00e1d\u00edme pouze podle index\u016f \u2014 dotaz s pl\u00e1nem pln\u00e9ho prohl\u00ed\u017een\u00ed tabulky pro n\u00e1s znamen\u00e1 p\u0159et\u00ed\u017een\u00ed DB a jej\u00edch selh\u00e1n\u00ed.<\/li>\n<\/ul>\n<p>\nTyto kroky n\u00e1m umo\u017enily vyt\u011b\u017eit z SQL server\u016f t\u00e9m\u011b\u0159 maxim\u00e1ln\u00ed v\u00fdkon. Nicm\u00e9n\u011b probl\u00e9m\u016f st\u00e1le p\u0159ib\u00fdvalo. Poj\u010fme si je prozkoumat.<\/p>\n<h2>Probl\u00e9my se SQL<\/h2>\n<p><\/p>\n<ul>\n<li>Proto\u017ee jsme pou\u017e\u00edvali vlastn\u00ed shardov\u00e1n\u00ed, p\u0159id\u00e1n\u00ed nov\u00fdch shard\u016f bylo prov\u00e1d\u011bno administr\u00e1tory ru\u010dn\u011b. Po celou dobu \u0161k\u00e1lovateln\u00e9 repliky dat nezpracov\u00e1valy \u017e\u00e1dn\u00e9 dotazy. <\/li>\n<li>S rostouc\u00edm po\u010dtem z\u00e1znam\u016f v tabulce se sni\u017euje rychlost vkl\u00e1d\u00e1n\u00ed a modifikace, p\u0159i p\u0159id\u00e1v\u00e1n\u00ed index\u016f k existuj\u00edc\u00ed tabulce rychlost kles\u00e1 mnohon\u00e1sobn\u011b, vytv\u00e1\u0159en\u00ed a obnovov\u00e1n\u00ed index\u016f prob\u00edh\u00e1 s v\u00fdpadkem.<\/li>\n<li>P\u0159\u00edtomnost mal\u00e9 skupiny Windows pro SQL Server v produkci zt\u011b\u017euje spr\u00e1vu infrastruktury.<\/li>\n<\/ul>\n<p>\nAle hlavn\u00ed probl\u00e9m \u2014 <\/p>\n<h2>Odolnos\u0165 vo\u010di zlyhaniam<\/h2>\n<p>\nKlasick\u00fd SQL server m\u00e1 slab\u00fa odolnos\u0165 vo\u010di v\u00fdpadkom. Predpokladajme, \u017ee m\u00e1te len jeden datab\u00e1zov\u00fd server, a ten zlyh\u00e1 raz za tri roky. Po\u010das tohto \u010dasu web nefunguje 20 min\u00fat, \u010do je akceptovate\u013en\u00e9. Ak m\u00e1te 64 serverov, web nefunguje u\u017e raz za tri t\u00fd\u017edne. A ak m\u00e1te 200 serverov, web nefunguje ka\u017ed\u00fa t\u00fd\u017ede\u0148. To je probl\u00e9m. <\/p>\n<p>\u010co mo\u017eno urobi\u0165 na zv\u00fd\u0161enie odolnosti SQL servera vo\u010di v\u00fdpadkom? Wikip\u00e9dia n\u00e1m navrhuje vytvori\u0165 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/High-availability_cluster\">vysoko dostupn\u00fd klaster<\/a><\/noindex>: kde v pr\u00edpade zlyhania ktor\u00e9hoko\u013evek z komponentov existuje duplik\u00e1t.<\/p>\n<p>To si vy\u017eaduje park n\u00e1kladn\u00e9ho vybavenia: mno\u017estvo duplikovania, optick\u00e9 vl\u00e1kno, zdie\u013ean\u00e9 \u00falo\u017eisk\u00e1, a dokonca aj aktivovanie rezervovania funguje nespo\u013eahlivo: pribli\u017ene 10% aktiv\u00e1ci\u00ed kon\u010d\u00ed zlyhan\u00edm z\u00e1lo\u017enej uzly, ktor\u00e1 nasleduje za hlavnou uzlou. <\/p>\n<p>Hlavnou nev\u00fdhodou tak\u00e9ho vysoko dostupn\u00e9ho klastra je v\u0161ak nulov\u00e1 dostupnos\u0165 pri zlyhan\u00ed d\u00e1tov\u00e9ho centra, v ktorom sa nach\u00e1dza. \u201eOdaktokos\u0165\u201c m\u00e1 \u0161tyri d\u00e1tov\u00e9 centr\u00e1 a mus\u00edme zabezpe\u010di\u0165 fungovanie pri \u00faplnej hav\u00e1rii v jednom z nich.<\/p>\n<p>Na to by sa mohla pou\u017ei\u0165 <noindex><a rel=\"nofollow\" href=\"https:\/\/technet.microsoft.com\/en-us\/library\/ms151196.aspx\">Multi-Master<\/a><\/noindex> replik\u00e1cia zabudovan\u00e1 v SQL Serveri. Tento pr\u00edstup je v\u00fdrazne drah\u0161\u00ed z h\u013eadiska n\u00e1kladov na softv\u00e9r a trp\u00ed dobre zn\u00e1mymi probl\u00e9mami s replik\u00e1ciou \u2013 nepredv\u00eddate\u013en\u00fdmi oneskoreniami transakci\u00ed pri synchronizovanej replik\u00e1cii a oneskoren\u00edm pou\u017eit\u00ed replik\u00e1ci\u00ed (a t\u00fdm p\u00e1dom stratou modifik\u00e1ci\u00ed) pri asynchr\u00f3nnej. Predpoklad\u00e1 sa, \u017ee <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/relational-databases\/replication\/transactional\/peer-to-peer-conflict-detection-in-peer-to-peer-replication\">ru\u010dne rie\u0161enie konfliktov<\/a><\/noindex> rob\u00ed t\u00fato mo\u017enos\u0165 pre n\u00e1s \u00faplne nevhodnou.<\/p>\n<p>V\u0161etky tieto probl\u00e9my si vy\u017eadovali z\u00e1sadn\u00e9 rie\u0161enie a pustili sme sa do ich podrobnej anal\u00fdzy. Oslovme sa s t\u00fdm, \u010do SQL Server v podstate rob\u00ed \u2013 transakciami.<\/p>\n<h2>Jednoduch\u00e1 transakcia<\/h2>\n<p>\nZv\u00e1\u017eme najjednoduch\u0161iu, z poh\u013eadu aplika\u010dn\u00e9ho SQL program\u00e1tora, transakciu: pridanie fotografie do albumu. Albumy a fotografie sa ukladaj\u00fa do r\u00f4znych tabuliek. Album m\u00e1 \u010d\u00edta\u010d verejn\u00fdch fotografi\u00ed. Potom sa tak\u00e1to transakcia rozde\u013euje na nasleduj\u00face kroky: <\/p>\n<ol>\n<li>Zablokujeme album pod\u013ea k\u013e\u00fa\u010da.<\/li>\n<li>Vytvor\u00edme z\u00e1znam v tabu\u013eke fotografi\u00ed. <\/li>\n<li>Ak m\u00e1 fotografia verejn\u00fd status, zvy\u0161ujeme v albume \u010d\u00edta\u010d verejn\u00fdch fotografi\u00ed, aktualizujeme z\u00e1znam a potvrd\u00edme transakciu.<\/li>\n<\/ol>\n<p>\nAlebo vo forme pseudok\u00f3du:<\/p>\n<pre><code>TX.start(\"Albums\", id);\nAlbum album = albums.lock(id);\nPhoto photo = photos.create(\u2026);\n\nif (photo.status == PUBLIC) {\n    album.incPublicPhotosCount();\n}\nalbum.update();\n\nTX.commit();<\/code><\/pre>\n<p>\nVid\u00edme, \u017ee najbe\u017enej\u0161\u00edm sc\u00e9narom obchodnej transakcie je pre\u010d\u00edtanie \u00fadajov z datab\u00e1zy do pam\u00e4te aplika\u010dn\u00e9ho servera, nie\u010do zmeni\u0165 a ulo\u017ei\u0165 nov\u00e9 hodnoty sp\u00e4\u0165 do datab\u00e1zy. Zvy\u010dajne v takejto transakcii aktualizujeme nieko\u013eko ent\u00edt, nieko\u013eko tabuliek. <\/p>\n<p>Po\u010das vykon\u00e1vania transakcie m\u00f4\u017ee d\u00f4js\u0165 k s\u00fabe\u017enej modifik\u00e1cii rovnak\u00fdch \u00fadajov z in\u00e9ho syst\u00e9mu. Napr\u00edklad, Antispam m\u00f4\u017ee zhodnoti\u0165, \u017ee pou\u017e\u00edvate\u013e je podozriv\u00fd, a preto v\u0161etky fotky pou\u017e\u00edvate\u013ea by u\u017e nemali by\u0165 verejn\u00e9, mali by by\u0165 odoslan\u00e9 na moder\u00e1ciu, \u010do znamen\u00e1 zmeni\u0165 photo.status na nejak\u00fa in\u00fa hodnotu a resetova\u0165 pr\u00edslu\u0161n\u00e9 po\u010d\u00edtadl\u00e1. Je zrejm\u00e9, \u017ee ak sa t\u00e1to oper\u00e1cia uskuto\u010dn\u00ed bez z\u00e1ruk at\u00f3movosti aplik\u00e1cie a izol\u00e1cie s\u00fabe\u017en\u00fdch modifik\u00e1ci\u00ed, ako v <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">ACID<\/a><\/noindex>, v\u00fdsledok nebude to, \u010do je potrebn\u00e9 \u2014 bu\u010f po\u010d\u00edtadlo fotiek bude ukazova\u0165 nespr\u00e1vnu hodnotu, alebo sa v\u0161etky fotky neodo\u0161l\u00fa na moder\u00e1ciu. <\/p>\n<p>Tak\u00fdto k\u00f3d, manipuluj\u00faci s r\u00f4znymi obchodn\u00fdmi entitami v r\u00e1mci jednej transakcie, bolo po\u010das existencie Odnoklassnikov nap\u00edsan\u00e9 ve\u013emi ve\u013ea. Na z\u00e1klade sk\u00fasenost\u00ed s migr\u00e1ciami na NoSQL s <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">Eventual Consistency<\/a><\/noindex> vieme, \u017ee najv\u00e4\u010d\u0161ie \u0165a\u017ekosti (a \u010dasov\u00e9 n\u00e1klady) sp\u00f4sobuje potreba vyv\u00edja\u0165 k\u00f3d, zameran\u00fd na udr\u017eanie konzistencie \u00fadajov. Preto sme pova\u017eovali za hlavn\u00fd po\u017eiadavok, aby nov\u00e9 \u00falo\u017eisko zabezpe\u010dilo pre aplika\u010dn\u00fa logiku skuto\u010dn\u00e9 ACID transakcie. <\/p>\n<p>In\u00e9, nemenej d\u00f4le\u017eit\u00e9 po\u017eiadavky boli:<\/p>\n<ul>\n<li>Pri v\u00fdpadku d\u00e1tov\u00e9ho centra musia by\u0165 dostupn\u00e9 aj \u010d\u00edtanie, aj z\u00e1pis do nov\u00e9ho \u00falo\u017eiska.<\/li>\n<li>Zachovanie aktu\u00e1lnej r\u00fdchlosti v\u00fdvoja. To znamen\u00e1, \u017ee pri pr\u00e1ci s nov\u00fdm \u00falo\u017eiskom by malo by\u0165 mno\u017estvo k\u00f3du pribli\u017ene rovnak\u00e9, nemalo by by\u0165 potrebn\u00e9 dop\u00edsava\u0165 nie\u010do do \u00falo\u017eiska, vyv\u00edja\u0165 algoritmy na rie\u0161enie konfliktov, udr\u017eiavanie sekund\u00e1rnych indexov a podobne. <\/li>\n<li>R\u00fdchlos\u0165 fungovania nov\u00e9ho \u00falo\u017eiska by mala by\u0165 dostato\u010dne vysok\u00e1, ako pri \u010d\u00edtan\u00ed \u00fadajov, tak aj pri spracovan\u00ed transakci\u00ed, \u010do efekt\u00edvne znamenalo nepraktickos\u0165 akademicky presn\u00fdch, univerz\u00e1lnych, ale pomal\u00fdch rie\u0161en\u00ed, ako napr\u00edklad, <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">dvojn\u00e1sobn\u00fdch komitov<\/a><\/noindex>.<\/li>\n<li>Automatick\u00e9 \u0161k\u00e1lovanie za behu. <\/li>\n<li>Pou\u017eitie be\u017en\u00fdch lacn\u00fdch serverov, bez potreby kupova\u0165 exotick\u00e9 zariadenia. <\/li>\n<li>Mo\u017enos\u0165 rozvoja \u00falo\u017eiska silami v\u00fdvoj\u00e1rov spolo\u010dnosti. In\u00fdmi slovami, priorita sa kl\u00e1dla na vlastn\u00e9 alebo rie\u0161enia zalo\u017een\u00e9 na otvorenom zdroji, ide\u00e1lne v Jave.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Rie\u0161enia, rie\u0161enia<\/h2>\n<p>\nAnal\u00fdzou mo\u017en\u00fdch rie\u0161en\u00ed sme pri\u0161li k dvom mo\u017en\u00fdm vo\u013eb\u00e1m architekt\u00fary:<\/p>\n<p>Prv\u00e1 - zobra\u0165 ak\u00fdko\u013evek SQL server a realizova\u0165 potrebn\u00fa odolnos\u0165 vo\u010di chyb\u00e1m, mechanizmus \u0161k\u00e1lovania, odoln\u00fd klaster, rie\u0161enie konfliktov a distribuovan\u00e9, spo\u013eahliv\u00e9 a r\u00fdchle ACID transakcie. Tento variant sme ohodnotili ako ve\u013emi netriv\u00e1lny a n\u00e1ro\u010dn\u00fd.<\/p>\n<p>Druh\u00e1 mo\u017enos\u0165 - zobra\u0165 hotov\u00e9 NoSQL \u00falo\u017eisko s implementovan\u00fdm \u0161k\u00e1lovan\u00edm, odoln\u00fdm klastrom, rie\u0161en\u00edm konfliktov a realizova\u0165 transakcie a SQL sami. Na prv\u00fd poh\u013ead vyzer\u00e1 aj \u00faloha implement\u00e1cie SQL, nehovoriac o ACID transakci\u00e1ch, ako \u00faloha na roky. Ale potom sme si uvedomili, \u017ee s\u00fabor mo\u017enost\u00ed SQL, ktor\u00fd pou\u017e\u00edvame v praxi, je \u010faleko od ANSI SQL rovnako \u010faleko ako <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Apache_Cassandra#Cassandra_Query_Language\">Cassandra CQL<\/a><\/noindex> \u010faleko od ANSI SQL. Po d\u00f4kladnej\u0161om presk\u00faman\u00ed CQL sme si uvedomili, \u017ee je dostato\u010dne bl\u00edzko tomu, \u010do potrebujeme.<\/p>\n<h2>Cassandra a CQL<\/h2>\n<p>\nTak\u017ee, \u010d\u00edm je Cassandra zauj\u00edmav\u00e1, ak\u00fdmi mo\u017enos\u0165ami disponuje?<\/p>\n<p>Po prv\u00e9, tu je mo\u017en\u00e9 vytv\u00e1ra\u0165 tabu\u013eky s podporou r\u00f4znych typov d\u00e1t, m\u00f4\u017eeme robi\u0165 SELECT alebo UPDATE pod\u013ea prim\u00e1rneho k\u013e\u00fa\u010da.<\/p>\n<pre><code>CREATE TABLE photos (id bigint KEY, owner bigint,\u2026);\nSELECT * FROM photos WHERE id=?;\nUPDATE photos SET \u2026 WHERE id=?;<\/code><\/pre>\n<p>\nNa zabezpe\u010denie konzistencie d\u00e1t repliky, Cassandra pou\u017e\u00edva <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Quorum_(distributed_computing)\">kv\u00f3rumov\u00fd pr\u00edstup<\/a><\/noindex>V najjednoduch\u0161om pr\u00edpade to znamen\u00e1, \u017ee pri umiestnen\u00ed troch replik rovnak\u00e9ho radu na r\u00f4zne nody clustra, z\u00e1pis sa pova\u017euje za \u00faspe\u0161n\u00fd, ak v\u00e4\u010d\u0161ina nodov (t.j. dve z troch) potvrdila \u00faspe\u0161nos\u0165 tejto oper\u00e1cie z\u00e1pisu. D\u00e1ta radu sa pova\u017euj\u00fa za konzistentn\u00e9, ak pri \u010d\u00edtan\u00ed bola op\u00fdtan\u00e1 v\u00e4\u010d\u0161ina nodov a potvrdila ich. Tak\u00fdmto sp\u00f4sobom, pri existencii troch replik je zaru\u010den\u00e1 \u00fapln\u00e1 a okam\u017eit\u00e1 konzistencia d\u00e1t pri zlyhan\u00ed jedn\u00e9ho nodu. Tento pr\u00edstup n\u00e1m umo\u017enil implementova\u0165 e\u0161te spo\u013eahlivej\u0161\u00ed syst\u00e9m: v\u017edy posiela\u0165 po\u017eiadavky na v\u0161etky tri repliky a \u010daka\u0165 na odpove\u010f od dvoch najr\u00fdchlej\u0161\u00edch. Odpove\u010f tretej repliky, ktor\u00e1 me\u0161k\u00e1, je v takom pr\u00edpade odmietnut\u00e1. Zme\u0161kan\u00fd odpovedaj\u00faci nod m\u00f4\u017ee ma\u0165 pritom v\u00e1\u017ene probl\u00e9my \u2014 oneskorenia, zber odpadu v JVM, priame uvo\u013enenie pam\u00e4te v linuxovom jadre, chyby hardv\u00e9ru, odpojenie od siete. Av\u0161ak to nijako neovplyv\u0148uje oper\u00e1cie klienta a d\u00e1ta.<\/p>\n<p>Pr\u00edstup, pri ktorom komunikujeme s tromi nodami a dost\u00e1vame odpove\u010f od dvoch, sa naz\u00fdva <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Speculative_execution\">\u0161pekul\u00e1cia<\/a><\/noindex>: po\u017eiadavka na zbyto\u010dn\u00e9 repliky sa odosiela e\u0161te predt\u00fdm, ako \"vypadn\u00fa\". <\/p>\n<p>\u010eal\u0161ou z v\u00fdhod Cassandra je Batchlog \u2014 mechanizmus, ktor\u00fd zaru\u010duje bu\u010f \u00fapln\u00fa aplik\u00e1ciu, alebo \u00fapln\u00e9 neprijatie bal\u00edka va\u0161ich zmien. To n\u00e1m umo\u017e\u0148uje vyrie\u0161i\u0165 A v ACID \u2014 atomickos\u0165 priamo z krabice.<\/p>\n<p>Najbli\u017e\u0161ie k transakci\u00e1m v Cassandre s\u00fa takzvan\u00e9 &#171;<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.datastax.com\/en\/cql\/3.3\/cql\/cql_using\/useInsertLWT.html\">\u013eahk\u00e9 transakcie<\/a><\/noindex>&#171;. Av\u0161ak od \u201eskuto\u010dn\u00fdch\u201c ACID transakci\u00ed s\u00fa vzdialen\u00e9: v skuto\u010dnosti ide o mo\u017enos\u0165 uskuto\u010dni\u0165 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Compare-and-swap\">CAS<\/a><\/noindex> na d\u00e1tach len jednej polo\u017eky, vyu\u017e\u00edvaj\u00faca konsenzus prostredn\u00edctvom \u0165a\u017ek\u00e9ho protokolu Paxos. Preto je r\u00fdchlos\u0165 tak\u00fdchto transakci\u00ed n\u00edzka. <\/p>\n<h2>\u010co n\u00e1m ch\u00fdbalo v Cassandre<\/h2>\n<p>\nTak\u017ee sme museli implementova\u0165 v Cassandre skuto\u010dn\u00e9 ACID transakcie. S ich pomocou by sme mohli jednoducho realizova\u0165 dve \u010fal\u0161ie pohodln\u00e9 funkcie klasick\u00fdch DBMS: konzistentn\u00e9 r\u00fdchle indexy, \u010do by n\u00e1m umo\u017enilo vykon\u00e1va\u0165 selekcie d\u00e1t nielen pod\u013ea prim\u00e1rneho k\u013e\u00fa\u010da a be\u017en\u00fd gener\u00e1tor monot\u00f3nnych autoinkrement\u00e1lnych ID.<\/p>\n<h4>C*One<\/h4>\n<p>\nTak sa narodila nov\u00e1 datab\u00e1zov\u00e1 spr\u00e1va <b>C*One<\/b>, zlo\u017een\u00e1 z troch typov serverov\u00fdch nodov:<\/p>\n<ul>\n<li>\u00dalo\u017eisk\u00e1 \u2014 (takmer) \u0161tandardn\u00e9 servery Cassandra, zodpovedaj\u00face za ukladanie d\u00e1t na lok\u00e1lnych diskoch. S rast\u00facim za\u0165a\u017een\u00edm a objemom d\u00e1t je ich po\u010det mo\u017en\u00e9 jednoducho roz\u0161\u00edri\u0165 na desiatky a stovky.<\/li>\n<li>Koordin\u00e1tory transakci \u2013 zabezpe\u010duj\u00fa vykon\u00e1vanie transakci\u00ed. <\/li>\n<li>Klienti \u2013 servery aplik\u00e1ci\u00ed, ktor\u00e9 realizuj\u00fa podnikov\u00e9 oper\u00e1cie a iniciuj\u00fa transakcie. Tak\u00fdchto klientov m\u00f4\u017ee by\u0165 tis\u00edce.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/f3809d89404ae596c62b642dbdb9e431.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nServery v\u0161etk\u00fdch typov s\u00fa s\u00fa\u010das\u0165ou spolo\u010dn\u00e9ho klastru, pou\u017e\u00edvaj\u00fa intern\u00fd protokol spr\u00e1v Cassandra na vz\u00e1jomn\u00fa komunik\u00e1ciu a <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">gossip<\/a><\/noindex> na v\u00fdmenu klastrick\u00fdch inform\u00e1ci\u00ed. S pomocou Heartbeat sa servery dozvedaj\u00fa o vz\u00e1jomn\u00fdch zlyhaniach, udr\u017eiavaj\u00fa jednotn\u00fa sch\u00e9mu d\u00e1t \u2013 tabu\u013eky, ich \u0161trukt\u00faru a replik\u00e1ciu; sch\u00e9mu partitioning, topol\u00f3giu klastru at\u010f.<\/p>\n<h4>Klienti<\/h4>\n<p>\n<img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/80f83358f215cf59db3b657ba1083420.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNamiesto \u0161tandardn\u00fdch ovl\u00e1da\u010dov sa pou\u017e\u00edva re\u017eim Fat Client. Tak\u00e1to noda neuchov\u00e1va d\u00e1ta, ale m\u00f4\u017ee fungova\u0165 ako koordin\u00e1tor vykon\u00e1vania po\u017eiadaviek, teda klient s\u00e1m vykon\u00e1va funkciu koordin\u00e1tora svojich po\u017eiadaviek: dotazuje repliky \u00falo\u017eiska a rie\u0161i konflikty. To je nielen spo\u013eahlivej\u0161ie a r\u00fdchlej\u0161ie ako \u0161tandardn\u00fd ovl\u00e1da\u010d, ktor\u00fd si vy\u017eaduje komunik\u00e1ciu s vzdialen\u00fdm koordin\u00e1torom, ale aj umo\u017e\u0148uje spravova\u0165 prenos po\u017eiadaviek. Mimo otvorenej transakcie na klientovi sa po\u017eiadavky smeruj\u00fa do \u00falo\u017e\u00edsk. Ak klient otvoril transakciu, v\u0161etky po\u017eiadavky v r\u00e1mci transakcie sa smeruj\u00fa k koordin\u00e1torovi transakci\u00ed.<br \/>\n<img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/709bf227eeb8f71abeff703a72780efd.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Koordin\u00e1tor transakci\u00ed C*One<\/h2>\n<p>\nKoordin\u00e1tor \u2013 to, \u010do sme realizovali pre C*One od z\u00e1kladov. Zodpoved\u00e1 za spr\u00e1vu transakci\u00ed, blokovania a poradia aplikovania transakci\u00ed.<\/p>\n<p>Pre ka\u017ed\u00fa obsluhovan\u00fa transakciu koordin\u00e1tor generuje \u010dasov\u00fa zna\u010dku: ka\u017ed\u00e1 nasleduj\u00faca je v\u00e4\u010d\u0161ia ako u predch\u00e1dzaj\u00facej transakcie. Ke\u010f\u017ee v Cassandre je syst\u00e9m rie\u0161enia konfliktov zalo\u017een\u00fd na \u010dasov\u00fdch zna\u010dk\u00e1ch (z dvoch konfliktuj\u00facich z\u00e1znamov je aktu\u00e1lny ten s neskor\u0161ou \u010dasovou zna\u010dkou), konflikt bude v\u017edy vyrie\u0161en\u00fd v prospech nasleduj\u00facej transakcie. Takto sme realizovali <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A7%D0%B0%D1%81%D1%8B_%D0%9B%D1%8D%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D0%B0\">Lamportove hodiny<\/a><\/noindex> \u2013 lacn\u00fd sp\u00f4sob rie\u0161enia konfliktov v distribuovanom syst\u00e9me.<\/p>\n<h2>Blokovania<\/h2>\n<p>\nNa zabezpe\u010denie izol\u00e1cie sme sa rozhodli pou\u017ei\u0165 najjednoduch\u0161\u00ed sp\u00f4sob \u2013 pesimistick\u00e9 blokovania pod\u013ea prim\u00e1rneho k\u013e\u00fa\u010da z\u00e1znamu. In\u00fdmi slovami, v transakcii je z\u00e1znam najprv potrebn\u00e9 zablokova\u0165, a\u017e potom pre\u010d\u00edta\u0165, modifikova\u0165 a ulo\u017ei\u0165. A\u017e po \u00faspe\u0161nom potvrden\u00ed m\u00f4\u017ee by\u0165 z\u00e1znam odblokovan\u00fd, aby konkuruj\u00face transakcie mohli jeho pou\u017e\u00edva\u0165.<\/p>\n<p>Implement\u00e1cia tak\u00e9hoto blokovania je jednoduch\u00e1 v nedistribuovanej prostred\u00ed. V distribuovanej s\u00fastave s\u00fa dva hlavn\u00e9 pr\u00edstupy: bu\u010f implementova\u0165 distribuovan\u00e9 blokovanie na klastre, alebo rozlo\u017ei\u0165 transakcie tak, aby transakcie t\u00fdkaj\u00face sa tej istej polo\u017eky v\u017edy spracov\u00e1val ten ist\u00fd koordin\u00e1tor.<\/p>\n<p>Ke\u010f\u017ee v na\u0161om pr\u00edpade s\u00fa \u00fadaje u\u017e rozdelen\u00e9 do skup\u00edn lok\u00e1lnych transakci\u00ed v SQL, rozhodlo sa priradi\u0165 koordin\u00e1torom skupiny lok\u00e1lnych transakci\u00ed: jeden koordin\u00e1tor vykon\u00e1va v\u0161etky transakcie s tokenom od 0 do 9, druh\u00fd \u2013 s tokenom od 10 do 19 a tak \u010falej. V d\u00f4sledku toho sa ka\u017ed\u00fd z in\u0161tanci\u00ed koordin\u00e1tora st\u00e1va majstrom skupiny transakci\u00ed. <\/p>\n<p>Vtedy m\u00f4\u017eu by\u0165 blokovania realizovan\u00e9 vo forme oby\u010dajn\u00e9ho HashMap v pam\u00e4ti koordin\u00e1tora.<\/p>\n<h2>Zlyhania koordin\u00e1torov<\/h2>\n<p>\nKe\u010f\u017ee jeden koordin\u00e1tor obsluhuje v\u00fdlu\u010dne skupinu transakci\u00ed, je ve\u013emi d\u00f4le\u017eit\u00e9 r\u00fdchlo ur\u010di\u0165 fakt jeho zlyhania, aby op\u00e4tovn\u00fd pokus o vykonanie transakcie spadal do \u010dasov\u00e9ho limitu. Aby to bolo r\u00fdchle a spo\u013eahliv\u00e9, pou\u017eili sme plne prepojen\u00fd kvorumov\u00fd heartbeat protokol:<\/p>\n<p>V ka\u017edom d\u00e1tovom centre sa umiest\u0148uje minim\u00e1lne dve uzly koordin\u00e1tora. Pravidelne ka\u017ed\u00fd koordin\u00e1tor posiela heartbeat spr\u00e1vu ostatn\u00fdm koordin\u00e1torom a informuje ich o svojom fungovan\u00ed, ako aj o tom, ktor\u00e9 heartbeat spr\u00e1vy dostal naposledy od ak\u00fdch koordin\u00e1torov v klastri. <\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/5c337e53815cad0a2071b160d98d42fa.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZ\u00edskan\u00edm podobn\u00fdch inform\u00e1ci\u00ed od ostatn\u00fdch v r\u00e1mci ich heartbeat spr\u00e1v, sa ka\u017ed\u00fd koordin\u00e1tor rozhoduje, ktor\u00e9 uzly klastra funguj\u00fa a ktor\u00e9 nie, riadiac sa princ\u00edpom kvorum: ak uzol X obdr\u017eal od v\u00e4\u010d\u0161iny uzlov v klastri inform\u00e1ciu o norm\u00e1lnom prij\u00edman\u00ed spr\u00e1v z uzla Y, znamen\u00e1 to, \u017ee Y funguje. A naopak, ak v\u00e4\u010d\u0161ina ozn\u00e1mi, \u017ee neobdr\u017eala spr\u00e1vy z uzla Y, znamen\u00e1 to, \u017ee Y zlyhal. Zauj\u00edmav\u00e9 je, \u017ee ak kvorum ozn\u00e1mi uzlu X, \u017ee od neho u\u017e viac spr\u00e1v nedost\u00e1va, uzol X sa s\u00e1m pova\u017euje za zlyhan\u00fd.<\/p>\n<p>Heartbeat spr\u00e1vy sa posielaj\u00fa s vysokou frekvenciou, pribli\u017ene 20-kr\u00e1t za sekundu, s peri\u00f3dou 50 ms. V Jave je \u0165a\u017ek\u00e9 zaru\u010di\u0165 odpove\u010f aplik\u00e1cie v priebehu 50 ms kv\u00f4li porovnate\u013enej d\u013a\u017eke pauz sp\u00f4soben\u00fdch garbage collectorom. Podarilo sa n\u00e1m dosiahnu\u0165 tak\u00fd \u010das odpovede pomocou garbage collectora G1, ktor\u00fd umo\u017e\u0148uje nastavit cie\u013e pre trvanie GC pauz. Av\u0161ak, niekedy, dos\u0165 zriedkavo, pauzy garbage collectora presahuj\u00fa 50 ms, \u010do m\u00f4\u017ee vies\u0165 k falo\u0161n\u00e9mu zisteniu poruchy. Aby k tomu nedo\u0161lo, koordin\u00e1tor nenahl\u00e1si poruchu vzdialenej nody pri strate prv\u00e9ho heartbeat spr\u00e1v od nej, iba ak sa strat\u00ed nieko\u013eko po sebe id\u00facich. Tak sme sa dok\u00e1zali dosta\u0165 k detekcii poruchy nody koordin\u00e1tora za 200 ms. <\/p>\n<p>Ale je tie\u017e d\u00f4le\u017eit\u00e9 r\u00fdchlo zisti\u0165, ktor\u00e1 noda prestala fungova\u0165. Je potrebn\u00e9 s t\u00fdm nie\u010do urobi\u0165. <\/p>\n<h2>Z\u00e1lohovanie<\/h2>\n<p>\nKlasick\u00e1 sch\u00e9ma predpoklad\u00e1, \u017ee v pr\u00edpade poruchy majstra sa spust\u00ed vo\u013eba nov\u00e9ho pomocou jedn\u00e9ho z<noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_Raft\"> modern\u00fdch<\/a><\/noindex> <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9F%D0%B0%D0%BA%D1%81%D0%BE%D1%81\">univerz\u00e1lnych<\/a><\/noindex> algoritmov. Av\u0161ak, tak\u00e9to algoritmy maj\u00fa dobre zn\u00e1me probl\u00e9my so zbiehan\u00edm v \u010dase a d\u013a\u017ekou samotn\u00e9ho procesu volieb. Tak\u00e9to dodato\u010dn\u00e9 oneskorenia sme dok\u00e1zali ob\u00eds\u0165 pomocou sch\u00e9my n\u00e1hrady koordin\u00e1torov v plne prepojenej sieti:<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/5e2db258fa2200026390a73a414dfe81.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPredpokladajme, \u017ee chceme vykona\u0165 transakciu v skupine 50. Vopred ur\u010d\u00edme sch\u00e9mu n\u00e1hrady, to znamen\u00e1, ktor\u00e9 nody bud\u00fa vykon\u00e1va\u0165 transakcie skupiny 50 v pr\u00edpade poruchy hlavn\u00e9ho koordin\u00e1tora. Na\u0161\u00edm cie\u013eom je zachova\u0165 funk\u010dnos\u0165 syst\u00e9mu pri poruche d\u00e1tov\u00e9ho centra. Ur\u010d\u00edme, \u017ee prvou rezervou bude noda z in\u00e9ho d\u00e1tov\u00e9ho centra a druhou rezervou bude noda z tretieho. T\u00e1to sch\u00e9ma sa vyber\u00e1 raz a nemen\u00ed sa, k\u00fdm sa nezmen\u00ed topol\u00f3gia klastru, to znamen\u00e1, k\u00fdm sa do neho nepridaj\u00fa nov\u00e9 nody (\u010do sa st\u00e1va ve\u013emi zriedkavo). Poradie vo\u013eby nov\u00e9ho akt\u00edvneho majstra pri poruche star\u00e9ho bude v\u017edy tak\u00e9to: akt\u00edvnym majstrom sa stane prv\u00e1 rezerva, a ak aj t\u00e1 prestala fungova\u0165 \u2013 druh\u00e1 rezerva. <\/p>\n<p>Tak\u00e1to sch\u00e9ma je spo\u013eahlivej\u0161ia ako univerz\u00e1lny algoritmus, preto\u017ee na aktiv\u00e1ciu nov\u00e9ho majstra sta\u010d\u00ed ur\u010denie faktu poruchy star\u00e9ho.<\/p>\n<p>Ale ako maj\u00fa klienti pochopi\u0165, ktor\u00fd z majstrov pr\u00e1ve pracuje? Za 50 ms nie je mo\u017en\u00e9 rozosla\u0165 inform\u00e1cie tis\u00edckam klientov. M\u00f4\u017ee vznikn\u00fa\u0165 situ\u00e1cia, ke\u010f klient po\u0161le \u017eiados\u0165 o otvorenie transakcie, e\u0161te nevediac, \u017ee tento majster u\u017e nefunguje, a \u017eiados\u0165 sa zablokuje na timeout. Aby sa tomu predi\u0161lo, klienti \u0161pekulat\u00edvne posielaj\u00fa \u017eiados\u0165 o otvorenie transakcie priamo majstrovi skupiny a jeho obom rezerv\u00e1m, ale odpovie na t\u00fato \u017eiados\u0165 iba ten, kto je v danom momente akt\u00edvnym majstrom. Cel\u00fa n\u00e1sledn\u00fa komunik\u00e1ciu v r\u00e1mci transakcie klient vykon\u00e1va iba s akt\u00edvnym majstrom.<\/p>\n<p>Rezervn\u00ed majstri prijat\u00e9 \u017eiadosti o nie svoje transakcie umiest\u0148uj\u00fa do fronty nenaroden\u00fdch transakci\u00ed, kde zost\u00e1vaj\u00fa nejak\u00fd \u010das. Ak akt\u00edvny majster zomrie, nov\u00fd majster sprac\u00fava \u017eiadosti o otvorenie transakci\u00ed zo svojej fronty a odpoved\u00e1 klientovi. Ak klient u\u017e stihol otvori\u0165 transakciu so star\u00fdm majstrom, druh\u00e1 odpove\u010f sa ignoruje (a, samozrejme, tak\u00e1 transakcia sa neskon\u010d\u00ed a bude opakovan\u00e1 klientom).<\/p>\n<h2>Ako funguje transakcia<\/h2>\n<p>\nPovedzme, \u017ee klient poslal koordin\u00e1torovi \u017eiados\u0165 o otvorenie transakcie pre ur\u010dit\u00fa entitu s ur\u010dit\u00fdm prim\u00e1rnym k\u013e\u00fa\u010dom. Koordin\u00e1tor t\u00fato entitu zablokuje a umiestni ju do tabu\u013eky blok\u00e1d v pam\u00e4ti. Ak je to potrebn\u00e9, koordin\u00e1tor na\u010d\u00edta t\u00fato entitu zo skladu a ulo\u017e\u00ed z\u00edskan\u00e9 \u00fadaje do stavu transakcie v pam\u00e4ti koordin\u00e1tora.<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/246b4a5c68a4cc886b87af784c16b9dc.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKe\u010f klient chce zmeni\u0165 \u00fadaje v transakcii, po\u0161le koordin\u00e1torovi \u017eiados\u0165 o modifik\u00e1ciu entity, a ten umiestni nov\u00e9 \u00fadaje do tabu\u013eky stavu transakci\u00ed v pam\u00e4ti. T\u00fdmto sa z\u00e1pis uzaviera \u2014 z\u00e1pis do skladu sa neuskuto\u010d\u0148uje.<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/4400a91af30eb71134978ff27474f745.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKe\u010f klient vy\u017eaduje v r\u00e1mci akt\u00edvnej transakcie svoje vlastn\u00e9 zmenen\u00e9 \u00fadaje, koordin\u00e1tor postupuje takto: <\/p>\n<ul>\n<li>ak ID u\u017e existuje v transakcii, \u00fadaje sa ber\u00fa z pam\u00e4te; <\/li>\n<li>ak ID v pam\u00e4ti nie je, ch\u00fdbaj\u00face \u00fadaje sa na\u010d\u00edtaj\u00fa z uzlov\u00fdch skladov, skombinuj\u00fa sa s u\u017e existuj\u00facimi v pam\u00e4ti a v\u00fdsledok sa odovzd\u00e1 klientovi. <\/li>\n<\/ul>\n<p>\nTakto m\u00f4\u017ee klient pre\u010d\u00edta\u0165 svoje vlastn\u00e9 zmeny, zatia\u013e \u010do in\u00ed klienti tieto zmeny nevidia, preto\u017ee s\u00fa ulo\u017een\u00e9 iba v pam\u00e4ti koordin\u00e1tora, v uzloch Cassandra ich e\u0161te niet.<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/c93fd7e8393f431a976f1f56b95e227c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKe\u010f klient odo\u0161le commit, stav, ktor\u00fd mal slu\u017eba v pam\u00e4ti, je koordin\u00e1torom ulo\u017een\u00fd do logged batch a u\u017e v podobe logged batch odoslan\u00fd do \u00falo\u017e\u00edsk Cassandra. \u00dalo\u017eisk\u00e1 robia v\u0161etko potrebn\u00e9, aby bol tento bal\u00edk atom\u00e1rne (\u00faplne) aplikovan\u00fd, a vracaj\u00fa odpove\u010f koordin\u00e1torovi, ktor\u00fd potom uvo\u013en\u00ed z\u00e1mky a potvrd\u00ed \u00faspe\u0161nos\u0165 transakcie klientovi.<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/ab20487ba53ed88e2f560a2249b5d6f9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA pre vr\u00e1tenie koordin\u00e1torovi sta\u010d\u00ed len uvo\u013eni\u0165 pam\u00e4\u0165, ktor\u00fa zaberalo stav transakcie.<\/p>\n<p>V d\u00f4sledku vy\u0161\u0161ie pop\u00edsan\u00fdch vylep\u0161en\u00ed sme implementovali princ\u00edpy ACID:<\/p>\n<ul>\n<li><b>Atomarita<\/b>. To je z\u00e1ruka, \u017ee \u017eiadna transakcia nebude v syst\u00e9me zaznamenan\u00e1 \u010diasto\u010dne, bu\u010f bud\u00fa vykonan\u00e9 v\u0161etky jej podoper\u00e1cie, alebo sa nevykon\u00e1 ani jedna. U n\u00e1s tento princ\u00edp je dodr\u017eiavan\u00fd v\u010faka logged batch v Cassandre.<\/li>\n<li><b>Konzistencia<\/b>. Ka\u017ed\u00e1 \u00faspe\u0161n\u00e1 transakcia pod\u013ea defin\u00edcie zaznamen\u00e1va iba pr\u00edpustn\u00e9 v\u00fdsledky. Ak sa po otvoren\u00ed transakcie a vykonan\u00ed \u010dasti oper\u00e1ci\u00ed zist\u00ed, \u017ee v\u00fdsledok je nepr\u00edpustn\u00fd, vykon\u00e1 sa vr\u00e1tenie.<\/li>\n<li><b>Izolovanos\u0165<\/b>. Pri vykon\u00e1van\u00ed transakcie paraleln\u00e9 transakcie nesm\u00fa ovplyvni\u0165 jej v\u00fdsledok. S\u00fa\u0165a\u017en\u00e9 transakcie s\u00fa izolovan\u00e9 pomocou pesimistick\u00fdch z\u00e1mkov na koordin\u00e1torovi. Pre \u010d\u00edtania mimo transakcie sa dodr\u017eiava princ\u00edp izolovanosti na \u00farovni Read Committed.<\/li>\n<li><b>Trv\u00e1cnos\u0165<\/b>. Nez\u00e1visle od probl\u00e9mov na ni\u017e\u0161\u00edch \u00farovniach \u2014 v\u00fdpadok syst\u00e9mu, porucha hardv\u00e9ru \u2014 zmeny vykonan\u00e9 \u00faspe\u0161ne dokon\u010denou transakciou musia zosta\u0165 ulo\u017een\u00e9 po obnoven\u00ed fungovania. <\/li>\n<\/ul>\n<p><\/p>\n<h2>\u010c\u00edtanie pod\u013ea indexov<\/h2>\n<p>\nVezmime si jednoduch\u00fa tabu\u013eku: <\/p>\n<pre><code>CREATE TABLE photos (\nid bigint primary key,\nowner bigint,\nmodified timestamp,\n\u2026)<\/code><\/pre>\n<p>\nM\u00e1 ID (prim\u00e1rny k\u013e\u00fa\u010d), vlastn\u00edka a d\u00e1tum zmeny. Potrebujeme vykona\u0165 ve\u013emi jednoduch\u00fd dotaz \u2014 vybra\u0165 \u00fadaje pod\u013ea vlastn\u00edka s d\u00e1tumom zmeny \u201eza posledn\u00fdch 24 hod\u00edn\u201c. <\/p>\n<pre><code>SELECT *\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nAby sa tak\u00fdto dotaz vykonal r\u00fdchlo, v klasickej SQL DBMS je potrebn\u00e9 vytvori\u0165 index pod\u013ea st\u013apcov (owner, modified). Nie\u010do tak\u00e9 m\u00f4\u017eeme urobi\u0165 celkom jednoducho, preto\u017ee teraz m\u00e1me z\u00e1ruky ACID!<\/p>\n<h2>Indexy v C*One<\/h2>\n<p>\nExistuje p\u00f4vodn\u00e1 tabu\u013eka s fotografiami, v ktorej je ID z\u00e1znamu prim\u00e1rnym k\u013e\u00fa\u010dom. <\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/9f5d7c5f66882666a7ae8219f710beeb.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPre syst\u00e9m C*One sa vytv\u00e1ra nov\u00e1 tabu\u013eka, ktor\u00e1 je k\u00f3piou p\u00f4vodnej. K\u013e\u00fa\u010d sa zhoduje s indexov\u00fdm v\u00fdrazom a zah\u0155\u0148a aj prim\u00e1rny k\u013e\u00fa\u010d z\u00e1znamu z p\u00f4vodnej tabu\u013eky.<\/p>\n<p><img decoding=\"async\" alt=\"NewSQL = NoSQL+ACID\" src=\"\/wp-content\/uploads\/2019\/09\/ce6df1c8407bca7ddc61fd88141455e6.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDotaz na \u201emajite\u013ea za posledn\u00fdch 24 hod\u00edn\u201c teraz m\u00f4\u017eeme prep\u00edsa\u0165 ako select z inej tabu\u013eky:<\/p>\n<pre><code>SELECT * FROM i1_test\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nKonzistencia \u00fadajov p\u00f4vodnej tabu\u013eky photos a indexnej tabu\u013eky i1 je automaticky udr\u017eiavan\u00e1 koordin\u00e1torom. Na z\u00e1klade samotnej sch\u00e9my \u00fadajov pri obdr\u017ean\u00ed zmeny koordin\u00e1tor generuje a uchov\u00e1va zmenu nielen pre hlavn\u00fa tabu\u013eku, ale aj pre zmeny k\u00f3pi\u00ed. Nebud\u00fa vykon\u00e1van\u00e9 \u017eiadne \u010fal\u0161ie akcie s indexovou tabu\u013ekou, logy sa ne\u010d\u00edtaj\u00fa, z\u00e1mky sa nepou\u017e\u00edvaj\u00fa. To znamen\u00e1, \u017ee prid\u00e1vanie indexov takmer nespotrebov\u00e1va zdroje a prakticky neovplyv\u0148uje r\u00fdchlos\u0165 aplik\u00e1cie modifik\u00e1ci\u00ed.<\/p>\n<p>S pomocou ACID sa n\u00e1m podarilo implementova\u0165 indexy \u201eako v SQL\u201c. Tieto indexy maj\u00fa konzistenciu, m\u00f4\u017eu by\u0165 \u0161k\u00e1lovate\u013en\u00e9, funguj\u00fa r\u00fdchlo, m\u00f4\u017eu by\u0165 zlo\u017een\u00e9 a s\u00fa integrovan\u00e9 do jazyka dotazov CQL. Na podporu indexov nie je potrebn\u00e9 meni\u0165 aplika\u010dn\u00fd k\u00f3d. V\u0161etko je jednoduch\u00e9, ako v SQL. A \u010do je najd\u00f4le\u017eitej\u0161ie, indexy neovplyv\u0148uj\u00fa r\u00fdchlos\u0165 vykon\u00e1vania modifik\u00e1ci\u00ed p\u00f4vodnej tabu\u013eky transakci\u00ed.<\/p>\n<h2>\u010co sa podarilo<\/h2>\n<p>\nC*One sme vyvinuli pred tromi rokmi a uviedli do komer\u010dnej prev\u00e1dzky. <\/p>\n<p>Ak\u00fd v\u00fdsledok sme teda dosiahli? Pos\u00fa\u010fme to na pr\u00edklade subsyst\u00e9mu spracovania a ukladania fotografi\u00ed, jedn\u00e9ho z najd\u00f4le\u017eitej\u0161\u00edch typov \u00fadajov v soci\u00e1lne sieti. Hovor\u00edme nielen o samotn\u00fdch sn\u00edmkach, ale aj o r\u00f4znych metainform\u00e1ci\u00e1ch. V s\u00fa\u010dasnosti v \u201eOdnoklassnikoch\u201c existuje pribli\u017ene 20 mili\u00e1rd tak\u00fdchto z\u00e1znamov, syst\u00e9m spracov\u00e1va 80 000 dotazov na \u010d\u00edtanie za sekundu, do 8 000 ACID transakci\u00ed za sekundu t\u00fdkaj\u00facich sa modifik\u00e1cie \u00fadajov. <\/p>\n<p>Ke\u010f sme pou\u017e\u00edvali SQL s faktorom replik\u00e1cie = 1 (ale v RAID 10), metainform\u00e1cie o fotografi\u00e1ch sa ukladali na vysoko dostupnom klastri zo 32 strojov s Microsoft SQL Serverom (plus 11 z\u00e1lo\u017en\u00fdch). Takisto bolo vy\u010dlenen\u00fdch 10 serverov na ukladanie z\u00e1loh. Celkovo teda 50 n\u00e1kladn\u00fdch strojov. Syst\u00e9m pritom pracoval s nomin\u00e1lnym za\u0165a\u017een\u00edm, bez rezervy.<\/p>\n<p>Po migr\u00e1cii na nov\u00fd syst\u00e9m sme dosiahli faktor replik\u00e1cie = 3 \u2014 po k\u00f3pii v ka\u017edom d\u00e1tovom centre. Syst\u00e9m pozost\u00e1va z 63 uzlov \u00falo\u017eiska Cassandra a 6 strojov koordin\u00e1torov, teda dokopy 69 serverov. Tieto stroje s\u00fa v\u0161ak v\u00fdrazne lacnej\u0161ie, ich celkov\u00e1 cena predstavuje pribli\u017ene 30 % ceny syst\u00e9mu na SQL. Z\u00e1rove\u0148 sa za\u0165a\u017eenos\u0165 udr\u017euje na \u00farovni 30 %.<\/p>\n<p>S implement\u00e1ciou C*One klesli aj oneskorenia: v SQL oper\u00e1cia z\u00e1pisu trvala pribli\u017ene 4,5 ms. V C*One \u2014 pribli\u017ene 1,6 ms. D\u013a\u017eka transakcie je v priemere krat\u0161ia ako 40 ms, commit sa vykon\u00e1va za 2 ms, d\u013a\u017eka \u010d\u00edtania a z\u00e1pisu \u2014 v priemere 2 ms. 99. percentil \u2014 len 3-3,1 ms, po\u010det timeoutov klesol stokr\u00e1t \u2014 v\u0161etko v\u010faka \u0161irok\u00e9mu vyu\u017e\u00edvaniu \u0161pekul\u00e1ci\u00ed. <\/p>\n<p>K s\u00fa\u010dasn\u00e9mu momentu bola z prev\u00e1dzky vypusten\u00e1 v\u00e4\u010d\u0161ina uzlov SQL Server, nov\u00e9 produkty sa vyv\u00edjaj\u00fa len s vyu\u017eit\u00edm C*One. Prisp\u00f4sobili sme C*One na pr\u00e1cu v na\u0161om cloude. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/odnoklassniki\/blog\/346868\/\">one-cloud<\/a><\/noindex>, \u010do umo\u017enilo ur\u00fdchli\u0165 nasadenie nov\u00fdch klastrov, zjednodu\u0161i\u0165 konfigur\u00e1ciu a automatizova\u0165 prev\u00e1dzku. Bez zdrojov\u00e9ho k\u00f3du by to bolo podstatne zlo\u017eitej\u0161ie a krkolomne. <\/p>\n<p>V s\u00fa\u010dasnosti pracujeme na migr\u00e1cii na\u0161ich \u010fal\u0161\u00edch \u00falo\u017e\u00edsk do cloudu \u2014 ale to je u\u017e \u00faplne in\u00fd pr\u00edbeh.<br \/>\n<br \/>Zdroj: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/odnoklassniki\/blog\/417593\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0414\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u043e\u043a\u043e\u043b\u043e 50 \u0422\u0411 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0445\u0440\u0430\u043d\u0438\u043b\u043e\u0441\u044c \u0432 SQL Server. \u0414\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043c\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439, \u0434\u0430 \u0435\u0449\u0435 \u0438 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u0439 \u043a \u043e\u0442\u043a\u0430\u0437\u0443 \u0426\u041e\u0414 \u0434\u043e\u0441\u0442\u0443\u043f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f SQL \u0421\u0423\u0411\u0414, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u041e\u0431\u044b\u0447\u043d\u043e \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u043d\u043e \u0438\u0437 NoSQL-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449, \u043d\u043e \u043d\u0435 \u0432\u0441\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0432 NoSQL: \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28484,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-37956","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0414\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u043e\u043a\u043e\u043b\u043e 50 \u0422\u0411 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/newsql-nosql-acid\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"sk_SK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47NewSQL = NoSQL+ACID | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0414\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u043e\u043a\u043e\u043b\u043e 50 \u0422\u0411 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/newsql-nosql-acid\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:20:47+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:20:47+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47NewSQL = NoSQL+ACID | ProHoster","description":"Do ned\u00e1vna sa v Odnoklassnikach spracov\u00e1valo pribli\u017ene 50 TB d\u00e1t.","canonical_url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/newsql-nosql-acid","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sk_SK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47NewSQL = NoSQL+ACID | ProHoster","og:description":"\u0414\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u043e\u043a\u043e\u043b\u043e 50 \u0422\u0411 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445.","og:url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/newsql-nosql-acid","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:20:47+00:00","article:modified_time":"2019-10-31T19:20:47+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"37956","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 19:55:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:17:23","updated":"2026-01-23 19:55:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media\/28484"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}