{"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\/no\/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 \/>\nFrem til nylig har omkring 50 TB med data blitt behandlet i sanntid i Odnoklassniki, lagret i SQL Server. For s\u00e5 mye data er det nesten umulig \u00e5 sikre rask og p\u00e5litelig, samt feiltolerant tilgang til datasenteret ved hjelp av SQL-databaser. Vanligvis brukes en av NoSQL-lagringene i slike tilfeller, men ikke alt kan flyttes til NoSQL: enkelte entiteter krever garantier for ACID-transaksjoner. <\/p>\n<p>Dette f\u00f8rte oss til \u00e5 bruke et NewSQL-lagringssystem, alts\u00e5 en database som tilbyr feiltoleranse, skalerbarhet og ytelsen til NoSQL-systemer, samtidig som den opprettholder de kjente ACID-garantiene fra klassiske systemer. Det finnes f\u00e5 fungerende industrielle systemer av denne nye klassen, s\u00e5 vi implementerte et lignende system selv og tok det i drift. <\/p>\n<p>Hvordan dette fungerer og hva vi fikk til \u2013 les mer under.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nI dag er den m\u00e5nedlige publikum p\u00e5 \u00abOdnoklassniki\u00bb over 70 millioner unike bes\u00f8kende. Vi <noindex><a rel=\"nofollow\" href=\"https:\/\/www.similarweb.com\/top-websites\/category\/internet-and-telecom\/social-network\">er blant de fem st\u00f8rste<\/a><\/noindex> sosiale mediene i verden, og blant de tyve nettstedene der brukerne tilbringer mest tid. Infrastrukturene til \u00abOK\u00bb h\u00e5ndterer sv\u00e6rt h\u00f8ye belastninger: over en million HTTP-foresp\u00f8rsel\/s p\u00e5 frontene. Deler av serverparken, som best\u00e5r av mer enn 8000 enheter, er plassert n\u00e6rt hverandre - i fire datasilos i Moskva, noe som muliggj\u00f8r en nettverksforsinkelse p\u00e5 mindre enn 1 ms mellom dem.<\/p>\n<p>Vi har brukt Cassandra siden 2010, fra versjon 0.6. I dag er flere titalls klynger i drift. Den raskeste klyngen behandler over 4 millioner operasjoner per sekund, og den st\u00f8rste lagrer 260 TB. <\/p>\n<p>Imidlertid er alt dette vanlige NoSQL-klynger som brukes til lagring av <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\">svakt konsistente<\/a><\/noindex> data. Vi \u00f8nsket imidlertid \u00e5 erstatte det prim\u00e6re konsistente lageret, Microsoft SQL Server, som har blitt brukt siden \u00abOdnoklassniki\u00bb ble grunnlagt. Lagringssystemet besto av mer enn 300 SQL Server Standard Edition-maskiner, som inneholdt 50 TB med data \u2013 forretningsentiteter. Disse dataene modifiseres innenfor ACID-transaksjoner og krever <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">h\u00f8y konsistens<\/a><\/noindex>.<\/p>\n<p>For distribusjon av data mellom nodene i SQL Server brukte vi b\u00e5de vertikal og horisontal <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Partition_(database)\">partisjonering<\/a><\/noindex> (sharding). Historisk har vi brukt et enkelt datashardingskjema: hver entitet ble tildelt en token \u2014 en funksjon av entitetens ID. Entiteter med samme token ble plassert p\u00e5 en SQL-server. Master-detail-forhold ble implementert slik at tokenene for hoved- og underpost alltid stemte overens og befant seg p\u00e5 samme server. I sosiale nettverk genereres nesten alle poster p\u00e5 vegne av brukeren \u2014 dermed lagres alle brukerdata innenfor et funksjonelt subsystem p\u00e5 \u00e9n server. Det vil si at i forretningstransaksjoner deltok nesten alltid tabeller fra \u00e9n SQL-server, noe som gjorde det mulig \u00e5 sikre datakonsistens ved hjelp av lokale ACID-transaksjoner, uten behov for \u00e5 bruke <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">langsomme og up\u00e5litelige<\/a><\/noindex> distribuerte ACID-transaksjoner.<\/p>\n<p>Takket v\u00e6re sharding og for \u00e5 \u00f8ke hastigheten p\u00e5 SQL:<\/p>\n<ul>\n<li>Vi bruker ikke fremmedn\u00f8kkelbegrensninger, siden entitetens ID kan befinne seg p\u00e5 en annen server ved sharding.<\/li>\n<li>Vi bruker ikke lagrede prosedyrer og triggere p\u00e5 grunn av ekstra belastning p\u00e5 database-CPU-en.<\/li>\n<li>Vi bruker ikke JOINs p\u00e5 grunn av alt det ovennevnte og mange tilfeldige disklesinger.<\/li>\n<li>Utenfor transaksjoner for \u00e5 redusere d\u00f8dl\u00e5s bruker vi isolasjonsniv\u00e5et Read Uncommitted.<\/li>\n<li>Vi utf\u00f8rer kun korte transaksjoner (i gjennomsnitt kortere enn 100 ms).<\/li>\n<li>Vi bruker ikke flerader UPDATE og DELETE p\u00e5 grunn av mange d\u00f8dl\u00e5ser \u2014 vi oppdaterer kun \u00e9n post om gangen.<\/li>\n<li>Foresp\u00f8rslene utf\u00f8res alltid kun etter indekser \u2014 en foresp\u00f8rsel med et fullt tabellvisningsplan betyr overbelastning av databasen og dens svikt.<\/li>\n<\/ul>\n<p>\nDisse trinnene har gjort det mulig \u00e5 presse nesten maksimal ytelse ut av SQL-serverne. Imidlertid ble problemene stadig flere. La oss se p\u00e5 dem.<\/p>\n<h2>Problemer med SQL<\/h2>\n<p><\/p>\n<ul>\n<li>Siden vi brukte egenutviklet sharding, ble tilf\u00f8rsel av nye shards utf\u00f8rt manuelt av administratorene. I hele denne perioden betjente ikke skalerbare datakopier foresp\u00f8rslene. <\/li>\n<li>Etter hvert som antallet poster i tabellen \u00f8ker, reduseres hastigheten for innsetting og modifikasjon; n\u00e5r man legger til indekser til eksisterende tabeller, synker hastigheten drastisk, og opprettelse og gjenoppretting av indekser skjer med nedetid.<\/li>\n<li>Tilstedev\u00e6relsen av et lite antall Windows-servere for SQL Server i produksjon kompliserer h\u00e5ndteringen av infrastrukturen.<\/li>\n<\/ul>\n<p>\nMen det st\u00f8rste problemet er \u2014 <\/p>\n<h2>Feiltoleranse<\/h2>\n<p>\nEn klassisk SQL-server har d\u00e5rlig feiloverf\u00f8ringsevne. La oss si at du bare har \u00e9n database-server, og den feiler hvert tredje \u00e5r. I l\u00f8pet av denne tiden fungerer ikke nettstedet i 20 minutter, noe som er akseptabelt. Men hvis du har 64 servere, vil nettstedet ikke fungere hver tredje uke. Og hvis du har 200 servere, vil nettstedet ikke fungere hver uke. Dette er et problem. <\/p>\n<p>Hva kan gj\u00f8res for \u00e5 forbedre feiloverf\u00f8ringsevnen til en SQL-server? Wikipedia foresl\u00e5r at vi bygger <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/High-availability_cluster\">et h\u00f8ytilgjengelig klynge<\/a><\/noindex>: der det finnes en duplikat i tilfelle en av komponentene feiler.<\/p>\n<p>Dette krever en park av kostbart utstyr: omfattende duplisering, fiberoptikk, felles lagring, og det \u00e5 inkludere reserver fungerer usikkert: rundt 10 % av oppstartene ender med feil i den reserve noden i r\u00e6kken bakerst. <\/p>\n<p>Men den st\u00f8rste ulempen med en slik h\u00f8ytilgjengelig klynge er null tilgjengelighet ved svikt i datasenteret den er plassert i. \u00abOdnoklassniki\u00bb har fire datasentre, og vi m\u00e5 sikre drift under total havari i ett av dem.<\/p>\n<p>For dette kunne man bruke <noindex><a rel=\"nofollow\" href=\"https:\/\/technet.microsoft.com\/en-us\/library\/ms151196.aspx\">Multi-Master<\/a><\/noindex> replikering, innebygd i SQL Server. Denne l\u00f8sningen er betydelig dyrere p\u00e5 grunn av programvarekostnaden og sliter med godt kjente problemer med replikering \u2013 uforutsigbare forsinkelser i transaksjoner ved synkron replikering og forsinkelser i anvendelsen av replikeringene (og dermed tapte modifikasjoner) ved asynkron. Det underforst\u00e5tte <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\">manuelle konfliktl\u00f8sninger<\/a><\/noindex> gj\u00f8r dette alternativet helt ubrukelig for oss.<\/p>\n<p>Alle disse problemene krevde en radikal l\u00f8sning, og vi begynte en detaljert analyse av dem. Her m\u00e5 vi bli kjent med hva SQL Server f\u00f8rst og fremst gj\u00f8r \u2013 transaksjoner.<\/p>\n<h2>En enkel transaksjon<\/h2>\n<p>\nLa oss se p\u00e5 den enkleste transaksjonen, fra et praktisk SQL-programmerers perspektiv: legge til et bilde i et album. Album og bilder lagres i ulike tabeller. Et album har en teller for offentlige bilder. Da deles en slik transaksjon opp i f\u00f8lgende trinn: <\/p>\n<ol>\n<li>Vi l\u00e5ser albumet med en n\u00f8kkel.<\/li>\n<li>Vi oppretter en post i bildets tabell. <\/li>\n<li>Hvis bildet har offentlig status, \u00f8ker vi tellingen av offentlige bilder i albumet, oppdaterer posten og forplikter transaksjonen.<\/li>\n<\/ol>\n<p>\nEller i form av pseudokode:<\/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>\nVi ser at det mest vanlige scenariet for forretningstransaksjoner er \u00e5 lese data fra databasen inn i applikasjonsserverens minne, gj\u00f8re noen endringer og lagre de nye verdiene tilbake i databasen. Vanligvis i en slik transaksjon oppdaterer vi flere entiteter, flere tabeller. <\/p>\n<p>N\u00e5r transaksjonen utf\u00f8res, kan det skje konkurrerende modifikasjoner av de samme dataene fra et annet system. For eksempel kan Antispam vurdere en bruker som mistenkelig, og derfor skal alle bilder til den brukeren ikke lenger v\u00e6re offentlige, de m\u00e5 sendes til moderering, noe som betyr at photo.status m\u00e5 endres til en annen verdi og de tilh\u00f8rende tellerne m\u00e5 justeres. Det er \u00e5penbart at hvis denne operasjonen skjer uten garantier for atomisk anvendelse og isolasjon av konkurrerende modifikasjoner, som i <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">ACID<\/a><\/noindex>, vil ikke resultatet bli det som er n\u00f8dvendig - enten vil foto-telleren vise en feil verdi, eller ikke alle bilder vil bli sendt til moderering. <\/p>\n<p>Det er skrevet mye liknende kode, som manipulerer forskjellige forretningsenheter innenfor en enkelt transaksjon, gjennom tiden til Eksperimentene. Basert p\u00e5 erfaringene fra migrering til NoSQL med <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">Eventual Consistency<\/a><\/noindex> vet vi at de st\u00f8rste utfordringene (og tidskostnadene) kommer fra behovet for \u00e5 utvikle kode som opprettholder datakonsistens. Derfor var det viktigste kravet til det nye lagringssystemet \u00e5 sikre ekte ACID-transaksjoner for applikasjonslogikken. <\/p>\n<p>Andre, minst like viktige, krav var:<\/p>\n<ul>\n<li>Ved sentersvikt m\u00e5 b\u00e5de lesing og skriving til det nye lagringssystemet v\u00e6re tilgjengelig.<\/li>\n<li>Opprettholde den n\u00e5v\u00e6rende hastigheten for utvikling. Det vil si at arbeidet med det nye lagringssystemet ikke skal kreve mye mer kode, og det skal ikke v\u00e6re behov for \u00e5 skrive noe nytt i lagringssystemet, utvikle algoritmer for konfliktl\u00f8sning, opprettholde sekund\u00e6re indekser osv. <\/li>\n<li>Hastigheten p\u00e5 det nye lagringssystemet m\u00e5 v\u00e6re tilstrekkelig h\u00f8y, b\u00e5de ved datauthenting og ved behandling av transaksjoner, noe som effektivt betyr at akademisk strenge, universelle, men langsomme l\u00f8sninger, som for eksempel <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_commit_protocol\">to-fase committer, ikke vil v\u00e6re anvendelige.<\/a><\/noindex>.<\/li>\n<li>Automatisk skalering i sanntid. <\/li>\n<li>Bruken av vanlige, billige servere, uten behov for \u00e5 kj\u00f8pe eksotisk maskinvare. <\/li>\n<li>Muligheten for utvikling av lagringssystemet av selskapets utviklere. Med andre ord, prioriteten ble gitt til egne eller \u00e5pne l\u00f8sninger, helst p\u00e5 Java.<\/li>\n<\/ul>\n<p><\/p>\n<h2>L\u00f8sninger, l\u00f8sninger<\/h2>\n<p>\nVed \u00e5 analysere mulige l\u00f8sninger kom vi til to mulige valg av arkitektur:<\/p>\n<p>Den f\u00f8rste er \u00e5 ta en hvilken som helst SQL-server og implementere n\u00f8dvendig feilresistens, skaleringsmekanisme, feilresistent klynge, konfliktl\u00f8sing og distribuerte, p\u00e5litelige og hurtige ACID-transaksjoner. Vi vurderte dette alternativet som ganske uvanlig og arbeidskrevende.<\/p>\n<p>Det andre alternativet er \u00e5 ta et ferdig NoSQL-lager med implementert skalerbarhet, feilresistent klynge, konfliktl\u00f8sing og implementere transaksjoner og SQL selv. Ved f\u00f8rste \u00f8yekast virker selv oppgaven med \u00e5 implementere SQL, for ikke \u00e5 snakke om ACID-transaksjoner, som en oppgave for flere \u00e5r. Men s\u00e5 skj\u00f8nte vi at settet av SQL-muligheter som vi bruker i praksis, er langt fra ANSI SQL s\u00e5 langt som <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Apache_Cassandra#Cassandra_Query_Language\">Cassandra CQL<\/a><\/noindex> er langt fra ANSI SQL. Ved \u00e5 se n\u00e6rmere p\u00e5 CQL, inns\u00e5 vi at det er n\u00e6rt det vi trenger.<\/p>\n<h2>Cassandra og CQL<\/h2>\n<p>\nS\u00e5 hva er det interessante med Cassandra, hvilke muligheter har den?<\/p>\n<p>For det f\u00f8rste kan du opprette tabeller som st\u00f8tter ulike datatyper, og du kan gj\u00f8re SELECT eller UPDATE basert p\u00e5 prim\u00e6rn\u00f8kkelen.<\/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>\nFor \u00e5 sikre datakonsistens mellom replikaene, bruker Cassandra <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Quorum_(distributed_computing)\">et kvorumtiln\u00e6rming<\/a><\/noindex>I det enkleste tilfellet betyr dette at n\u00e5r man setter opp tre repliker av samme rad p\u00e5 forskjellige noder i klyngen, anses skriveoperasjonen som vellykket hvis flertallet av nodene (dvs. to av tre) har bekreftet suksessen med denne skriveoperasjonen. Raddataene anses som konsistente hvis flertallet av nodene ble forespurt under lesingen og bekreftet dem. Dermed garanterer tilstedev\u00e6relsen av tre repliker fullstendig og umiddelbar datakonsistens ved feil av en node. Denne tiln\u00e6rmingen har gjort det mulig for oss \u00e5 implementere et enda mer p\u00e5litelig system: alltid sende foresp\u00f8rslene til alle tre repliker, og vente p\u00e5 svar fra de to raskeste. Det forsinkede svaret fra den tredje replikaen blir i slike tilfeller forkastet. Den forsinkede noden kan ha alvorlige problemer \u2014 forsinkelser, s\u00f8ppelinnsamling i JVM, direkte minnefrigivelse i linux-kjernen, maskinvarefeil, nettverksavbrudd. Men dette p\u00e5virker ikke klientoperasjonen eller dataene p\u00e5 noen m\u00e5te.<\/p>\n<p>Tiln\u00e6rmingen der vi henvender oss til tre noder og f\u00e5r svar fra to, kalles <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Speculative_execution\">speklulasjon<\/a><\/noindex>: foresp\u00f8rselen til de ekstra replikaene sendes f\u00f8r de faktisk 'faller av'. <\/p>\n<p>En annen fordel med Cassandra er Batchlog \u2014 en mekanisme som garanterer enten fullstendig anvendelse eller fullstendig annullering av pakken med endringer du gj\u00f8r. Dette lar oss l\u00f8se A i ACID \u2014 atomisitet rett ut av boksen.<\/p>\n<p>Det som ligger n\u00e6rmest transaksjoner i Cassandra, er det som kalles &#171;<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.datastax.com\/en\/cql\/3.3\/cql\/cql_using\/useInsertLWT.html\">lettvekts-transaksjoner<\/a><\/noindex>&#171;. Men de er langt fra \u00abekte\u00bb ACID-transaksjoner: i virkeligheten er det en mulighet til \u00e5 gj\u00f8re <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Compare-and-swap\">CAS<\/a><\/noindex> p\u00e5 dataene til kun \u00e9n oppf\u00f8ring, ved hjelp av konsensus via den tunge protokollen Paxos. Derfor er hastigheten p\u00e5 slike transaksjoner ikke h\u00f8y. <\/p>\n<h2>Hva vi manglet i Cassandra<\/h2>\n<p>\nS\u00e5 vi m\u00e5tte implementere ekte ACID-transaksjoner i Cassandra. Med dem kunne vi lett realisere to andre praktiske funksjoner fra klassiske DBMS: konsistente raske indekser, som ville gj\u00f8re det mulig for oss \u00e5 hente data ikke bare etter prim\u00e6rn\u00f8kkelen, og en vanlig generator av monotont autoinkrementerende ID-er.<\/p>\n<h4>C*One<\/h4>\n<p>\nS\u00e5 ble en ny DBMS f\u00f8dt, <b>C*One<\/b>som best\u00e5r av tre typer servernoder:<\/p>\n<ul>\n<li>Lager \u2014 (nesten) standard Cassandra-servere ansvarlige for lagring av data p\u00e5 lokale disker. Etter hvert som belastningen og datamengden \u00f8ker, kan antallet enkelt skaleres opp til titalls og hundrevis.<\/li>\n<li>Transaksjonskoordinatorer \u2014 s\u00f8rger for gjennomf\u00f8ring av transaksjoner. <\/li>\n<li>Kunder \u2014 applikasjonsservere som utf\u00f8rer forretningsoperasjoner og initierer transaksjoner. Det kan v\u00e6re tusenvis av slike kunder.<\/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 \/>\nServere av alle typer er en del av et felles klynge, bruker den interne meldingsprotokollen Cassandra for \u00e5 kommunisere med hverandre og <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Gossip_protocol\">gossip<\/a><\/noindex> for \u00e5 dele klyngeinformasjon. Gjennom Heartbeat f\u00e5r serverne informasjon om gjensidige fiaskoer, opprettholder en felles dataskjema \u2014 tabeller, deres struktur og replikasjon; partisjoneringsskjema, topologi av klyngen, osv.<\/p>\n<h4>Kunder<\/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 \/>\nI stedet for standarddrivere brukes Fat Client-modus. En slik node lagrer ikke data, men kan fungere som koordinator for foresp\u00f8rselene, det vil si at klienten selv utf\u00f8rer koordinatorfunksjonen for foresp\u00f8rslene sine: sp\u00f8r replikene i lagringssystemet og l\u00f8ser konflikter. Dette er ikke bare mer p\u00e5litelig og raskere enn den standarddriveren som krever kommunikasjon med en ekstern koordinator, men det muliggj\u00f8r ogs\u00e5 administrasjon av foresp\u00f8rselsoverf\u00f8ring. Utenfor en \u00e5pen transaksjon hos klienten sendes foresp\u00f8rslene til lagringene. Hvis klienten derimot har \u00e5pnet en transaksjon, sendes alle foresp\u00f8rslene innenfor transaksjonen til transaksjonskoordinatoren.<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>Transaksjonskoordinator C*One<\/h2>\n<p>\nKoordinator \u2014 det vi har implementert for C*One fra bunnen av. Han er ansvarlig for administrasjon av transaksjoner, l\u00e5ser og rekkef\u00f8lge av anvendelse av transaksjoner.<\/p>\n<p>For hver h\u00e5ndtert transaksjon genererer koordinatoren et tidsstempel: hvert p\u00e5f\u00f8lgende er st\u00f8rre enn det for den foreg\u00e5ende transaksjonen. Siden konfliktl\u00f8sningen i Cassandra-systemet er basert p\u00e5 tidsstempler (blant to konfliktfylte poster anses den som aktuell med det senere tidsstempelet), vil konflikten alltid bli l\u00f8st til fordel for den p\u00e5f\u00f8lgende transaksjonen. Dermed har vi implementert <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\">Lamports klokker<\/a><\/noindex> \u2014 en billig m\u00e5te \u00e5 l\u00f8se konflikter i et distribuert system.<\/p>\n<h2>L\u00e5ser<\/h2>\n<p>\nFor \u00e5 sikre isolasjon valgte vi den enkleste metoden \u2014 pessimistiske l\u00e5ser basert p\u00e5 prim\u00e6rn\u00f8kkelen til oppf\u00f8ringen. Med andre ord, i transaksjonen m\u00e5 posten f\u00f8rst l\u00e5ses, deretter leses, modifiseres og lagres. F\u00f8rst etter en vellykket commit kan posten l\u00e5ses opp, slik at konkurrrerende transaksjoner kan bruke den.<\/p>\n<p>Implementering av en slik l\u00e5sing er enkel i et ufordelt milj\u00f8. I et fordelt system er det to hovedveier: enten implementere en distribuert l\u00e5sing i klyngen, eller fordele transaksjoner slik at transaksjoner som involverer en enkelt post alltid h\u00e5ndteres av den samme koordinatoren.<\/p>\n<p>Siden dataene i v\u00e5rt tilfelle allerede er fordelt p\u00e5 grupper av lokale transaksjoner i SQL, ble det besluttet \u00e5 tildele koordinatorene grupper av lokale transaksjoner: \u00e9n koordinator h\u00e5ndterer alle transaksjoner med en token fra 0 til 9, den andre - fra 10 til 19, og s\u00e5 videre. Resultatet er at hver av koordinatorinstansene blir mester for sin gruppe av transaksjoner. <\/p>\n<p>Da kan l\u00e5sene implementeres i form av en enkel HashMap i minnet til koordinatoren.<\/p>\n<h2>Koordinatorfeil<\/h2>\n<p>\nSiden \u00e9n koordinator utelukkende betjener en gruppe transaksjoner, er det avgj\u00f8rende \u00e5 raskt fastsl\u00e5 om den har sviktet, slik at gjenopptakelsen av transaksjonen kan skje innen tidsfristen. For \u00e5 oppn\u00e5 dette raskt og p\u00e5litelig, har vi anvendt en fullstendig koblet kvorum heartbeat-protokoll:<\/p>\n<p>Hver datasenter har minst to koordinatornoder. Regelmessig sender hver koordinator heartbeat-meldinger til de andre koordinatorene for \u00e5 informere dem om at den fungerer, samt hvilke heartbeat-meldinger fra andre koordinatorer i klyngen den sist mottok. <\/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 \/>\nVed \u00e5 motta lignende informasjon fra de andre koordinatorene i sine heartbeat-meldinger, bestemmer hver koordinator hvilke noder i klyngen som fungerer, og hvilke som ikke gj\u00f8r det, basert p\u00e5 kvorumprinsippet: hvis node X har f\u00e5tt bekreftelse fra flertallet av nodene i klyngen om at meldinger fra node Y er mottatt normalt, fungerer Y. Og omvendt, s\u00e5 snart flertallet rapporterer om tap av meldinger fra node Y, har Y sviktet. Det er interessant at hvis kvorum informerer node X om at den ikke har f\u00e5tt meldinger fra den, vil node X selv anse seg som sviktet.<\/p>\n<p>Heartbeat-meldinger sendes med h\u00f8y frekvens, omtrent 20 ganger i sekundet, med en periode p\u00e5 50 ms. I Java er det vanskelig \u00e5 garantere applikasjonens respons innen 50 ms p\u00e5 grunn av sammenlignbare pauser for\u00e5rsaket av s\u00f8ppelsamleren. Vi klarte \u00e5 oppn\u00e5 en slik respons tid ved \u00e5 bruke G1-s\u00f8ppelsamler, som gj\u00f8r det mulig \u00e5 spesifisere m\u00e5l for varigheten av GC-pauser. Imidlertid, av og til, sjeldent, overskrider pauses\u00f8ppelsamlerens tid 50 ms, noe som kan f\u00f8re til falsk feiloppdagelse. For \u00e5 unng\u00e5 dette, varsler ikke koordinatoren om feil p\u00e5 en ekstern node ved tap av den f\u00f8rste heartbeat-meldingen fra den, men kun hvis flere meldinger g\u00e5r tapt p\u00e5 rad. P\u00e5 den m\u00e5ten klarte vi \u00e5 oppn\u00e5 oppdagelse av feil p\u00e5 koordinatoren innen 200 ms. <\/p>\n<p>Men det er ikke nok \u00e5 raskt forst\u00e5 hvilken node som har sluttet \u00e5 fungere. Det m\u00e5 gj\u00f8res noe med det. <\/p>\n<h2>Redundans<\/h2>\n<p>\nDen klassiske ordningen inneb\u00e6rer i tilfelle av feil hos master \u00e5 starte valg av en ny med hjelp av en av<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\"> de popul\u00e6re<\/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\">universelle<\/a><\/noindex> algoritmene. Imidlertid har slike algoritmer godt kjente problemer med konvergens over tid og varigheten av selve valgprosessen. Slike ekstra forsinkelser klarte vi \u00e5 unng\u00e5 ved \u00e5 bruke en erstatningsordning for koordinatorer i et fullt sammenkoblet nettverk:<\/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 \/>\nLa oss si at vi vil utf\u00f8re en transaksjon i gruppe 50. Vi definerer p\u00e5 forh\u00e5nd erstatningsordningen, det vil si hvilke noder som skal utf\u00f8re transaksjoner for gruppe 50 i tilfelle hovedkoordinatoren feiler. M\u00e5let v\u00e5rt er \u00e5 opprettholde systemets funksjonalitet ved et datacenters svikt. Vi definerer at det f\u00f8rste reserve vil v\u00e6re en node fra et annet datacenter, og det andre reserve vil v\u00e6re en node fra det tredje. Denne ordningen velges en gang og endres ikke s\u00e5 lenge klustertopologien ikke endres, det vil si s\u00e5 lenge det ikke legges til nye noder i den (noe som skjer sv\u00e6rt sjeldent). Rangeringen for valg av en ny aktiv master ved feil hos den gamle vil alltid v\u00e6re slik: den aktive masteren blir det f\u00f8rste reserve, og hvis det ogs\u00e5 har sluttet \u00e5 fungere \u2013 det andre reserve. <\/p>\n<p>Denne ordningen er mer p\u00e5litelig enn den universelle algoritmen, ettersom det er tilstrekkelig \u00e5 fastsl\u00e5 faktum om feilen til den gamle for \u00e5 aktivere den nye masteren.<\/p>\n<p>Men klientene forst\u00e5r ikke hvilken av mesterne som jobber akkurat n\u00e5? P\u00e5 50 ms er det umulig \u00e5 sende informasjon til tusenvis av kunder. Det kan oppst\u00e5 en situasjon der kunden sender en foresp\u00f8rsel om \u00e5 \u00e5pne en transaksjon, uten \u00e5 vite at den mesteren allerede ikke fungerer, og foresp\u00f8rselen vil henge p\u00e5 time-out. For \u00e5 unng\u00e5 dette, sender kundene spekulativt foresp\u00f8rselen om \u00e5 \u00e5pne transaksjonen til gruppens mester og begge hans reservemestrene, men det vil bare v\u00e6re den aktive mesteren som svarer p\u00e5 denne foresp\u00f8rselen i \u00f8yeblikket. All videre kommunikasjon i forbindelse med transaksjonen vil kunden ha bare med den aktive mesteren.<\/p>\n<p>Reserve-mestrene plasserer foresp\u00f8rslene de mottar om andre mestres transaksjoner i k\u00f8en for ikke-f\u00f8dte transaksjoner, hvor de oppbevares en stund. Hvis den aktive mesteren d\u00f8r, s\u00e5 behandler den nye mesteren foresp\u00f8rslene om \u00e5 \u00e5pne transaksjoner fra sin egen k\u00f8 og svarer kunden. Hvis kunden allerede har klart \u00e5 \u00e5pne en transaksjon med den gamle mesteren, s\u00e5 ignoreres det andre svaret (og denne transaksjonen vil \u00e5penbart ikke fullf\u00f8res og m\u00e5 gjentas av kunden).<\/p>\n<h2>Hvordan fungerer en transaksjon<\/h2>\n<p>\nLa oss si at kunden har sendt en foresp\u00f8rsel til koordinatoren om \u00e5 \u00e5pne en transaksjon for en bestemt enhet med en viss prim\u00e6rn\u00f8kkel. Koordinatoren l\u00e5ser denne enheten og plasserer den i blokkeringstabellen i minnet. Om n\u00f8dvendig leser koordinatoren denne enheten fra lagringen og lagrer de mottatte dataene i transaksjonens tilstand i koordinatorens minne.<\/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 \/>\nN\u00e5r kunden \u00f8nsker \u00e5 endre dataene i transaksjonen, sender han en foresp\u00f8rsel til koordinatoren om \u00e5 modifisere enheten, som da plasserer de nye dataene i tabellen for transaksjonsstatus i minnet. P\u00e5 dette punktet er oppf\u00f8rselen fullf\u00f8rt \u2013 ingen skriving til lagringen finner sted.<\/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 \/>\nN\u00e5r kunden anmoder om egne endrede data innenfor en aktiv transaksjon, handler koordinatoren slik: <\/p>\n<ul>\n<li>hvis ID allerede finnes i transaksjonen, tas dataene fra minnet; <\/li>\n<li>hvis ID ikke finnes i minnet, leses de manglende dataene fra nodene i lagringen, kombineres med de allerede tilgjengelige i minnet, og resultatet returneres til kunden. <\/li>\n<\/ul>\n<p>\nDermed kan kunden lese sine egne endringer, mens andre kunder ikke ser disse endringene, fordi de bare lagres i koordinatorens minne; i nodene i Cassandra finnes de ikke enn\u00e5.<\/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 \/>\nN\u00e5r en klient sender en commit, blir tilstanden som har v\u00e6rt i minnet hos tjenesten, lagret av koordinatoren i logged batch, og i form av logged batch sendes den til Cassandra-lagerne. Lagringene gj\u00f8r alt n\u00f8dvendig for at denne pakken skal bli atomisk (fullstendig) anvendt, og returnerer et svar til koordinatoren, som deretter frigj\u00f8r l\u00e5ser og bekrefter transaksjonens suksess til klienten.<\/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 \/>\nOg for \u00e5 rulle tilbake trenger koordinatoren bare \u00e5 frigj\u00f8re minnet som ble brukt til transaksjonens tilstand.<\/p>\n<p>Som et resultat av de ovennevnte forbedringene har vi implementert ACID-prinsippene:<\/p>\n<ul>\n<li><b>Atomisitet<\/b>. Dette er en garanti for at ingen transaksjoner vil bli delvis bekreftet i systemet; enten blir alle deloperasjoner utf\u00f8rt, eller ingen av dem. I v\u00e5rt tilfelle overholdes dette prinsippet ved hjelp av logged batch i Cassandra.<\/li>\n<li><b>Konsistens<\/b>. Hver vellykket transaksjon registrerer per definisjon bare gyldige resultater. Hvis det etter \u00e5pning av en transaksjon og utf\u00f8relse av deler av operasjonene oppdages at resultatet er ugyldig, utf\u00f8res en rulling tilbake.<\/li>\n<li><b>Isolasjon<\/b>. N\u00e5r en transaksjon utf\u00f8res, m\u00e5 parallelle transaksjoner ikke p\u00e5virke dens resultat. Konkurrerende transaksjoner er isolert ved hjelp av pessimistiske l\u00e5ser p\u00e5 koordinatoren. For leseoperasjoner utenfor transaksjonen overholdes isolasjonsprinsippet p\u00e5 niv\u00e5et Read Committed.<\/li>\n<li><b>Motstandskraft<\/b>. Uavhengig av problemer p\u00e5 lavere niv\u00e5er \u2014 str\u00f8mbrudd eller maskinvarefeil \u2014 m\u00e5 endringene gjort av en vellykket avsluttet transaksjon forbli lagret etter at funksjonen er gjenopptatt. <\/li>\n<\/ul>\n<p><\/p>\n<h2>Lesing etter indekser<\/h2>\n<p>\nLa oss ta en enkel tabell: <\/p>\n<pre><code>CREATE TABLE photos (\nid bigint primary key,\neier bigint,\nmodifisert timestamp,\n\u2026)<\/code><\/pre>\n<p>\nDen har en ID (prim\u00e6rn\u00f8kkel), eier og endringsdato. Vi m\u00e5 gj\u00f8re en veldig enkel foresp\u00f8rsel \u2014 velge data etter eier med endringsdato \"de siste 24 timer\". <\/p>\n<pre><code>SELECT *\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nFor at en slik foresp\u00f8rsel skal kj\u00f8re raskt, m\u00e5 vi i en klassisk SQL-database bygge et indeks p\u00e5 kolonnene (owner, modified). Dette kan vi gj\u00f8re ganske enkelt, siden vi n\u00e5 har garantier for ACID!<\/p>\n<h2>Indekser i C*One<\/h2>\n<p>\nDet finnes en original tabell med bilder, hvor ID-en til posten er prim\u00e6rn\u00f8kkelen. <\/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 \/>\nFor indeksen lager C*One en ny tabell som er en kopi av originalen. N\u00f8kkelen samsvarer med indeksuttrykket, samtidig som den ogs\u00e5 inkluderer den prim\u00e6re n\u00f8kkelen fra originaltabellen:<\/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 \/>\nN\u00e5 kan sp\u00f8rringen \"eier for de siste 24 timene\" skrives om som select fra en annen tabell:<\/p>\n<pre><code>SELECT * FROM i1_test\nWHERE owner=?\nAND modified&gt;?<\/code><\/pre>\n<p>\nKonsistensen til den opprinnelige tabellen photos og indekstabellen i1 opprettholdes automatisk av koordinatoren. Ut fra bare dataskjemaet, n\u00e5r det gj\u00f8res endringer, genererer og husker koordinatoren endringer ikke bare i hovedtabellen, men ogs\u00e5 endringer i kopiene. Ingen ekstra handlinger med indeks-tabellen utf\u00f8res, logger leses ikke, l\u00e5sing brukes ikke. Det vil si at tillegg av indekser nesten ikke bruker ressurser og har praktisk talt ingen innvirkning p\u00e5 hastigheten av modifikasjoner.<\/p>\n<p>Med ACID klarte vi \u00e5 implementere indekser \"som i SQL\". De har konsistens, kan skaleres, jobber raskt, kan v\u00e6re sammensatte og integrert i CQL-sp\u00f8rrespr\u00e5ket. For \u00e5 st\u00f8tte indekser er det ikke n\u00f8dvendig med endringer i anvendt kode. Alt er enkelt, som i SQL. Og det viktigste, indeksene p\u00e5virker ikke hastigheten p\u00e5 utf\u00f8relsen av modifikasjoner i transaksjons tabellen.<\/p>\n<h2>Hva fikk vi?<\/h2>\n<p>\nVi utviklet C*One for tre \u00e5r siden og satte det i produksjon. <\/p>\n<p>Hva fikk vi ut av dette? La oss vurdere det ved hjelp av delsystemet for behandling og lagring av bilder, en av de viktigste datatypene i sosiale nettverk. Det handler ikke om selve bildene, men om all slags metadata. N\u00e5 er det omtrent 20 milliarder slike poster i \"Odnoklassniki\", systemet h\u00e5ndterer 80 000 lesesp\u00f8rringer i sekundet, opptil 8 000 ACID-transaksjoner i sekundet knyttet til datamodifikasjoner. <\/p>\n<p>Da vi brukte SQL med replication factor = 1 (men i RAID 10), ble metadataene om bildene lagret p\u00e5 en h\u00f8yt tilgjengelig klynge best\u00e5ende av 32 maskiner med Microsoft SQL Server (pluss 11 backup-maskiner). Det ble ogs\u00e5 avsatt 10 servere for \u00e5 lagre sikkerhetskopier. Totalt 50 kostbare maskiner. Systemet fungerte med nominell belastning, uten margin.<\/p>\n<p>Etter migrering til det nye systemet fikk vi replication factor = 3 \u2014 en kopi i hvert datasenter. Systemet best\u00e5r av 63 Cassandra-lagringsnoder og 6 koordinatormaskiner, totalt 69 servere. Disse maskinene er imidlertid betydelig billigere, den totale kostnaden er omtrent 30 % av kostnaden ved SQL-systemet. Samtidig holdes belastningen p\u00e5 niv\u00e5et 30 %.<\/p>\n<p>Med innf\u00f8ringen av C*One har b\u00e5de forsinkelser redusert: i SQL tok skriveoperasjonen omtrent 4,5 ms. I C*One \u2014 omtrent 1,6 ms. Gjennomsnittlig transaksjonstid er mindre enn 40 ms, commiten utf\u00f8res p\u00e5 2 ms, lese- og skrivevarigheten er i gjennomsnitt 2 ms. 99. percentil er bare 3-3,1 ms, antall tidsavbrudd har redusert med 100 ganger \u2014 alt takket v\u00e6re det brede bruken av spekulasjoner. <\/p>\n<p>Per n\u00e5 er det meste av SQL Server-nodene tatt ut av drift, nye produkter utvikles kun ved bruk av C*One. Vi har tilpasset C*One for drift i v\u00e5rt sky. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/odnoklassniki\/blog\/346868\/\">one-cloud<\/a><\/noindex>, noe som har gjort det mulig \u00e5 akselerere opprettelsen av nye klynger, forenkle konfigurasjonen og automatisere driften. Uten kildekoden ville dette v\u00e6rt betydelig mer komplisert og kl\u00f8nete. <\/p>\n<p>Akkurat n\u00e5 jobber vi med \u00e5 flytte andre datalagre til skyen \u2014 men det er en helt annen historie.<br \/>\n<br \/>Kilde: <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.5 - 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\/no\/blog\/administrirovanie\/newsql-nosql-acid\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"nn_NO\" \/>\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\/no\/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":"Frem til nylig var det rundt 50 TB data som ble behandlet i Odnoklassniki.","canonical_url":"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/newsql-nosql-acid","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nn_NO","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\/no\/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\/no\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media\/28484"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}