{"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\/cs\/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 bylo v Odnoklassnik\u00e1ch kolem 50 TB dat, kter\u00e1 se zpracov\u00e1vala v re\u00e1ln\u00e9m \u010dase, ulo\u017eeno v SQL Serveru. Zajistit rychl\u00fd, spolehliv\u00fd a z\u00e1rove\u0148 odoln\u00fd p\u0159\u00edstup k datov\u00e9mu centru pro takov\u00e9 objemy pomoc\u00ed SQL DB je prakticky nemo\u017en\u00e9. Obvykle se v takov\u00fdch p\u0159\u00edpadech pou\u017e\u00edv\u00e1 jedno z NoSQL ulo\u017ei\u0161\u0165, ale ne v\u0161echno lze p\u0159ev\u00e9st do NoSQL: n\u011bkter\u00e9 entity vy\u017eaduj\u00ed z\u00e1ruky ACID transakc\u00ed. <\/p>\n<p>To n\u00e1s p\u0159ivedlo k pou\u017eit\u00ed NewSQL ulo\u017ei\u0161t\u011b, tedy DBMS, kter\u00e1 poskytuje odolnost, \u0161k\u00e1lovatelnost a rychlost NoSQL syst\u00e9m\u016f a p\u0159itom zachov\u00e1v\u00e1 zn\u00e1m\u00e9 ACID z\u00e1ruky klasick\u00fdch syst\u00e9m\u016f. Funk\u010dn\u00edch pr\u016fmyslov\u00fdch syst\u00e9m\u016f t\u00e9to nov\u00e9 t\u0159\u00eddy je m\u00e1lo, proto jsme takov\u00fd syst\u00e9m sami realizovali a uvedli ho do pr\u016fmyslov\u00e9ho provozu. <\/p>\n<p>Jak to funguje a co se poda\u0159ilo \u2014 \u010dt\u011bte pod odkazem.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nDnes m\u011bs\u00ed\u010dn\u00ed publikum \u201eOdnoklassnikov\u201c \u010din\u00ed v\u00edce ne\u017e 70 milion\u016f unik\u00e1tn\u00edch n\u00e1v\u0161t\u011bvn\u00edk\u016f. My <noindex><a rel=\"nofollow\" href=\"https:\/\/www.similarweb.com\/top-websites\/category\/internet-and-telecom\/social-network\">jsme v top p\u011bti<\/a><\/noindex> nejv\u011bt\u0161\u00edch soci\u00e1ln\u00edch s\u00edt\u00ed sv\u011bta a v prvn\u00ed dvac\u00edtce web\u016f, na kter\u00fdch u\u017eivatel\u00e9 tr\u00e1v\u00ed nejv\u00edce \u010dasu. Infrastruktura \u201eOK\u201c zpracov\u00e1v\u00e1 velmi vysok\u00e9 z\u00e1t\u011b\u017ee: v\u00edce ne\u017e milion HTTP po\u017eadavk\u016f za sekundu na fronty. \u010c\u00e1sti serverov\u00e9ho parku o v\u00edce ne\u017e 8000 kusech jsou um\u00edst\u011bny bl\u00edzko sebe \u2014 ve \u010dty\u0159ech moskevsk\u00fdch datov\u00fdch centrech, co\u017e umo\u017e\u0148uje zajistit s\u00ed\u0165ovou latenci ni\u017e\u0161\u00ed ne\u017e 1 ms mezi nimi.<\/p>\n<p>Pou\u017e\u00edv\u00e1me Cassandru od roku 2010, po\u010d\u00ednaje verz\u00ed 0.6. Dnes m\u00e1me v provozu n\u011bkolik des\u00edtek cluster\u016f. Nejrychlej\u0161\u00ed cluster zpracov\u00e1v\u00e1 v\u00edce ne\u017e 4 miliony operac\u00ed za sekundu, zat\u00edmco nejv\u011bt\u0161\u00ed uchov\u00e1v\u00e1 260 TB. <\/p>\n<p>Nicm\u00e9n\u011b to v\u0161e jsou b\u011b\u017en\u00e9 NoSQL clustery, kter\u00e9 se pou\u017e\u00edvaj\u00ed k ukl\u00e1d\u00e1n\u00ed <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\">slab\u011b konsolidovan\u00fdch<\/a><\/noindex> dat. My jsme cht\u011bli nahradit hlavn\u00ed konzistentn\u00ed \u00falo\u017ei\u0161t\u011b, Microsoft SQL Server, kter\u00e9 bylo pou\u017e\u00edv\u00e1no od zalo\u017een\u00ed \u201eOdnoklassnikov\u201c. \u00dalo\u017ei\u0161t\u011b se skl\u00e1dalo z v\u00edce ne\u017e 300 stroj\u016f v edici SQL Server Standard, kter\u00e9 uchov\u00e1valy 50 TB dat \u2014 obchodn\u00edch entit. Tato data se modifikuj\u00ed v r\u00e1mci ACID transakc\u00ed a vy\u017eaduj\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">vysokou konzistenci.<\/a><\/noindex>.<\/p>\n<p>Pro rozd\u011blen\u00ed dat mezi uzly SQL Serveru jsme pou\u017eili jak vertik\u00e1ln\u00ed, tak horizont\u00e1ln\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Partition_(database)\">particionov\u00e1n\u00ed.<\/a><\/noindex> (sharding). Historicky jsme pou\u017e\u00edvali jednoduch\u00e9 sch\u00e9ma 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 souhlasily a nach\u00e1zely se na jednom serveru. V soci\u00e1ln\u00ed s\u00edti v\u011bt\u0161inu z\u00e1znam\u016f vytv\u00e1\u0159\u00ed u\u017eivatel \u2014 to znamen\u00e1, \u017ee v\u0161echna data u\u017eivatele v r\u00e1mci jedn\u00e9 funk\u010dn\u00ed podsyst\u00e9mu jsou ulo\u017eena na jednom serveru. To znamen\u00e1, \u017ee v obchodn\u00ed transakci se t\u00e9m\u011b\u0159 v\u017edy \u00fa\u010dastnily tabulky jednoho SQL serveru, co\u017e umo\u017enilo zajistit konzistenci dat pomoc\u00ed m\u00edstn\u00edch ACID transakc\u00ed, bez pot\u0159eby pou\u017eit\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">pomal\u00fdch a nespolehliv\u00fdch<\/a><\/noindex> rozlo\u017een\u00fdch ACID transakc\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 b\u00fdt ID entity um\u00edst\u011bno 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 datab\u00e1zov\u00e9ho syst\u00e9mu.<\/li>\n<li>Nepou\u017e\u00edv\u00e1me JOINy z d\u016fvodu v\u0161ech v\u00fd\u0161e uveden\u00fdch v\u011bc\u00ed a mno\u017estv\u00ed n\u00e1hodn\u00fdch \u010dten\u00ed z disku.<\/li>\n<li>Mimo transakce 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 vykon\u00e1v\u00e1me pouze podle index\u016f \u2014 dotaz s pl\u00e1nem pro \u00fapln\u00fd pohled na tabulku pro n\u00e1s znamen\u00e1 p\u0159et\u00ed\u017een\u00ed datab\u00e1ze a jej\u00ed selh\u00e1n\u00ed.<\/li>\n<\/ul>\n<p>\nTyto kroky umo\u017enily vyt\u011b\u017eit z SQL server\u016f t\u00e9m\u011b\u0159 maxim\u00e1ln\u00ed v\u00fdkon. Av\u0161ak probl\u00e9m\u016f p\u0159ib\u00fdvalo. Poj\u010fme se na n\u011b pod\u00edvat.<\/p>\n<h2>Probl\u00e9my se SQL<\/h2>\n<p><\/p>\n<ul>\n<li>Jeliko\u017e jsme pou\u017e\u00edvali vlastn\u00ed shardov\u00e1n\u00ed, p\u0159id\u00e1v\u00e1n\u00ed nov\u00fdch shard\u016f prov\u00e1d\u011bli administr\u00e1to\u0159i ru\u010dn\u011b. Po celou tu dobu \u0161k\u00e1lovateln\u00e9 repliky dat nezpracov\u00e1valy 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\u00e1n\u00ed index\u016f k existuj\u00edc\u00ed tabulce rychlost kles\u00e1 n\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\u00e9ho po\u010dtu 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>Odolnost proti v\u00fdpadk\u016fm<\/h2>\n<p>\nKlasick\u00fd SQL server m\u00e1 \u0161patnou odolnost v\u016f\u010di v\u00fdpadk\u016fm. P\u0159edstavte si, \u017ee m\u00e1te pouze jeden server datab\u00e1ze a ten selh\u00e1v\u00e1 jednou za t\u0159i roky. V tuto dobu web nefunguje 20 minut, co\u017e je p\u0159ijateln\u00e9. Pokud m\u00e1te 64 server\u016f, pak web nefunguje jednou za t\u0159i t\u00fddny. A pokud m\u00e1te 200 server\u016f, web nefunguje ka\u017ed\u00fd t\u00fdden. To je probl\u00e9m. <\/p>\n<p>Co lze ud\u011blat pro zv\u00fd\u0161en\u00ed odolnosti SQL serveru? Wikipedie n\u00e1m doporu\u010duje vybudovat <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/High-availability_cluster\">vysoce dostupn\u00fd cluster<\/a><\/noindex>: kde v p\u0159\u00edpad\u011b selh\u00e1n\u00ed jak\u00e9hokoliv z komponent je zde duplik\u00e1t.<\/p>\n<p>To vy\u017eaduje drah\u00fd park za\u0159\u00edzen\u00ed: \u010detn\u00e9 duplikace, optick\u00e1 vl\u00e1kna, sd\u00edlen\u00e1 \u00falo\u017ei\u0161t\u011b a zapnut\u00ed rezervy funguje nespolehliv\u011b: asi 10% zapnut\u00ed kon\u010d\u00ed selh\u00e1n\u00edm rezervn\u00ed uzlu za hlavn\u00edm uzlem. <\/p>\n<p>Ale hlavn\u00ed nev\u00fdhodou takov\u00e9ho vysoce dostupn\u00e9ho clusteru je nulov\u00e1 dostupnost p\u0159i selh\u00e1n\u00ed datov\u00e9ho centra, ve kter\u00e9m je um\u00edst\u011bn. U \"Odclassniky\" m\u00e1me \u010dty\u0159i datov\u00e1 centra a mus\u00edme zajistit provoz p\u0159i \u00fapln\u00e9m v\u00fdpadku v jednom z nich.<\/p>\n<p>K tomu bychom mohli pou\u017e\u00edt <noindex><a rel=\"nofollow\" href=\"https:\/\/technet.microsoft.com\/en-us\/library\/ms151196.aspx\">Multi-Master<\/a><\/noindex> replikaci, integrovanou do SQL Serveru. Toto \u0159e\u0161en\u00ed je mnohem dra\u017e\u0161\u00ed kv\u016fli n\u00e1klad\u016fm na software a trp\u00ed dob\u0159e zn\u00e1m\u00fdmi probl\u00e9my s replikac\u00ed - nep\u0159edv\u00eddateln\u00fdmi zpo\u017ed\u011bn\u00edmi transakc\u00ed p\u0159i synchronn\u00ed replikaci a zpo\u017ed\u011bn\u00edmi v aplikaci replikac\u00ed (a d\u016fsledkem toho ztracen\u00fdmi modifikacemi) p\u0159i asynchronn\u00ed. P\u0159edpokl\u00e1dan\u00e9 <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\u010dn\u00ed \u0159e\u0161en\u00ed konflikt\u016f<\/a><\/noindex> \u010din\u00ed tuto variantu pro n\u00e1s zcela nepou\u017eitelnou.<\/p>\n<p>V\u0161echny tyto probl\u00e9my vy\u017eadovaly radik\u00e1ln\u00ed \u0159e\u0161en\u00ed a za\u010dali jsme jejich podrobnou anal\u00fdzu. Zde se mus\u00edme sezn\u00e1mit s t\u00edm, co SQL Server obvykle d\u011bl\u00e1 - s transakcemi.<\/p>\n<h2>Jednoduch\u00e1 transakce<\/h2>\n<p>\nZva\u017eme nejjednodu\u0161\u0161\u00ed transakci z pohledu praktick\u00e9ho SQL program\u00e1tora: p\u0159id\u00e1n\u00ed fotografie do alba. Alba a fotografie jsou ulo\u017eeny v r\u016fzn\u00fdch tabulk\u00e1ch. Album m\u00e1 po\u010d\u00edtadlo ve\u0159ejn\u00fdch fotografi\u00ed. Pak je takov\u00e1 transakce rozd\u011blena na n\u00e1sleduj\u00edc\u00ed kroky: <\/p>\n<ol>\n<li>Zamkneme album podle kl\u00ed\u010de.<\/li>\n<li>Vytvo\u0159\u00edme z\u00e1znam v tabulce fotografi\u00ed. <\/li>\n<li>Pokud m\u00e1 fotografie ve\u0159ejn\u00fd status, pak zv\u00fd\u0161\u00edme v albu po\u010d\u00edtadlo ve\u0159ejn\u00fdch fotografi\u00ed, aktualizujeme z\u00e1znam a potvrzujeme transakci.<\/li>\n<\/ol>\n<p>\nNebo ve form\u011b 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 nejb\u011b\u017en\u011bj\u0161\u00ed sc\u00e9n\u00e1\u0159 obchodn\u00ed transakce spo\u010d\u00edv\u00e1 v p\u0159e\u010dten\u00ed dat z datab\u00e1ze do pam\u011bti aplika\u010dn\u00edho serveru, proveden\u00ed n\u011bjak\u00fdch zm\u011bn a ulo\u017een\u00edm nov\u00fdch hodnot zp\u011bt do datab\u00e1ze. Obvykle v takov\u00e9 transakci aktualizujeme n\u011bkolik entit, n\u011bkolik tabulek. <\/p>\n<p>P\u0159i prov\u00e1d\u011bn\u00ed transakce m\u016f\u017ee doj\u00edt k konkurentn\u00edmu modifikov\u00e1n\u00ed stejn\u00fdch dat z jin\u00e9ho syst\u00e9mu. Nap\u0159\u00edklad, Antispam m\u016f\u017ee rozhodnout, \u017ee u\u017eivatel je podez\u0159el\u00fd, a proto by v\u0161echny fotografie u\u017eivatele nem\u011bly b\u00fdt ve\u0159ejn\u00e9, m\u011bly by b\u00fdt zasl\u00e1ny na moderaci, co\u017e znamen\u00e1 zm\u011bnit photo.status na n\u011bjakou jinou hodnotu a upravit p\u0159\u00edslu\u0161n\u00e9 po\u010d\u00edtadla. Je z\u0159ejm\u00e9, \u017ee pokud tato operace prob\u011bhne bez z\u00e1ruk atom\u00e1rnosti a izolace konkuren\u010dn\u00edch modifikac\u00ed, jak je tomu v <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">ACID<\/a><\/noindex>, v\u00fdsledek nebude takov\u00fd, jak\u00fd je pot\u0159eba \u2014 bu\u010f po\u010d\u00edtadlo fotografi\u00ed bude ukazovat nespr\u00e1vnou hodnotu, nebo se v\u0161echny fotografie neode\u0161lou na moderaci. <\/p>\n<p>Podobn\u00e9ho k\u00f3du, kter\u00fd manipuluje r\u016fzn\u00fdmi obchodn\u00edmi entitami v r\u00e1mci jedn\u00e9 transakce, bylo naps\u00e1no velmi mnoho za cel\u00e9 obdob\u00ed existence Odnoklassnikov. Zku\u0161enosti z migrac\u00ed na NoSQL s <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">Eventual Consistency<\/a><\/noindex> v\u00edme, \u017ee nejv\u011bt\u0161\u00ed obt\u00ed\u017ee (a \u010dasov\u00e9 n\u00e1roky) vyvol\u00e1v\u00e1 pot\u0159eba vyv\u00edjet k\u00f3d zam\u011b\u0159en\u00fd na udr\u017eov\u00e1n\u00ed konzistence dat. Proto hlavn\u00edm po\u017eadavkem na nov\u00e9 \u00falo\u017ei\u0161t\u011b bylo zaji\u0161t\u011bn\u00ed skute\u010dn\u00fdch ACID transakc\u00ed pro aplika\u010dn\u00ed logiku. <\/p>\n<p>Dal\u0161\u00ed, nem\u00e9n\u011b d\u016fle\u017eit\u00e9 po\u017eadavky byly:<\/p>\n<ul>\n<li>P\u0159i selh\u00e1n\u00ed datov\u00e9ho centra mus\u00ed b\u00fdt dostupn\u00e9 jak \u010dten\u00ed, tak z\u00e1pis do nov\u00e9ho \u00falo\u017ei\u0161t\u011b.<\/li>\n<li>Zachov\u00e1n\u00ed sou\u010dasn\u00e9 rychlosti v\u00fdvoje. To znamen\u00e1, \u017ee p\u0159i pr\u00e1ci s nov\u00fdm \u00falo\u017ei\u0161t\u011bm by m\u011bl b\u00fdt objem k\u00f3du p\u0159ibli\u017en\u011b stejn\u00fd, nem\u011bla by vzniknout pot\u0159eba dopisovat n\u011bco do \u00falo\u017ei\u0161t\u011b, vyv\u00edjet algoritmy pro \u0159e\u0161en\u00ed konflikt\u016f, udr\u017eov\u00e1n\u00ed sekund\u00e1rn\u00edch index\u016f atd. <\/li>\n<li>Rychlost nov\u00e9ho \u00falo\u017ei\u0161t\u011b by m\u011bla b\u00fdt dostate\u010dn\u011b vysok\u00e1 jak p\u0159i \u010dten\u00ed dat, tak p\u0159i zpracov\u00e1n\u00ed transakc\u00ed, co\u017e efektivn\u011b znamenalo nevhodnost akademicky p\u0159\u00edsn\u00fdch, univerz\u00e1ln\u00edch, ale pomal\u00fdch \u0159e\u0161en\u00ed, jako nap\u0159\u00edklad <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">dvouf\u00e1zov\u00fdch commit\u016f<\/a><\/noindex>.<\/li>\n<li>Automatick\u00e9 \u0161k\u00e1lov\u00e1n\u00ed za chodu. <\/li>\n<li>Pou\u017e\u00edv\u00e1n\u00ed b\u011b\u017en\u00fdch levn\u00fdch server\u016f, bez nutnosti zakupovat exotick\u00fd hardware. <\/li>\n<li>Mo\u017enost rozvoje \u00falo\u017ei\u0161t\u011b silami v\u00fdvoj\u00e1\u0159\u016f spole\u010dnosti. Jin\u00fdmi slovy, priorita byla d\u00e1na intern\u00edm nebo open-source \u0159e\u0161en\u00edm, ide\u00e1ln\u011b na Jav\u011b.<\/li>\n<\/ul>\n<p><\/p>\n<h2>\u0158e\u0161en\u00ed, \u0159e\u0161en\u00ed<\/h2>\n<p>\nAnalyzov\u00e1n\u00edm mo\u017en\u00fdch \u0159e\u0161en\u00ed jsme do\u0161li k dv\u011bma mo\u017en\u00fdm architektonick\u00fdm volb\u00e1m:<\/p>\n<p>Prvn\u00ed \u2014 vz\u00edt jak\u00fdkoliv SQL server a implementovat pot\u0159ebnou odolnost proti chyb\u00e1m, mechanismus \u0161k\u00e1lov\u00e1n\u00ed, odoln\u00fd cluster, \u0159e\u0161en\u00ed konflikt\u016f a distribuovan\u00e9, spolehliv\u00e9 a rychl\u00e9 ACID transakce. Tento variant jsme vyhodnotili jako velmi netradi\u010dn\u00ed a \u010dasov\u011b n\u00e1ro\u010dn\u00fd.<\/p>\n<p>Druh\u00e1 mo\u017enost \u2014 vz\u00edt hotov\u00e9 NoSQL \u00falo\u017ei\u0161t\u011b s implementovan\u00fdm \u0161k\u00e1lov\u00e1n\u00edm, odoln\u00fdm clusterem, \u0159e\u0161en\u00edm konflikt\u016f a realizovat transakce a SQL sami. Na prvn\u00ed pohled se i \u00fakol realizace SQL, nemluv\u011b o ACID transakc\u00edch, jev\u00ed jako pr\u00e1ce na l\u00e9ta. Ale pot\u00e9 jsme si uv\u011bdomili, \u017ee sada SQL funkc\u00ed, kter\u00e9 pou\u017e\u00edv\u00e1me v praxi, je daleko od ANSI SQL tak daleko jako <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Apache_Cassandra#Cassandra_Query_Language\">Cassandra CQL<\/a><\/noindex> daleko od ANSI SQL. P\u0159i bli\u017e\u0161\u00edm pohledu na CQL jsme zjistili, \u017ee je dostate\u010dn\u011b bl\u00edzk\u00e9 tomu, co pot\u0159ebujeme.<\/p>\n<h2>Cassandra a CQL<\/h2>\n<p>\nTak\u017ee, \u010d\u00edm je Cassandra zaj\u00edmav\u00e1, jak\u00e9 m\u00e1 mo\u017enosti?<\/p>\n<p>Za prv\u00e9, zde lze vytv\u00e1\u0159et tabulky s podporou r\u016fzn\u00fdch typ\u016f dat, lze prov\u00e1d\u011bt SELECT nebo UPDATE podle prim\u00e1rn\u00edho kl\u00ed\u010de.<\/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>\nPro zaji\u0161t\u011bn\u00ed konzistence dat replik Cassandra pou\u017e\u00edv\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Quorum_(distributed_computing)\">kv\u00f3rumov\u00fd p\u0159\u00edstup<\/a><\/noindex>. V nejjednodu\u0161\u0161\u00edm p\u0159\u00edpad\u011b to znamen\u00e1, \u017ee p\u0159i um\u00edst\u011bn\u00ed t\u0159\u00ed replik stejn\u00e9ho \u0159\u00e1dku na r\u016fzn\u00fdch uzlech clusteru je z\u00e1znam pova\u017eov\u00e1n za \u00fasp\u011b\u0161n\u00fd, pokud v\u011bt\u0161ina uzl\u016f (tj. dv\u011b ze t\u0159\u00ed) potvrdila \u00fasp\u011b\u0161nost t\u00e9to operace z\u00e1pisu. Data \u0159\u00e1dku jsou pova\u017eov\u00e1na za konzistentn\u00ed, pokud p\u0159i \u010dten\u00ed byly dotazov\u00e1ny v\u011bt\u0161inou uzl\u016f a potvrdily je. T\u00edmto zp\u016fsobem je zaru\u010dena \u00fapln\u00e1 a okam\u017eit\u00e1 konzistence dat p\u0159i selh\u00e1n\u00ed jednoho uzlu, pokud existuj\u00ed t\u0159i repliky. Tento p\u0159\u00edstup n\u00e1m umo\u017enil realizovat je\u0161t\u011b spolehliv\u011bj\u0161\u00ed sch\u00e9ma: v\u017edy odes\u00edlat po\u017eadavky na v\u0161echny t\u0159i repliky a \u010dekat na odpov\u011b\u010f od dvou nejrychlej\u0161\u00edch. Pozdn\u00ed odpov\u011b\u010f t\u0159et\u00ed repliky je v takov\u00e9m p\u0159\u00edpad\u011b odm\u00edtnuta. Na uzlu, kter\u00fd odpov\u00edd\u00e1 pozd\u011b, mohou t\u00edmto zp\u016fsobem vzniknout v\u00e1\u017en\u00e9 probl\u00e9my \u2013 zpomalen\u00ed, shroma\u017e\u010fov\u00e1n\u00ed odpadk\u016f v JVM, p\u0159\u00edm\u00e9 uvoln\u011bn\u00ed pam\u011bti v linuxov\u00e9m j\u00e1d\u0159e, selh\u00e1n\u00ed hardwaru nebo odpojen\u00ed od s\u00edt\u011b. Nicm\u00e9n\u011b to nijak neovliv\u0148uje operace klienta a data.<\/p>\n<p>P\u0159\u00edstup, kdy se obrac\u00edme na t\u0159i uzly a dost\u00e1v\u00e1me odpov\u011b\u010f od dvou, se naz\u00fdv\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Speculative_execution\">spekulace<\/a><\/noindex>: po\u017eadavek na nadbyte\u010dn\u00e9 repliky je odesl\u00e1n je\u0161t\u011b p\u0159edt\u00edm, ne\u017e \u201eodpadne\u201c. <\/p>\n<p>Dal\u0161\u00ed z v\u00fdhod Cassandry je Batchlog \u2013 mechanismus, kter\u00fd zaru\u010duje bu\u010f \u00fapln\u00e9 pou\u017eit\u00ed, nebo \u00fapln\u00e9 nepou\u017eit\u00ed souboru va\u0161ich zm\u011bn. To n\u00e1m umo\u017e\u0148uje vy\u0159e\u0161it A v ACID \u2013 atomaritu hned \u201ez krabice\u201c.<\/p>\n<p>Nejbli\u017e\u0161\u00ed k transakc\u00edm v Cassand\u0159e je takzvan\u00fd &#171;<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.datastax.com\/en\/cql\/3.3\/cql\/cql_using\/useInsertLWT.html\">lightweight transactions<\/a><\/noindex>&#171;. Ale od \"skute\u010dn\u00fdch\" ACID tranzakc\u00ed jsou daleko: ve skute\u010dnosti je to mo\u017enost prov\u00e9st <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Compare-and-swap\">CAS<\/a><\/noindex> na datech pouze jedn\u00e9 polo\u017eky, p\u0159i\u010dem\u017e se pou\u017e\u00edv\u00e1 konsensus podle t\u011b\u017ek\u00e9ho protokolu Paxos. Proto rychlost t\u011bchto transakc\u00ed nen\u00ed vysok\u00e1. <\/p>\n<h2>Co n\u00e1m v Cassand\u0159e chyb\u011blo<\/h2>\n<p>\nTak\u017ee jsme se museli postarat o implementaci skute\u010dn\u00fdch ACID transakc\u00ed v Cassand\u0159e. S jejich\u017e pomoc\u00ed bychom mohli snadno implementovat dv\u011b dal\u0161\u00ed pohodln\u00e9 funkce klasick\u00fdch DBMS: konzistentn\u00ed rychl\u00e9 indexy, co\u017e by n\u00e1m umo\u017enilo prov\u00e1d\u011bt v\u00fdb\u011bry dat nejen podle prim\u00e1rn\u00edho kl\u00ed\u010de a b\u011b\u017en\u00fd gener\u00e1tor monot\u00f3nn\u00edch auto-incrementn\u00edch ID.<\/p>\n<h4>C*One<\/h4>\n<p>\nTak se zrodila nov\u00e1 DBMS <b>C*One<\/b>, skl\u00e1daj\u00edc\u00ed se ze t\u0159\u00ed typ\u016f serverov\u00fdch uzl\u016f:<\/p>\n<ul>\n<li>\u00dalo\u017ei\u0161t\u011b \u2013 (t\u00e9m\u011b\u0159) standardn\u00ed servery Cassandry odpov\u011bdn\u00e9 za ukl\u00e1d\u00e1n\u00ed dat na m\u00edstn\u00ed disky. S rostouc\u00edm zat\u00ed\u017een\u00edm a objemem dat je jejich po\u010det snadno \u0161k\u00e1lovateln\u00fd na des\u00edtky a stovky.<\/li>\n<li>Koordin\u00e1to\u0159i transakc\u00ed zaji\u0161\u0165uj\u00ed prov\u00e1d\u011bn\u00ed transakc\u00ed. <\/li>\n<li>Klienti jsou aplika\u010dn\u00ed servery, kter\u00e9 realizuj\u00ed obchodn\u00ed operace a iniciuj\u00ed transakce. Takov\u00fdch klient\u016f m\u016f\u017ee b\u00fdt 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\u0161ech typ\u016f jsou sou\u010d\u00e1st\u00ed spole\u010dn\u00e9ho klastru, pou\u017e\u00edvaj\u00ed intern\u00ed protokol zpr\u00e1v Cassandra k vz\u00e1jemn\u00e9 komunikaci a <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">gossip<\/a><\/noindex> k v\u00fdm\u011bn\u011b informac\u00ed o klastru. Pomoc\u00ed Heartbeat se servery dozv\u00eddaj\u00ed o vz\u00e1jemn\u00fdch selh\u00e1n\u00edch, udr\u017euj\u00ed jednotnou sch\u00e9ma dat \u2013 tabulky, jejich strukturu a replikaci; sch\u00e9ma partitioningu, topologii klastru, atd.<\/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 \/>\nM\u00edsto standardn\u00edch ovlada\u010d\u016f se pou\u017e\u00edv\u00e1 re\u017eim Fat Client. Takov\u00fd uzel neuchov\u00e1v\u00e1 data, ale m\u016f\u017ee fungovat jako koordin\u00e1tor prov\u00e1d\u011bn\u00ed dotaz\u016f, co\u017e znamen\u00e1, \u017ee klient s\u00e1m zast\u00e1v\u00e1 funkci koordin\u00e1tora sv\u00fdch dotaz\u016f: vy\u017eaduje repliky \u00falo\u017ei\u0161t\u011b a \u0159e\u0161\u00ed konflikty. To je nejen spolehliv\u011bj\u0161\u00ed a rychlej\u0161\u00ed ne\u017e standardn\u00ed ovlada\u010d, kter\u00fd vy\u017eaduje komunikaci s vzd\u00e1len\u00fdm koordin\u00e1torem, ale tak\u00e9 umo\u017e\u0148uje spravovat p\u0159enos dotaz\u016f. Mimo otev\u0159enou transakci na klientovi jsou dotazy sm\u011brov\u00e1ny do \u00falo\u017ei\u0161\u0165. Pokud v\u0161ak klient otev\u0159el transakci, jsou v\u0161echny dotazy v r\u00e1mci transakce sm\u011brov\u00e1ny ke koordin\u00e1torovi transakc\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 transakc\u00ed C*One<\/h2>\n<p>\nKoordin\u00e1tor je to, co jsme implementovali pro C*One od nuly. Odpov\u00edd\u00e1 za spr\u00e1vu transakc\u00ed, z\u00e1mk\u016f a po\u0159ad\u00ed aplikace transakc\u00ed.<\/p>\n<p>Pro ka\u017edou obsluhovanou transakci koordin\u00e1tor generuje \u010dasovou zna\u010dku: ka\u017ed\u00e1 n\u00e1sleduj\u00edc\u00ed je v\u011bt\u0161\u00ed ne\u017e u p\u0159edchoz\u00ed transakce. Vzhledem k tomu, \u017ee v Cassand\u0159e je syst\u00e9m \u0159e\u0161en\u00ed konflikt\u016f zalo\u017een na \u010dasov\u00fdch zna\u010dk\u00e1ch (z dvou konfliktuj\u00edc\u00edch z\u00e1znam\u016f je aktu\u00e1ln\u00ed pova\u017eov\u00e1na ta s pozd\u011bj\u0161\u00ed \u010dasovou zna\u010dkou), bude konflikt v\u017edy vy\u0159e\u0161en ve prosp\u011bch n\u00e1sleduj\u00edc\u00ed transakce. Tak jsme 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\">Lamportovy hodiny<\/a><\/noindex> \u2013 levn\u00fd zp\u016fsob, jak \u0159e\u0161it konflikty v distribuovan\u00e9m syst\u00e9mu.<\/p>\n<h2>Z\u00e1mky<\/h2>\n<p>\nPro zaji\u0161t\u011bn\u00ed izolace jsme se rozhodli pou\u017e\u00edt ten nejjednodu\u0161\u0161\u00ed zp\u016fsob \u2013 pesimistick\u00e9 z\u00e1mky podle prim\u00e1rn\u00edho kl\u00ed\u010de z\u00e1znamu. Jin\u00fdmi slovy, v transakci je t\u0159eba nejprve z\u00e1znam zamknout, pot\u00e9 p\u0159e\u010d\u00edst, modifikovat a ulo\u017eit. Pouze po \u00fasp\u011b\u0161n\u00e9m potvrzen\u00ed m\u016f\u017ee b\u00fdt z\u00e1znam odem\u010den, aby konkuren\u010dn\u00ed transakce mohly k n\u011bmu p\u0159istupovat.<\/p>\n<p>Implementace takov\u00e9 blokace je jednoduch\u00e1 v nerovnom\u011brn\u011b rozlo\u017een\u00e9m prost\u0159ed\u00ed. V distribuovan\u00e9m syst\u00e9mu existuj\u00ed dv\u011b hlavn\u00ed cesty: bu\u010f implementovat distribuovanou blokaci na clusteru, nebo rozlo\u017eit transakce tak, aby transakce t\u00fdkaj\u00edc\u00ed se jedn\u00e9 polo\u017eky v\u017edy odbavoval stejn\u00fd koordin\u00e1tor.<\/p>\n<p>Jeliko\u017e m\u00e1me ji\u017e data rozlo\u017een\u00e1 do skupin lok\u00e1ln\u00edch transakc\u00ed v SQL, bylo rozhodnuto p\u0159id\u011blit koordin\u00e1tor\u016fm skupiny lok\u00e1ln\u00edch transakc\u00ed: jeden koordin\u00e1tor prov\u00e1d\u00ed v\u0161echny transakce s tokenem od 0 do 9, druh\u00fd - s tokenem od 10 do 19, a tak d\u00e1le. V\u00fdsledkem je, \u017ee ka\u017ed\u00fd z instanc\u00ed koordin\u00e1tora se st\u00e1v\u00e1 mistrem skupiny transakc\u00ed. <\/p>\n<p>Pot\u00e9 mohou b\u00fdt blokace implementov\u00e1ny jako oby\u010dejn\u00e1 HashMap v pam\u011bti koordin\u00e1tora.<\/p>\n<h2>Selh\u00e1n\u00ed koordin\u00e1tor\u016f<\/h2>\n<p>\nJeliko\u017e jeden koordin\u00e1tor v\u00fdhradn\u011b odbavuje skupinu transakc\u00ed, je velmi d\u016fle\u017eit\u00e9 rychle ur\u010dit, zda do\u0161lo k jeho selh\u00e1n\u00ed, aby op\u011btovn\u00fd pokus o proveden\u00ed transakce spadal do \u010dasov\u00e9ho limitu. Aby to bylo rychl\u00e9 a spolehliv\u00e9, pou\u017eili jsme pln\u011b propojen\u00fd kv\u00f3rumov\u00fd heartbeat protokol:<\/p>\n<p>V ka\u017ed\u00e9m datov\u00e9m centru je um\u00edst\u011bno minim\u00e1ln\u011b dv\u011b uzly koordin\u00e1tora. Pravideln\u011b ka\u017ed\u00fd koordin\u00e1tor rozes\u00edl\u00e1 heartbeat zpr\u00e1vu ostatn\u00edm koordin\u00e1tor\u016fm a informuje je o sv\u00e9 funk\u010dnosti, jako\u017e i o tom, jak\u00e9 heartbeat zpr\u00e1vy od kter\u00fdch koordin\u00e1tor\u016f v clusteru naposledy p\u0159ij\u00edmal. <\/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 \/>\nP\u0159ij\u00edmaj\u00edc podobn\u00e9 informace od ostatn\u00edch v r\u00e1mci jejich heartbeat zpr\u00e1v, ka\u017ed\u00fd koordin\u00e1tor rozhoduje, kter\u00e9 uzly clusteru funguj\u00ed a kter\u00e9 ne, podle principu kv\u00f3ra: pokud uzel X obdr\u017eel od v\u011bt\u0161iny uzl\u016f v clusteru informaci o norm\u00e1ln\u00edm obdr\u017een\u00ed zpr\u00e1v z uzlu Y, pak Y funguje. A naopak, jakmile v\u011bt\u0161ina uzl\u016f ozn\u00e1m\u00ed, \u017ee nep\u0159ij\u00edma zpr\u00e1vy z uzlu Y, znamen\u00e1 to, \u017ee Y selhal. Zaj\u00edmav\u00e9 je, \u017ee pokud kv\u00f3rum ozn\u00e1m\u00ed uzlu X, \u017ee od n\u011bj ji\u017e v\u00edce zpr\u00e1v neobdr\u017eelo, uzel X se bude pova\u017eovat za selhan\u00fd.<\/p>\n<p>Heartbeat zpr\u00e1vy se zas\u00edlaj\u00ed velkou frekvenc\u00ed, p\u0159ibli\u017en\u011b 20kr\u00e1t za sekundu, s intervalem 50 ms. V Jav\u011b je obt\u00ed\u017en\u00e9 zaru\u010dit reakci aplikace b\u011bhem 50 ms kv\u016fli podobn\u00e9 d\u00e9lce pauz zp\u016fsoben\u00fdch garbage collectorem. Poda\u0159ilo se n\u00e1m dos\u00e1hnout t\u00e9to doby odezvy pomoc\u00ed garbage collectoru G1, kter\u00fd umo\u017e\u0148uje stanovit c\u00edl pro d\u00e9lku pauz GC. Nicm\u00e9n\u011b, ob\u010das, pom\u011brn\u011b vz\u00e1cn\u011b, pauzy garbage collectoru p\u0159es\u00e1hnou 50 ms, co\u017e m\u016f\u017ee v\u00e9st k fale\u0161n\u00e9mu zji\u0161t\u011bn\u00ed selh\u00e1n\u00ed. Aby k tomu nedo\u0161lo, koordin\u00e1tor neohl\u00e1s\u00ed selh\u00e1n\u00ed vzd\u00e1len\u00e9ho uzlu po prvn\u00edm ztracen\u00e9m heartbeat zpr\u00e1v\u011b, pouze pokud jich chyb\u00ed n\u011bkolik po sob\u011b. <\/p>\n<p>Ale nesta\u010d\u00ed rychle pochopit, kter\u00fd uzel p\u0159estal fungovat. Je pot\u0159eba s t\u00edm n\u011bco d\u011blat. <\/p>\n<h2>Z\u00e1lohov\u00e1n\u00ed<\/h2>\n<p>\nKlasick\u00fd sc\u00e9n\u00e1\u0159 p\u0159edpokl\u00e1d\u00e1, \u017ee v p\u0159\u00edpad\u011b selh\u00e1n\u00ed mastera se spust\u00ed volby nov\u00e9ho pomoc\u00ed jednoho 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\u00edch<\/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\u00e1ln\u00edch<\/a><\/noindex> algoritm\u016f. Nicm\u00e9n\u011b, tyto algoritmy maj\u00ed dob\u0159e zn\u00e1m\u00e9 probl\u00e9my se shodou v \u010dase a d\u00e9lkou samotn\u00e9ho procesu voleb. Takov\u00fdchto dodate\u010dn\u00fdch zpo\u017ed\u011bn\u00ed jsme se dok\u00e1zali vyhnout pomoc\u00ed sch\u00e9matu nahrazov\u00e1n\u00ed koordin\u00e1tor\u016f v pln\u011b propojen\u00e9 s\u00edti:<\/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 \/>\nP\u0159edstavme si, \u017ee chceme prov\u00e9st transakci ve skupin\u011b 50. P\u0159edem ur\u010d\u00edme sch\u00e9ma nahrazov\u00e1n\u00ed, tedy kter\u00e9 uzly budou vykon\u00e1vat transakce skupiny 50 v p\u0159\u00edpad\u011b selh\u00e1n\u00ed hlavn\u00edho koordin\u00e1tora. Na\u0161\u00edm c\u00edlem je udr\u017eet syst\u00e9m funk\u010dn\u00ed p\u0159i selh\u00e1n\u00ed datov\u00e9ho centra. Ur\u010d\u00edme, \u017ee prvn\u00edm z\u00e1lo\u017en\u00edm uzlem bude uzel z jin\u00e9ho datov\u00e9ho centra a druh\u00fdm z\u00e1lo\u017en\u00edm uzlem bude uzel z t\u0159et\u00edho. Toto sch\u00e9ma se vyb\u00edr\u00e1 jednou a nem\u011bn\u00ed se, dokud nedojde ke zm\u011bn\u011b topologie clusteru, tedy dokud do n\u011bj nevstoup\u00ed nov\u00e9 uzly (co\u017e se st\u00e1v\u00e1 velmi z\u0159\u00eddka). Po\u0159ad\u00ed v\u00fdb\u011bru nov\u00e9ho aktivn\u00edho mastera p\u0159i selh\u00e1n\u00ed star\u00e9ho bude v\u017edy takov\u00e9: prvn\u00edm z\u00e1lo\u017en\u00edm uzlem se stane prvn\u00ed z\u00e1lo\u017en\u00ed, a pokud i ten p\u0159estane fungovat \u2013 druh\u00fd z\u00e1lo\u017en\u00ed. <\/p>\n<p>Toto sch\u00e9ma je spolehliv\u011bj\u0161\u00ed ne\u017e univerz\u00e1ln\u00ed algoritmus, proto\u017ee pro aktivaci nov\u00e9ho mastera sta\u010d\u00ed stanovit fakt selh\u00e1n\u00ed star\u00e9ho.<\/p>\n<p>Ale jak klienti poznaj\u00ed, kter\u00fd z mistr\u016f pr\u00e1v\u011b pracuje? Nen\u00ed mo\u017en\u00e9 rozeslat informace na tis\u00edce klient\u016f za 50 ms. M\u016f\u017ee nastat situace, kdy klient ode\u0161le \u017e\u00e1dost o otev\u0159en\u00ed transakce, ani\u017e by v\u011bd\u011bl, \u017ee tento mistr ji\u017e nefunguje, a \u017e\u00e1dost uv\u00e1zne na \u010dasov\u00e9m limitu. Aby se tomu zabr\u00e1nilo, klienti spekulativn\u011b pos\u00edlaj\u00ed \u017e\u00e1dost o otev\u0159en\u00ed transakce rovnou mistru skupiny a ob\u011bma jeho z\u00e1loh\u00e1m, ale odpov\u00ed pouze ten, kdo je aktu\u00e1ln\u011b aktivn\u00ed mistr. Ve\u0161kerou n\u00e1sleduj\u00edc\u00ed komunikaci v r\u00e1mci transakce klient prov\u00e1d\u00ed pouze s aktivn\u00edm mistrem.<\/p>\n<p>Z\u00e1lo\u017en\u00ed mist\u0159i um\u00edst\u00ed p\u0159ijat\u00e9 \u017e\u00e1dosti na ciz\u00ed transakce do fronty nenarozen\u00fdch transakc\u00ed, kde z\u016fst\u00e1vaj\u00ed n\u011bjakou dobu. Pokud aktivn\u00ed mistr zem\u0159e, nov\u00fd mistr zpracov\u00e1v\u00e1 \u017e\u00e1dosti o otev\u0159en\u00ed transakc\u00ed ze sv\u00e9 fronty a odpov\u00edd\u00e1 klientovi. Pokud klient ji\u017e stihl otev\u0159\u00edt transakci se star\u00fdm mistrem, druh\u00e1 odpov\u011b\u010f bude ignorov\u00e1na (a zjevn\u011b takov\u00e1 transakce se nedokon\u010d\u00ed a bude opakov\u00e1na klientem).<\/p>\n<h2>Jak funguje transakce<\/h2>\n<p>\nP\u0159edstavme si, \u017ee klient zaslal koordin\u00e1torovi \u017e\u00e1dost o otev\u0159en\u00ed transakce pro ur\u010ditou entitu s dan\u00fdm prim\u00e1rn\u00edm kl\u00ed\u010dem. Koordin\u00e1tor tuto entitu zablokuje a um\u00edst\u00ed ji do tabulky z\u00e1mk\u016f v pam\u011bti. Pokud je to nutn\u00e9, koordin\u00e1tor na\u010dte tuto entitu ze skladu a ulo\u017e\u00ed z\u00edskan\u00e1 data do stavu transakce v pam\u011bti 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 \/>\nKdy\u017e klient chce zm\u011bnit data v transakci, za\u0161le koordin\u00e1torovi \u017e\u00e1dost o modifikaci entity, a ten um\u00edst\u00ed nov\u00e1 data do tabulky stavu transakc\u00ed v pam\u011bti. Na tomto zapisov\u00e1n\u00ed je konec - z\u00e1pis do skladu se neprov\u00e1d\u00ed.<\/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 \/>\nKdy\u017e klient v r\u00e1mci aktivn\u00ed transakce po\u017eaduje vlastn\u00ed zm\u011bn\u011bn\u00e1 data, koordin\u00e1tor postupuje takto: <\/p>\n<ul>\n<li>pokud je ID ji\u017e v transakci, data se berou z pam\u011bti; <\/li>\n<li>pokud ID v pam\u011bti nen\u00ed, chyb\u011bj\u00edc\u00ed data se na\u010dtou z uzl\u016f skladu, spoj\u00ed se ji\u017e existuj\u00edc\u00edmi v pam\u011bti a v\u00fdsledek se p\u0159ed\u00e1 klientovi. <\/li>\n<\/ul>\n<p>\nT\u00edmto zp\u016fsobem m\u016f\u017ee klient p\u0159e\u010d\u00edst sv\u00e9 vlastn\u00ed zm\u011bny, zat\u00edmco ostatn\u00ed klienti tyto zm\u011bny nevid\u00ed, proto\u017ee jsou uchov\u00e1v\u00e1ny pouze v pam\u011bti koordin\u00e1tora a v uzlech Cassandra je\u0161t\u011b neexistuj\u00ed.<\/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 \/>\nKdy\u017e klient po\u0161le commit, stav, kter\u00fd m\u011bl slu\u017eba v pam\u011bti, je koordin\u00e1torem ulo\u017een do logged batch a jako logged batch je odesl\u00e1n do \u00falo\u017ei\u0161\u0165 Cassandra. \u00dalo\u017ei\u0161t\u011b vykonaj\u00ed v\u0161e pot\u0159ebn\u00e9, aby byl tento bal\u00ed\u010dek atom\u00e1rn\u011b (\u00fapln\u011b) aplikov\u00e1n, a vr\u00e1t\u00ed odpov\u011b\u010f koordin\u00e1torovi, kter\u00fd uvoln\u00ed z\u00e1mky a potvrd\u00ed \u00fasp\u011b\u0161nost transakce 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 pro rollback sta\u010d\u00ed koordin\u00e1torovi pouze uvolnit pam\u011b\u0165 obsazenou stavem transakce.<\/p>\n<p>V d\u016fsledku v\u00fd\u0161e uveden\u00fdch vylep\u0161en\u00ed jsme implementovali principy ACID:<\/p>\n<ul>\n<li><b>Atomarita<\/b>. To je z\u00e1ruka, \u017ee \u017e\u00e1dn\u00e1 transakce nebude v syst\u00e9mu zafixov\u00e1na \u010d\u00e1ste\u010dn\u011b, budou bu\u010f provedeny v\u0161echny jej\u00ed podoperace, nebo \u017e\u00e1dn\u00e1. Tento princip je u n\u00e1s dodr\u017eov\u00e1n d\u00edky logged batch v Cassand\u0159e.<\/li>\n<li><b>Konzistence<\/b>. Ka\u017ed\u00e1 \u00fasp\u011b\u0161n\u00e1 transakce podle definice zafixuje pouze platn\u00e9 v\u00fdsledky. Pokud je po otev\u0159en\u00ed transakce a proveden\u00ed \u010d\u00e1sti operac\u00ed zji\u0161t\u011bno, \u017ee v\u00fdsledek je neplatn\u00fd, prov\u00e1d\u00ed se rollback.<\/li>\n<li><b>Izolovanost<\/b>. P\u0159i prov\u00e1d\u011bn\u00ed transakce by paraleln\u00ed transakce nem\u011bly m\u00edt vliv na jej\u00ed v\u00fdsledek. Sout\u011b\u017e\u00edc\u00ed transakce jsou izolov\u00e1ny pomoc\u00ed pesimistick\u00fdch z\u00e1mk\u016f na koordin\u00e1torovi. Pro \u010dten\u00ed mimo transakci se dodr\u017euje princip izolovanosti na \u00farovni Read Committed.<\/li>\n<li><b>Odolnost<\/b>. Nez\u00e1visle na probl\u00e9mech na spodn\u00edch \u00farovn\u00edch \u2014 v\u00fdpadku syst\u00e9mu, selh\u00e1n\u00ed hardwaru \u2014 zm\u011bny, kter\u00e9 provedla \u00fasp\u011b\u0161n\u011b dokon\u010den\u00e1 transakce, by m\u011bly z\u016fstat uchov\u00e1ny po obnoven\u00ed fungov\u00e1n\u00ed. <\/li>\n<\/ul>\n<p><\/p>\n<h2>\u010cten\u00ed podle index\u016f<\/h2>\n<p>\nVezm\u011bme si jednoduchou tabulku: <\/p>\n<pre><code>CREATE TABLE photos (\nid bigint primary key,\nowner bigint,\nmodified timestamp,\n\u2026)<\/code><\/pre>\n<p>\nTa m\u00e1 ID (prim\u00e1rn\u00ed kl\u00ed\u010d), vlastn\u00edka a datum zm\u011bny. Je pot\u0159eba ud\u011blat velmi jednoduch\u00fd dotaz \u2014 vybrat data podle vlastn\u00edka s datem zm\u011bny \u201eza posledn\u00edch 24 hodin\u201c. <\/p>\n<pre><code>SELECT *\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nAby takov\u00fd dotaz b\u011b\u017eel rychle, je v klasick\u00e9 SQL DBMS pot\u0159eba vytvo\u0159it index na sloupc\u00edch (owner, modified). To m\u016f\u017eeme ud\u011blat pom\u011brn\u011b snadno, proto\u017ee nyn\u00ed m\u00e1me z\u00e1ruky ACID!<\/p>\n<h2>Indexy v C*One<\/h2>\n<p>\nExistuje p\u016fvodn\u00ed tabulka s fotografiemi, ve kter\u00e9 je ID z\u00e1znamu prim\u00e1rn\u00ed kl\u00ed\u010d. <\/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 \/>\nPro index C*One vytvo\u0159\u00ed novou tabulku, kter\u00e1 je kopi\u00ed p\u016fvodn\u00ed. Kl\u00ed\u010d se shoduje s indexov\u00fdm v\u00fdrazem, nav\u00edc zahrnuje i prim\u00e1rn\u00ed kl\u00ed\u010d z\u00e1znamu z p\u016fvodn\u00ed tabulky:<\/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 \/>\nNyn\u00ed lze dotaz na \u201evlastn\u00edka za posledn\u00edch 24 hodin\u201c p\u0159eformulovat jako SELECT z jin\u00e9 tabulky:<\/p>\n<pre><code>SELECT * FROM i1_test\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nKonzistence dat p\u016fvodn\u00ed tabulky photos a indexov\u00e9 tabulky i1 je automaticky udr\u017eov\u00e1na koordin\u00e1torem. Na z\u00e1klad\u011b samotn\u00e9 datov\u00e9 sch\u00e9matu p\u0159i z\u00edsk\u00e1n\u00ed zm\u011bny koordin\u00e1tor generuje a ukl\u00e1d\u00e1 zm\u011bnu nejen p\u016fvodn\u00ed tabulky, ale i zm\u011bny kopi\u00ed. Neprov\u00e1d\u011bj\u00ed se \u017e\u00e1dn\u00e9 dal\u0161\u00ed akce s indexovou tabulkou, logy nejsou \u010dteny, z\u00e1mky nejsou pou\u017e\u00edv\u00e1ny. To znamen\u00e1, \u017ee p\u0159id\u00e1n\u00ed index\u016f t\u00e9m\u011b\u0159 nezat\u011b\u017euje zdroje a prakticky neovliv\u0148uje rychlost aplikace modifikac\u00ed.<\/p>\n<p>D\u00edky ACID se n\u00e1m poda\u0159ilo implementovat indexy \u201ejako v SQL\u201c. Tyto indexy maj\u00ed konzistenci, daj\u00ed se \u0161k\u00e1lovat, rychle funguj\u00ed, mohou b\u00fdt slo\u017een\u00e9 a integrov\u00e1ny do jazyka dotaz\u016f CQL. Pro podporu index\u016f nen\u00ed t\u0159eba m\u011bnit aplika\u010dn\u00ed k\u00f3d. V\u0161e je jednoduch\u00e9 jako v SQL. Co je nejd\u016fle\u017eit\u011bj\u0161\u00ed, indexy neovliv\u0148uj\u00ed rychlost prov\u00e1d\u011bn\u00ed modifikac\u00ed p\u016fvodn\u00ed tabulky transakc\u00ed.<\/p>\n<h2>Co jsme z\u00edskali<\/h2>\n<p>\nC*One jsme vyvinuli p\u0159ed t\u0159emi lety a uvedli do pr\u016fmyslov\u00e9ho provozu. <\/p>\n<p>Co jsme tedy na z\u00e1v\u011br z\u00edskali? Posu\u010fme to na p\u0159\u00edkladu subsyst\u00e9mu zpracov\u00e1n\u00ed a ukl\u00e1d\u00e1n\u00ed fotografi\u00ed, jednoho z nejd\u016fle\u017eit\u011bj\u0161\u00edch typ\u016f dat v soci\u00e1ln\u00ed s\u00edti. Nemluv\u00edme o samotn\u00fdch t\u011blech fotografi\u00ed, ale o r\u016fzn\u00fdch meta informac\u00edch. V sou\u010dasnosti v \u201eOdnoklassnik\u00e1ch\u201c existuje asi 20 miliard takov\u00fdch z\u00e1znam\u016f, syst\u00e9m zpracov\u00e1v\u00e1 80 tis\u00edc dotaz\u016f za sekundu, a\u017e 8 tis\u00edc ACID transakc\u00ed za sekundu t\u00fdkaj\u00edc\u00edch se modifikace dat. <\/p>\n<p>Kdy\u017e jsme pou\u017e\u00edvali SQL s replication factor = 1 (ale v RAID 10), meta informace fotografi\u00ed byly ulo\u017eeny na vysoce dostupn\u00e9m clusteru o 32 stroj\u00edch s Microsoft SQL Server (plus 11 z\u00e1lo\u017en\u00edch). Tak\u00e9 bylo vy\u010dlen\u011bno 10 server\u016f pro ukl\u00e1d\u00e1n\u00ed z\u00e1loh. Celkem tedy 50 n\u00e1kladn\u00fdch stroj\u016f. P\u0159i\u010dem\u017e syst\u00e9m fungoval na nomin\u00e1ln\u00edm zat\u00ed\u017een\u00ed, bez rezervy.<\/p>\n<p>Po migraci na nov\u00fd syst\u00e9m jsme z\u00edskali replication factor = 3 \u2014 jednu kopii v ka\u017ed\u00e9m datov\u00e9m centru. Syst\u00e9m se skl\u00e1d\u00e1 z 63 uzl\u016f \u00falo\u017ei\u0161t\u011b Cassandra a 6 stroj\u016f koordin\u00e1tor\u016f, celkem 69 server\u016f. Ale tyto stroje jsou v\u00fdrazn\u011b levn\u011bj\u0161\u00ed, jejich celkov\u00e9 n\u00e1klady \u010din\u00ed p\u0159ibli\u017en\u011b 30 % n\u00e1klad\u016f syst\u00e9mu na SQL. Zat\u00edmco zat\u00ed\u017een\u00ed je na \u00farovni 30 %.<\/p>\n<p>S implementac\u00ed C*One se sn\u00ed\u017eily i latence: operace z\u00e1pisu v SQL trvala p\u0159ibli\u017en\u011b 4,5 ms. V C*One \u2014 p\u0159ibli\u017en\u011b 1,6 ms. D\u00e9lka transakce je v pr\u016fm\u011bru m\u00e9n\u011b ne\u017e 40 ms, commit prob\u00edh\u00e1 za 2 ms, d\u00e9lka \u010dten\u00ed a z\u00e1pisu \u2014 v pr\u016fm\u011bru 2 ms. 99. percentil \u2014 pouze 3-3,1 ms, po\u010det timeout\u016f se sn\u00ed\u017eil 100kr\u00e1t \u2014 a to d\u00edky \u0161irok\u00e9mu vyu\u017eit\u00ed spekulac\u00ed. <\/p>\n<p>K dne\u0161n\u00edmu dni bylo vy\u0159azeno z provozu v\u011bt\u0161ina uzl\u016f SQL Serveru, nov\u00e9 produkty jsou vyv\u00edjeny pouze s vyu\u017eit\u00edm C*One. P\u0159izp\u016fsobili jsme C*One pro pr\u00e1ci v na\u0161em cloudu. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/odnoklassniki\/blog\/346868\/\">one-cloud<\/a><\/noindex>, co\u017e umo\u017enilo zrychlit nasazen\u00ed nov\u00fdch klastr\u016f, zjednodu\u0161it konfiguraci a automatizovat provoz. Bez zdrojov\u00e9ho k\u00f3du by to bylo mnohem slo\u017eit\u011bj\u0161\u00ed a m\u00e9n\u011b efektivn\u00ed. <\/p>\n<p>Nyn\u00ed pracujeme na p\u0159evodu ostatn\u00edch na\u0161ich \u00falo\u017ei\u0161\u0165 do cloudu \u2014 ale to u\u017e je \u00fapln\u011b jin\u00fd p\u0159\u00edb\u011bh.<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\/cs\/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=\"cs_CZ\" \/>\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\/cs\/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":"A\u017e do ned\u00e1vn\u00e9 doby bylo v Odnoklassnik\u00e1ch p\u0159ibli\u017en\u011b 50 TB zpracov\u00e1van\u00fdch dat.","canonical_url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/newsql-nosql-acid","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/28484"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}