NewSQL = NoSQL + ACID

NewSQL = NoSQL + ACID
Finu à pocu tempu, Odnoklassniki hà guardatu circa 50 TB di dati trattati in tempu reale in SQL Server. Per un tali voluminu, hè quasi impussibile di furnisce un accessu veloce è affidabile, è ancu un accessu tolerante à u fallimentu di u centru di dati cù un DBMS SQL. Di genere, in tali casi, unu di i magazzini NoSQL hè utilizatu, ma micca tuttu pò esse trasferitu à NoSQL: alcune entità necessitanu garanzii di transazzione ACID.

Questu ci hà purtatu à l'usu di l'almacenamiento NewSQL, vale à dì un DBMS chì furnisce a tolleranza di difetti, a scalabilità è a prestazione di i sistemi NoSQL, ma à u stessu tempu mantenendu i garanti ACID familiar à i sistemi classici. Ci hè un pocu di sistemi industriali di travagliu di sta nova classa, cusì avemu implementatu un tali sistema noi stessi è l'avemu in opera cummerciale.

Cumu travaglia è ciò chì hè accadutu - leghje sottu u cut.

Oghje, l'audienza mensili di Odnoklassniki hè più di 70 milioni di visitatori unichi. Noi Semu in i primi cinque più grande rete suciale in u mondu, è trà i vinti siti nantu à quale l'utilizatori passanu u più tempu. L'infrastruttura OK gestisce carichi assai elevati: più di un milione di richieste HTTP / sec per fronte. Parte di una flotta di servitori di più di 8000 1 pezzi sò situati vicinu à l'altri - in quattru centri di dati di Mosca, chì permette di assicurà una latenza di rete di menu di XNUMX ms trà elli.

Avemu usatu Cassandra da u 2010, cumincendu cù a versione 0.6. Oghje ci sò parechje decine di clusters in opera. U cluster più veloce processa più di 4 milioni di operazioni per seconda, è i più grandi magazzini 260 TB.

Tuttavia, questi sò tutti i clusters NoSQL ordinali utilizati per u almacenamentu debolmente coordinata dati. Vulemu rimpiazzà l'almacenamiento consistente principale, Microsoft SQL Server, chì hè stata utilizata da a fundazione di Odnoklassniki. L'almacenamiento era custituitu da più di 300 macchine SQL Server Standard Edition, chì cuntenenu 50 TB di dati - entità cummerciale. Sta dati hè mudificatu cum'è parte di transazzione ACID è esige alta consistenza.

Per distribuisce e dati in i nodi di SQL Server, avemu usatu sia verticale sia horizontale spartizione (frammentazione). Stòricamente, avemu usatu un schema simplice di sharding di dati: ogni entità hè stata assuciata cù un token - una funzione di l'ID di l'entità. Entità cù u listessu token sò stati posti nantu à u stessu servitore SQL. A relazione maestru-detagli hè stata implementata in modu chì i tokens di i registri principali è di u zitellu sempre scontranu è si trovanu in u stessu servitore. In una reta suciale, quasi tutti i registri sò generati in nome di l'utilizatore - chì significa chì tutti i dati di l'utilizatori in un subsistema funziunale sò almacenati in un servitore. Vale à dì, una transazzione cummerciale quasi sempre implicava tavule da un servitore SQL, chì hà permessu di assicurà a coherenza di dati utilizendu transazzioni ACID lucali, senza bisognu di utilizà. lento è inaffidabile transazzione ACID distribuitu.

Grazie à u sharding è à accelerà SQL:

  • Ùn avemu micca aduprà limitazioni di chjave straniera, postu chì quandu u sharding l'ID di l'entità pò esse situatu in un altru servitore.
  • Ùn usemu micca e prucedure almacenate è triggers per via di a carica addiziale nantu à u CPU DBMS.
  • Ùn avemu micca aduprà JOIN per via di tuttu ciò chì sopra è assai di leghje aleatorii da u discu.
  • Fora di una transazzione, usemu u livellu di isolamentu Read Uncommitted per riduce i blocchi.
  • Facemu solu transazzioni brevi (in media più brevi di 100 ms).
  • Ùn avemu micca aduprà UPDATE è DELETE multi-fila per via di u gran numaru di blocchi - aghjurnemu solu un record à u tempu.
  • Eseguimu sempre e dumande solu nantu à l'indici - una dumanda cù un pianu di scansione di tavula cumpleta per noi significa sovraccaricare a basa di dati è a causa di fallu.

Questi passi ci anu permessu di stringhje quasi u massimu rendimentu da i servitori SQL. Tuttavia, i prublemi sò diventati più è più numerosi. Fighjemu à elli.

Prublemi cù SQL

  • Siccomu avemu usatu sharding auto-scrittu, l'aghjunzione di novi frammenti hè stata fatta manualmente da l'amministratori. Tuttu stu tempu, rèpliche di dati scalabili ùn eranu micca richieste di serviziu.
  • Quandu u numeru di registri in a tavula cresce, a velocità di inserzione è mudificazione diminuite quandu aghjunghje indici à una tavula esistente, a velocità di creazione è a ricreazione di l'indici si trova cù u tempu di downtime;
  • Avè una piccula quantità di Windows per SQL Server in produzzione rende a gestione di l'infrastruttura difficiule

Ma u prublema principali hè

tolleranza à i difetti

U servitore SQL classicu hà una povira toleranza di difetti. Diciamu chì avete solu un servitore di basa di dati, è falla una volta ogni trè anni. Duranti stu tempu, u situ hè falatu per 20 minuti, chì hè accettabile. Sì avete 64 servitori, u situ hè falatu una volta ogni trè simane. È se avete 200 servitori, u situ ùn viaghja micca ogni settimana. Questu hè u prublema.

Chì pò esse fattu per migliurà a toleranza di difetti di un servitore SQL? Wikipedia ci invita à custruisce cluster altamente dispunibule: induve in casu di fallimentu di qualcunu di i cumpunenti ci hè una copia di salvezza.

Questu hè bisognu di una flotta d'equipaggiu caru: numerosi duplicazioni, fibra ottica, almacenamentu spartutu, è l'inclusione di una riserva ùn funziona micca in modu affidabile: circa 10% di i cambiamenti finiscinu cù u fallimentu di u node di salvezza cum'è un trenu daretu à u node principale.

Ma u principale svantaghju di un cluster cusì assai dispunibile hè a dispunibilità zero se u centru di dati in quale si trova falla. Odnoklassniki hà quattru centri di dati, è avemu bisognu di assicurà u funziunamentu in casu di fallimentu cumpletu in unu di elli.

Per questu pudemu usà Multi-Maestru replicazione integrata in SQL Server. Sta suluzione hè assai più caru per u costu di u software è soffre di prublemi cunnisciuti cù a replicazione - ritardu di transazzione imprevisible cù replicazione sincrona è ritardi in l'applicazione di replicazioni (è, in u risultatu, mudificazioni perse) cù replicazione asincrona. L'implicite risoluzione manuale di cunflittu rende questa opzione completamente inapplicabile per noi.

Tutti issi prublemi necessitanu una suluzione radicali, è avemu cuminciatu à analizà in dettu. Quì avemu bisognu di cunnosce ciò chì SQL Server faci principalmente - transazzioni.

Transazzione simplice

Cunsideremu a transazzione più simplice, da u puntu di vista di un programatore SQL applicatu: aghjunghje una foto à un album. L'album è e fotografie sò guardati in diverse piastre. L'album hà un contatore di foto publicu. Allora una tale transazzione hè divisa in i seguenti passi:

  1. Chjavemu l'album da chjave.
  2. Crea una entrata in a tavula di foto.
  3. Se a foto hà un statutu publicu, aghjunghje un contatore di foto publicu à l'album, aghjurnà u record è cummette a transazzione.

O in pseudocode:

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

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

TX.commit();

Avemu vistu chì u scenariu di transazzione cummerciale più cumuni hè di leghje e dati da a basa di dati in a memoria di u servitore di l'applicazione, cambià qualcosa è salvà i novi valori in a basa di dati. Di solitu in una tale transazzione aghjurnà parechje entità, parechje tavule.

Quandu eseguisce una transazzione, a mudificazione simultanea di e stesse dati da un altru sistema pò esse. Per esempiu, l'Antispam pò decide chì l'utilizatore hè in qualchì modu suspettu è per quessa tutte e foto di l'utilizatori ùn devenu più publiche, anu da esse mandatu per a moderazione, chì significa cambià photo.status à qualchì altru valore è disattivà i cuntatori currispundenti. Ovviamente, se questa operazione si verifica senza garanzie di atomicità di applicazione è isolamentu di mudificazioni cuncurrenti, cum'è in àcitu, allura u risultatu ùn serà micca ciò chì hè necessariu - o u contatore di foto mostrarà u valore sbagliatu, o micca tutte e foto seranu mandate per a moderazione.

Un saccu di codice simili, manipulendu diverse entità cummerciale in una transazzione, hè statu scrittu in tutta l'esistenza di Odnoklassniki. Basatu nantu à l'esperienza di migrazioni à NoSQL da Cuerenza Eventuale Sapemu chì a sfida più grande (è l'investimentu di u tempu) vene da u sviluppu di codice per mantene a cunsistenza di e dati. Dunque, avemu cunsideratu u requisitu principalu per u novu almacenamentu per esse furnitu per transazzioni ACID reali per a logica di l'applicazione.

Altri requisiti, micca menu impurtanti, eranu:

  • Se u centru di dati falla, sia a lettura sia a scrittura à u novu almacenamentu deve esse dispunibule.
  • Mantene a velocità di sviluppu attuale. Questu hè, quandu u travagliu cù un novu repository, a quantità di codice deve esse apprussimatamente a stessa, ùn deve esse micca bisognu di aghjunghje qualcosa à u repository, sviluppà algoritmi per risolve i cunflitti, mantene indici secundari, etc.
  • A vitezza di u novu almacenamentu duvia esse abbastanza alta, sia in leghje e dati sia in u processu di e transacciones, chì significheghja in modu efficace chì suluzioni rigurosu accademicu, universale, ma lento, cum'è, per esempiu, ùn eranu micca applicabili. impegni in dui fasi.
  • Scala autumàticu à a mosca.
  • Aduprendu servitori rigulari boni, senza bisognu di cumprà hardware esoticu.
  • Possibilità di sviluppu di almacenamiento da i sviluppatori di a cumpagnia. In altri palori, a priorità hè stata data à suluzioni proprietarie o open source, preferibbilmente in Java.

Decisioni, decisioni

Analizendu e pussibuli suluzioni, simu ghjunti à duie scelte di architettura pussibuli:

U primu hè di piglià qualsiasi servitore SQL è implementà a tolleranza di difetti necessaria, u mecanismu di scala, u cluster di failover, a risoluzione di cunflittu è e transazzioni ACID distribuite, affidabili è veloci. Avemu valutatu sta opzione cum'è assai micca triviale è intensiva di travagliu.

A seconda opzione hè di piglià un almacenamiento NoSQL prontu cù scala implementata, un cluster di failover, risoluzione di cunflittu, è implementà transazzioni è SQL stessu. À u primu sguardu, ancu u compitu di implementà SQL, per ùn dì micca e transazzione ACID, s'assumiglia un compitu chì duverà anni. Ma dopu avemu capitu chì u set di funzioni SQL chì usemu in pratica hè tantu luntanu da ANSI SQL quant'è Cassandra CQL luntanu da ANSI SQL. Fighjendu ancu più vicinu à CQL, avemu capitu chì era abbastanza vicinu à ciò chì avemu bisognu.

Cassandra è CQL

Allora, chì hè interessante di Cassandra, chì capacità hà?

Prima, quì pudete creà tavule chì supportanu diversi tipi di dati, pudete fà SELECT o UPDATE nantu à a chjave primaria.

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

Per assicurà a coherenza di a replica di dati, Cassandra usa approche quorum. In u casu più simplice, questu significa chì quandu trè rèpliche di a listessa fila sò posti nantu à diversi nodi di u cluster, a scrittura hè cunsiderata successu se a maiò parte di i nodi (vale à dì, dui di trè) cunfirmanu u successu di sta operazione di scrittura. . I dati di fila sò cunsiderati cunsistenti se, quandu leghje, a maiò parte di i nodi sò stati sondati è cunfirmati. Cusì, cù trè rèpliche, a coherenza di dati cumpleta è immediata hè garantita se un node falla. Stu approcciu ci hà permessu di implementà un schema ancu più affidabile: mandate sempre e dumande à e trè rèpliche, aspittendu una risposta da i dui più veloci. A risposta tardi di a terza replica hè scartata in questu casu. Un node chì hè tardu à risponde pò avè prublemi serii - freni, cullizzioni di basura in a JVM, ricuperazione di memoria diretta in u kernel Linux, fallimentu hardware, scollegamentu da a reta. Tuttavia, questu ùn affetta micca l'operazioni o dati di u cliente in ogni modu.

L'approcciu quandu avemu cuntattatu trè nodi è riceve una risposta da dui hè chjamatu speculazione: una dumanda di repliche extra hè mandata ancu prima ch'ella "casca".

Un altru benefiziu di Cassandra hè Batchlog, un mecanismu chì assicura chì un batch di cambiamenti chì fate sò o appiicati cumplettamente o micca appiicati in tuttu. Questu ci permette di risolve A in ACID - atomicità fora di a scatula.

A cosa più vicinu à e transazzione in Cassandra sò i cosiddetti "transazzione ligera". Ma sò luntanu da e transacciones ACID "veri": in fattu, questu hè una oppurtunità di fà CAS nantu à dati da un solu record, usendu cunsensu cù u protocolu Paxos di pesu pesu. Per quessa, a vitezza di tali transazzioni hè bassu.

Ciò chì ci mancava in Cassandra

Dunque, avemu avutu à implementà transazzioni ACID reali in Cassandra. Aduprendu chì pudemu facilmente implementà duie altre caratteristiche convenienti di DBMS classicu: indici veloci coerenti, chì ci permettenu di fà selezzione di dati micca solu da a chjave primaria, è un generatore regulare di ID auto-incrementanti monotoni.

C* Unu

Cusì hè natu un novu DBMS C* Unu, custituitu da trè tippi di nodi di u servitore:

  • Storage - (quasi) servitori Cassandra standard rispunsevuli di almacenà e dati nantu à i dischi lucali. Cume a carica è u voluminu di dati cresce, a so quantità pò esse facilmente scalata à decine è centu.
  • Coordinatori di transazzione - assicuranu l'esekzione di e transazzione.
  • I clienti sò servitori d'applicazioni chì implementanu operazioni cummerciale è inizianu transacciones. Ci ponu esse millaie di tali clienti.

NewSQL = NoSQL + ACID

I servitori di tutti i tipi sò parti di un cluster cumunu, utilizate u protocolu internu di messagiu Cassandra per cumunicà cù l'altri è gossip per scambià infurmazioni di cluster. Cù Heartbeat, i servitori amparanu i fallimenti mutuali, mantenenu un schema di dati unicu - tabelle, a so struttura è a replicazione; schema di partizionamentu, topulugia di cluster, etc.

Clienti

NewSQL = NoSQL + ACID

Invece di i driver standard, u modu Fat Client hè utilizatu. Un tali node ùn guarda micca e dati, ma pò agisce cum'è un coordinatore per l'esekzione di a dumanda, vale à dì, u Cliente stessu agisce cum'è un coordinatore di e so dumande: interrogà rèpliche di almacenamiento è risolve i cunflitti. Questu hè micca solu più affidabile è più veloce di u driver standard, chì deve esse cumunicazione cù un coordinatore remota, ma permette ancu di cuntrullà a trasmissione di e dumande. Fora di una transazzione aperta nantu à u cliente, e dumande sò mandate à i repositori. Se u cliente hà apertu una transazzione, tutte e dumande in a transazzione sò mandate à u coordinatore di transazzione.
NewSQL = NoSQL + ACID

C* One Coordinator di transazzione

U coordinatore hè qualcosa chì avemu implementatu per C * One da zero. Hè rispunsevuli di gestisce e transacciones, chjusi, è l'ordine in quale e transazzione sò applicate.

Per ogni transazzione servita, u coordinatore genera un timestamp: ogni transazzione sussegwenti hè più grande di a transazzione precedente. Siccomu u sistema di risoluzione di u cunflittu di Cassandra hè basatu annantu à i timestamps (di dui registri cunflitti, quellu cù l'ultimu timestamp hè cunsideratu attuale), u cunflittu serà sempre risoltu in favore di a transazzione successiva. Cusì avemu implementatu Orologio Lampport - un modu economicu per risolve i cunflitti in un sistema distribuitu.

Serrature

Per assicurà l'isolamentu, avemu decisu di utilizà u metudu più simplice - chjusi pessimisti basati nantu à a chjave primaria di u record. In altri palori, in una transazzione, un registru deve esse prima chjusu, solu dopu leghje, mudificatu è salvatu. Solu dopu un impegnu successu pò esse sbloccatu un registru in modu chì e transazzioni cuncurrenti ponu aduprà.

L'implementazione di tali blocchi hè simplice in un ambiente micca distribuitu. In un sistema distribuitu, ci sò duie opzioni principali: o implementà un chjusu distribuitu nantu à u cluster, o distribuisce transacciones in modu chì e transazzione chì implicanu u stessu record sò sempre servite da u stessu coordinatore.

Siccomu in u nostru casu, a dati hè digià distribuitu trà gruppi di transazzione lucali in SQL, hè statu decisu di assignà gruppi di transazzione lucali à i coordinatori: un coordinatore realiza tutte e transazzione cù tokens da 0 à 9, u sicondu - cù tokens da 10 à 19, eccetera. In u risultatu, ognunu di l'istanze di u coordinatore diventa u maestru di u gruppu di transazzione.

Allora i chjusi ponu esse implementati in a forma di un HashMap banale in a memoria di u coordinatore.

I fallimenti di u coordinatore

Siccomu un coordinatore serve solu un gruppu di transazzione, hè assai impurtante per determinà rapidamente u fattu di u so fallimentu in modu chì u sicondu tentativu di eseguisce a transazzione hà da u tempu. Per fà questu veloce è affidabile, avemu usatu un protokollu di quorum hearbeat cumplettamente cunnessu:

Ogni data center ospita almenu dui nodi coordinatori. Periodicamente, ogni coordinatore manda un missaghju di battitu cardiacu à l'altri coordinatori è li informa nantu à u so funziunamentu, è ancu di quale messagi di battimentu cardiacu hà ricevutu da quali coordinatori in u cluster l'ultima volta.

NewSQL = NoSQL + ACID

Ricevendu infurmazioni simili da l'altri cum'è parte di i so messagi di u battutu di u core, ogni coordinatore decide per ellu stessu quale nodi di cluster sò funziunanti è chì ùn sò micca, guidati da u principiu di quorum: se u node X hà ricevutu infurmazioni da a maiò parte di i nodi in u cluster nantu à u normale. ricezione di missaghji da u nodu Y, allora, Y travaglia. È vice versa, appena a maiuranza informa di missing missing from node Y, allura Y hà rifiutatu. Hè curiosu chì se u quorum informa u node X chì ùn riceve più messagi da ellu, u node X stessu cunsidererà chì hà fallutu.

I missaghji Heartbeat sò mandati cù alta frequenza, circa 20 volte per seconda, cù un periodu di 50 ms. In Java, hè difficiule di guarantisce a risposta di l'applicazione in 50 ms per via di a durata paragunabile di e pause causate da u cullettore di basura. Pudemu ottene stu tempu di risposta utilizendu u cullettore di basura G1, chì ci permette di specificà un mira per a durata di e pause GC. Tuttavia, a volte, abbastanza raramente, i pause di u cullettivu superanu 50 ms, chì ponu purtà à una falsa deteczione di difetti. Per impediscenu chì questu succede, u coordinatore ùn informa micca un fallimentu di un node remotu quandu u primu missaghju di u battitu di u cori sparisce, solu se parechji sò spariti in una fila ms.

Ma ùn hè micca abbastanza per capisce rapidamente quale node hà cessatu di funziunà. Avemu bisognu di fà qualcosa nantu à questu.

Riservazione

U schema classicu implica, in casu di un fallimentu maestru, principià una nova elezzione cù unu di moda universale algoritmi. Tuttavia, tali algoritmi anu prublemi cunnisciuti cù a cunvergenza di u tempu è a durata di u prucessu elettorale stessu. Pudemu evità tali ritardi supplementari usendu un schema di sustituzione di coordinatore in una rete cumpletamente cunnessa:

NewSQL = NoSQL + ACID

Dicemu chì vulemu eseguisce una transazzione in u gruppu 50. Determinemu in anticipu u schema di rimpiazzamentu, vale à dì chì nodi eseguisce transazzione in u gruppu 50 in casu di fallimentu di u coordinatore principale. U nostru scopu hè di mantene a funziunalità di u sistema in casu di fallimentu di u centru di dati. Determinemu chì a prima riserva serà un node da un altru centru di dati, è a seconda riserva serà un node da un terzu. Stu schema hè sceltu una volta è ùn cambia micca finu à chì a topologia di u cluster cambia, vale à dì, finu à chì i novi nodi entranu in questu (chì succede assai raramente). A prucedura per selezziunà un novu maestru attivu se l'anzianu falla sempre serà cusì: a prima riserva diventerà u maestru attivu, è s'ellu hà cessatu di funziunà, a seconda riserva diventerà u maestru attivu.

Stu schema hè più affidabile di l'algoritmu universale, postu chì per attivà un novu maestru hè abbastanza per determinà u fallimentu di u vechju.

Ma cumu i clienti capiscenu quale maestru travaglia avà? Hè impussibile di mandà infurmazioni à millaie di clienti in 50 ms. Una situazione hè pussibule quandu un cliente manda una dumanda per apre una transazzione, ùn sapendu ancu chì stu maestru ùn hè più in funziunamentu, è a dumanda sarà u tempu. Per impediscenu questu, i clienti speculativamente mandanu una dumanda per apre una transazzione à u maestru di u gruppu è e so riserve in una volta, ma solu quellu chì hè u maestru attivu in u mumentu risponde à sta dumanda. Tutte e cumunicazioni sussegwente in a transazzione seranu realizate da u cliente solu cù u maestru attivu.

I maestri di salvezza ponu ricivutu richieste per transacciones chì ùn sò micca i soi in a fila di transazzione nascuta, induve sò almacenati per qualchì tempu. Se u maestru attivu mori, u novu maestru processa e dumande per apre transazzione da a so fila è risponde à u cliente. Se u cliente hà digià apertu una transazzione cù u vechju maestru, allora a seconda risposta hè ignorata (è, ovviamente, una transazzione tali ùn serà micca cumpletata è serà ripetuta da u cliente).

Cumu funziona a transazzione

Diciamu chì un cliente hà mandatu una dumanda à u coordinatore per apre una transazzione per una tale è una tale entità cù una tale è una chjave primaria. U coordinatore chjude sta entità è a mette in a tavola di serratura in memoria. Se ne necessariu, u coordinatore leghje sta entità da u almacenamentu è guarda i dati resultanti in un statu di transazzione in a memoria di u coordinatore.

NewSQL = NoSQL + ACID

Quandu un cliente vole cambià a dati in una transazzione, manda una dumanda à u coordinatore per mudificà l'entità, è u coordinatore mette a nova dati in a tabella di statutu di transazzione in memoria. Questu compie a registrazione - nisuna registrazione hè fatta à l'almacenamiento.

NewSQL = NoSQL + ACID

Quandu un cliente dumanda i so dati mudificati cum'è parte di una transazzione attiva, u coordinatore agisce cusì:

  • se l'ID hè digià in a transazzione, allora i dati sò pigliati da a memoria;
  • s'ellu ùn ci hè micca ID in memoria, allora i dati mancanti sò letti da i nodi di almacenamiento, cumminati cù quelli chì sò digià in memoria, è u risultatu hè datu à u cliente.

Cusì, u cliente pò leghje i so cambiamenti, ma altri clienti ùn vedenu micca questi cambiamenti, perchè sò stati guardati solu in a memoria di u coordinatore ùn sò micca ancu in i nodi di Cassandra.

NewSQL = NoSQL + ACID

Quandu u cliente manda commit, u statu chì era in a memoria di u serviziu hè salvatu da u coordinatore in un batch logged, è hè mandatu cum'è un batch logged à Cassandra storage. I magazzini facenu tuttu ciò chì hè necessariu per assicurà chì stu pacchettu hè applicatu atomicamente (cumpletamente), è torna una risposta à u coordinatore, chì libera i chjusi è cunfirma u successu di a transazzione à u cliente.

NewSQL = NoSQL + ACID

È per rollback, u coordinatore solu bisognu di liberà a memoria occupata da u statu di transazzione.

In u risultatu di e migliure sopra, avemu implementatu i principii ACID:

  • Atomicità. Questa hè una guaranzia chì nisuna transazzione serà parzialmente arregistrata in u sistema, sia tutte e so suboperazioni seranu compie, o nimu serà cumpletu. Aderemu à stu principiu attraversu batch logged in Cassandra.
  • Cuerenza. Ogni transazzione successu, per definizione, registra solu risultati validi. Se, dopu avè apertu una transazzione è eseguisce una parte di l'operazioni, hè scupertu chì u risultatu hè invalidu, un rollback hè realizatu.
  • Isulamentu. Quandu una transazzione hè eseguita, e transazzione simultanea ùn deve micca affettà u so risultatu. E transazzione in cuncurrenza sò isolate usendu chjusi pessimisti nantu à u coordinatore. Per leghje fora di una transazzione, u principiu di isolamentu hè osservatu à u livellu Read Committed.
  • Sostenibilità. Indipendentemente da i prublemi à i livelli più bassi - blackout di u sistema, fallimentu di hardware - i cambiamenti fatti da una transazzione cumpleta cù successu duveranu esse cunservati quandu l'operazione ripiglià.

Lettura per indici

Pigliemu una tavola simplice:

CREATE TABLE photos (
id bigint primary key,
owner bigint,
modified timestamp,
…)

Havi un ID (chjave primaria), u pruprietariu è a data di mudificazione. Avete bisognu di fà una dumanda assai simplice - selezziunate dati nantu à u pruprietariu cù a data di cambiamentu "per l'ultimu ghjornu".

SELECT *
WHERE owner=?
AND modified>?

Per chì una tale dumanda sia processata rapidamente, in un DBMS SQL classicu avete bisognu di custruisce un indici per colonne (proprietariu, mudificatu). Pudemu fà questu abbastanza facilmente, postu chì avemu avà garanzii ACID!

Indici in C * One

Ci hè una tavola fonte cù ritratti in quale l'ID record hè a chjave primaria.

NewSQL = NoSQL + ACID

Per un indice, C * One crea una nova tavula chì hè una copia di l'uriginale. A chjave hè listessa cum'è l'espressione di l'indici, è include ancu a chjave primaria di u record da a tavola fonte:

NewSQL = NoSQL + ACID

Avà a dumanda per "proprietariu per l'ultimu ghjornu" pò esse riscritta cum'è una scelta da una altra tavola:

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

A coherenza di e dati in e foto di a tavola fonte è a tavola d'indici i1 hè mantinuta automaticamente da u coordinatore. Basatu nantu à u schema di dati solu, quandu un cambiamentu hè ricevutu, u coordinatore genera è guarda un cambiamentu micca solu in a tavola principale, ma ancu in copie. Nisuna azzioni supplementarii sò realizati nantu à a tavola d'indici, i logs ùn sò micca letti, è ùn sò micca usati chjusi. Vale à dì, l'aghjunzione di l'indici ùn cunsuma quasi nisuna risorsa è ùn hà praticamente micca effettu nantu à a rapidità di applicà mudificazioni.

Utilizendu ACID, pudemu implementà indici simili à SQL. Sò coerenti, scalabili, veloci, cumponibili è integrati in a lingua di query CQL. Nisuna mudificazione à u codice di l'applicazione hè necessariu per sustene l'indici. Tuttu hè simplice quant'è in SQL. È più importantemente, l'indici ùn anu micca influenzatu a velocità di esecuzione di mudificazioni à a tabella di transazzione originale.

Chì hè accadutu

Avemu sviluppatu C * One trè anni fà è lanciamu in operazione cummerciale.

Chì avemu avutu à a fine ? Evaluemu questu aduprendu l'esempiu di u sottosistema di trasfurmazioni è di almacenamiento di foto, unu di i tipi di dati più impurtanti in una reta suciale. Ùn parlemu micca di i corpi di i ritratti stessi, ma di ogni tipu di meta-informazioni. Avà Odnoklassniki hà circa 20 billion such records, u sistema processa 80 mila richieste di lettura per seconda, finu à 8 mila transazzione ACID per seconda assuciata cù a mudificazione di dati.

Quandu avemu usatu SQL cù fattore di replicazione = 1 (ma in RAID 10), a metainformazione di a foto hè stata guardata in un cluster altamente dispunibile di macchine 32 chì eseguenu Microsoft SQL Server (più 11 backups). 10 servitori sò stati ancu attribuiti per almacenà e copie di salvezza. Un totale di 50 vitture caru. À u listessu tempu, u sistema operatu à carica nominale, senza riserva.

Dopu avè migratu à u novu sistema, avemu ricevutu un fattore di replicazione = 3 - una copia in ogni centru di dati. U sistema hè custituitu da 63 nodi di almacenamiento Cassandra è 6 macchine di coordinatori, per un totale di 69 servitori. Ma sti machini sò assai più prezzu, u so costu tutale hè di circa 30% di u costu di un sistema SQL. À u listessu tempu, a carica hè tenuta à 30%.

Cù l'intruduzioni di C * One, a latenza hè ancu diminuita: in SQL, una operazione di scrittura hà pigliatu circa 4,5 ms. In C * One - circa 1,6 ms. A durata di a transazzione hè in media di menu di 40 ms, u cummit hè cumpletu in 2 ms, a durata di lettura è scrittura hè in media di 2 ms. 99th percentile - solu 3-3,1 ms, u numeru di timeouts hè diminuitu da 100 volte - tuttu per via di l'usu generalizatu di speculazione.

A ora, a maiò parte di i nodi di u SQL Server sò stati decommissionati novi prudutti sò sviluppati solu cù C * One. Avemu adattatu C * One per travaglià in u nostru nuvulu una sola nuvola, chì hà permessu di accelerà a implementazione di novi clusters, simplificà a cunfigurazione è automatizà l'operazione. Senza u codice fonte, fà questu seria assai più difficiule è ingombrante.

Avà travagliammu per trasferisce e nostre altre strutture di almacenamento in u nuvulu - ma hè una storia completamente diversa.

Source: www.habr.com

Add a comment