Sunteți pe pagina 1din 7

Online event processing

Atinge consistenta acolo unde tranzactiile distribuite au esuat

Pentru mai bine de un jumate de secol, tranzactiile ACID au asigurat consistenta in


sistemele bazate pe stocarea de date.
Dar ce reprezinta ACID? ACID reprezinta un acronim pentru proprietatile care definesc acest
concept. Si sunt aceste proprietati?
1) Atomicitatea - e bazat pe conceptul “totul sau nimic” - asigura ca ori toate, ori nici o
actiune a tranzactiei are efect in caz de esec.
2) Consistenta care spune ca baza de date trebuie sa ramana consistenta, indiferent de
actiunile tranzactiilor.
3) Independenta care previne interferenta care ar putea fi provocata de rularea
concurenta a mai multor tranzactii
4) Durabilitatea - asigura ca toate modificarile comise de o tranzactie nu vor fi pierdute
in caz de esec.

Tranzactiile lucreaza foarte bine cu produse care au o singura baza de date. Cand vine
vorba de a lucra cu mai multe parti de stocare de date, de la diferiti distribuitori, tranzactiile
sunt problematice. Astfel, aplicatiile de scara mare folosesc o abordare ad hoc,
neoptimizata, pentru a putea mentine consistenta sistemelor lor.

In ciuda acestui fapt, recent, s-a inceput folosirea din ce in ce mai deasa a event log-urilor ca
si un mecanism de management de date in aplicatiile de dimensiuni mari. Aceste log-uri de
events - sunt cunoscute sub numele de OLEP, adica online event processing.

Persistenta Polyglot
Diferite sisteme de stocare de date sunt realizate pentru a accesa si a folosi diferite pattern-
uri, nu exista un tip de sistem de stocare care sa fie un all-arounder pentru tot ceea ce
exista. De aceea, foarte multe aplicatii folosesc in ziua de azi o combinatie de tehnologii de
stocare, o abordare cunoscuta cu termenul de persistenta polyglot.
Exemple - full-text search, Data warehousing, Stream processing, Application-Level caching.
Este de mentionat ca aceste sisteme de stocare nu sunt total independente unele fata de
altele - ba chiar, de multe ori, e normal ca un sistem sa iti tina copii de date intr-un alt sistem
de stocare. Deci, de mule ori, cand un sistem isi updateaza anumite date, e nevoie sa fie
updatate si in celelalt sistem - exemplu figura 1.
Tranzactiile OLTP (online transaction processing) sunt scurte si predefinite.
Majositatea OLTP-urilor sunt actionate/trigg-uite de requesturi facute prin HTTP de catre
useri, requesturi facute unei aplicatii web sau serviciu web. In majoritatea aplicatiilor,
actiunea tranzactiilor nu se extinde mai mult decat satisfacerea unui singur request HTTP.
De asemenea, OLTP-urile executa un set mic de pattern-uri de tranzactii. In principiu se
folosesc proceduri stocate pentru a encapsula business logic-ul tranzactiilor.

Tranzactiile eteorgene si distribuite sunt problematice


Tranzactiile eteorgene si distribuite actioneaza in diferite tehnologii de stocare a unor diferiti
furnizori. Din cauza definitiei si constructiei lor, trnazactiile eterigene si distribuite pot sa se
bazeze doar pe cel mai mic numitor comun al sistemelor participante. Astfel, tranzactiile sunt
problematice. De exemplu, tranzactiile XA (extended architecture) blocheaza executia daca
procesul unei aplicatii esueaza in faza de pregatire. De asemenea, tranzactiile XA nu ofera
detectia deadlock-urilor si nu ofera niciun suport pentru schemele de control de concurenta
optimista.

BUILDING UPON EVENT LOGS


Daca avem tranzactii eterogene distribuite, sistemul poate sa asigure atomicitatea scrierii
intre 2 sisteme. Totusi, majoritatea serverelor de cautare nu suporta tranzactiile distribuite,
lasat sistemul vulnerabil la diferite tipuri de inconsistente:
- Scriere non-atomica - daca cumva avem o esuare, e posibil ca o scriere sa fie intr-un
sistem, dar nu in celelalt sistem
- Ordinea diferite a scrierilor - daca avem 2 requesturi concurente de update A si B
pentru aceleasi intregistrari, un sistem poate procesa requesturile intr-o ordine, iar
celelalt sistem in alta ordine

O solutie simpla pentru aceste probleme descrise mai in sus ar fi:


- In loc de a face scrieri directe in cele 2 sisteme de stocare, adauga un event de
update intr-un log. Baza de date si index-ul de cautare subscriu la log si astfel, ei
realizeaza updates in sistemul de stocare in ordinea in care cererile apar in log.
Astfel, se asigura consitenta sistemelor.
Abstractizarea log-urilor
Sunt o multitudine de implementari care pot servi abstractizarea de log-uri (Apache Kafka,
CORFU de la Microsoft, LogDevice de la Facebook, etc). Toate aceste implementari, si nu
numai, au in comun anumite proprietati:
- Durabilitate - log-ul e scris pe disk si e replicat la diferite noduri, pentru a nu fi
pierdute cumva.
- Doar adaugare sau append-only - evenimentele pot fi adaugate in log doar prin
adaugarea lor la finalul log-ului.
- Citiri secventiale - Toti subscriberii log-ului vad acelasi evenimente in aceeasi ordine.
Fiecarui event ii e asignat un LSN (numar de secventa log - log sequence number) si
astfel se stabileste si ordinea, in functie de acest LSN.
- Tolerant de erori - log-ul ramane disponibil pentru citire si scriere in prezenta unei
esuari
- Partitionat - un log individual poate avea o capacitate maxima de tranzitie de date,
dar care nu e neaparat suficienta. Astfel, un sistem suporta partitionarea unui log
mare in log-uri mai mici, care in final pot fi multiplexate intr-o singura partitie fizica de
log.

Semantica - exactly once


Exista cateva procesoare stream bazate pe log-uri (de exemplu Apache Flink) suporta
semantica exactly-once, care presupune ca, chiar daca un event a fost procesat de mai
multe ori, efectul procesarilor e de fiecare data acelasi, rezultatul e acelasi, ca si cum ar fi
fost procesat o singura data.
Dar, daca un consumator de log-uri scrie in sisteme de stocare externe (exemplu fig 2),
semanticele exactly-once nu pot fi asigurate, pentru ca ar trebui sa existe un protocol de
commit atomic si eterogen intre procesir si sistemul de stocare, lucru care inca nu exista pe
multe sisteme de stocare.
Totusi, multe framework-uri cu semantica exactly-once reusesc sa realizeze o actiune de
“cel putin o procesare” cand interactioneaza cu sisteme externe de stocare, bazandu-se apoi
pe idempotenta pentru a elimina efectele unei procesari duplicate.

Atomicitatea si impunerea constrangerilor


Un exemplu clasic in care atomicitatea este necesara este cel al sistemului de plati bancare,
in care transferul intre 2 conturi se face intr-un mod atomic.
Totodata acest sistem trebuie sa fie si consistent in sensul in care, spre exemplu, retragerea
numerarului dintr-un cont se limiteaza pana la o anumita suma.
In figura 3 este reprezentat un astfel de sistem care foloseste metoda OLEP in locul
tranzactiilor distribuite.

Semnificatia sagetii pline - adaugarea unui eveniment la un log, iar a sagetii deschis -
subscrierea la evenimentele dintr-un log.

Cum functioneaza:
1. Atunci cand utilizatorul doreste sa realizeze un transfer, prima data adauga un
eveniment de cerere de plata la logul contului sursa, indicand doar intentia de a
efectua un transfer. Evenimentul detine un ID unic cu ajutorul caruia se poate
identifica cererea.
2. Un proces executant al platii, care e pe un singur thread, subscrie la log-ul contului
sursa. Acesta verifica intr-un mod deterministic daca cererea de transfer ar trebui sa
fie acceptata pe baza soldului curent si eventual a altor factori
3. In cazul in care procesul executant ofera permisiunea de plata, ii comunica bazei de
date locale si adauga evenimentele la diferite log-uri: sub forma unui eveniment de
plata de iesire catre contul sursa si sub forma unui eveniment de plata de intrare
pentru contul destinatie. Se mai poate adauga, de asemenea, un eveniment de plata
pentru taxe. Toate aceste evenimente generate detin ID-ul evenimentului original.
4. Evenimentul de plata de iesire se intoarce inapoi la procesul executant care a
subscris acestuia.
5. Restul celorlalte evenimente sunt procesate intr-un mod similar de cate un proces
executant per fiecare cont. Intregul proces este idempotent pentru ca se elimina ID-
urile duplicate.
6. Severul care gestioneaza cererea utilizatorului poate la randul sau sa subscrie la
logul contului sursa si astfel sa fie notificat cand s-a procesat plata. Informatia despre
status poate fi returnata la utilizator.
Daca plata esueaza, se poate intampla sa se reproceseze anumite cereri care au
fost partial procesate si inainte de esec. Astfel pot aparea evenimente de plata
duplicate la nivelul contului sursa, dar aceasta problema se poate rezolva usor pe
baza ID-urilor unice.

Procesarea multipartiție

In cadrul acestui exemplu de plata, fiecare cont are un log separat care se poate
stoca pe un nod diferit. Fiecare proces executant trebuie sa subscrie doar la
evenimentele unui singur cont, deci fiecare cont are un alt executant.
In exemplul dat, permisiunea de plata este data doar in functie de soldul contului
sursa, drept pentru care se poate presupune ca plata se realizeaza intotdeauna cu
succes pentru ca soldul contului destinatie nu poate decat sa creasca. Din aceasta
cauza, executantul platii trebuie sa serializeze cererea de plata doar in ceea ce
priveste celelalte evenimente care au loc in cadrul contului sursa.
Atunci cand alte partitii ale log-ului contribuie la decizie, plata se aproba printr-un
proces format din mai multe etape care serializeaza cererea in mod corespunzator
log-urilor.
Impartirea transactiei intr-un pipeline de procese pe etape multiple permite fiecarei
etape sa progreseze doar pe baza datelor locale => partitiile nu sunt niciodata
blocate si ofera scalabilitate sistemelor OLEP.

Avantajele procesarii de eveniment

● Se pot crea vizualizari derivate noi sau servicii bazate pe log-uri de eveniment
usor.
● Subscriberii se pot programa asa incat sa ignore evenimente gresite, spre
deosebire de bazele de date care permita efectuarea arbitrara a operatiilor de
insertie, stergere, actualizare.
● Debugging-ul este mult mai usor datorita acestor loguri care permit doar
adaugare (concatenare)
● Facilitate crescuta in privinta modelarii datelor - rationarea consta in faptul ca
evenimentele pastreaza starea tranzitiilor cu o acuratete mult mai mare decat
operatiile CRUD pe tabele = side effects. (exemplu “student cancelled course
enrollment” clearly expresses intent, whereas the side effects “one
row was deleted from the enrollments table” and “one cancellation reason was added
to the student feedback table” are much less clear).
● Log-ul unui eveniment este mult mai valoros pentru un analist de date, spre
exemplu intr-o aplicatie e-commerce ar fi de un interes considerabil intregul
proces de adaugare si stergere de produse din cosul de cumparaturi, nu doar
ce contine acesta la checkout, pentru ca s-ar putea ca acest client sa se
reintoarca ulterior dupa un produs sters.
● La tranzactia distribuita, daca se intampla ca un nod sa fie indisponibil, atunci
intreaga tranzactie trebuie sa fie reluata. Spre deosebire de aceasta, la un log
cu subscriberi multipli, fiecare progreseaza independent.

Dezavantajele abordarii OLEP

In ciuda faptului ca abordarea OLEP garanteaza procesarea tuturor evenimentelor


de catre fiecare consumer, nu exista o limita de timp pentru acest lucru.
Acest fapt poate conduce la inconsistente ale valorilor citite de clienti din baza de
data in cazul in care au avut loc modificari concomitente asupra aceleiasi date (de
exemplu citirea contului sursa dupa plata si a contului destinatie inainte sa fi avut loc
transferul, totusi intr-un final vor converge catre o stare consistenta).

Studiu de caz : THE NEW YORK TIMES

New York Times pastreaza tot continutul text intr-o singura partitie log in Apache Kafka inca
de cand a fost infiintat acest ziar, in 1851.
De fiecare data cand un nou continut (asset) este publicat sau actualizat, se adauga un
eveniment la log, la care subscriu mai multe servere.
Ordinea evenimentelor din log satisface 2 reguli:
● Intotdeauna assetul care referentiaza un alt asset apare inaintea acestuia in log
● La actualizarea unui asset, ultima versiune devine cea publicata de ultimul eveniment
din log.

De exemplu, un editor ar putea sa publice o imagine si apoi sa actualizeze un articol care sa


referentieze imaginea. In acest caz fiecare consumer al log-ului are de parcurs 3 etape:
1. Versiunea veche a articolului exista
2. Imaginea exista dar este nereferentiata de articol
3. Atat articolul cat si imaginea exista, cu articolul care referentiaza imaginea

Astfel se asigura ca articolul nu referentiaza o imagine inexistenta.


Acest model consistent ofera beneficiile tranzactiilor distribuite fara pierderea
performantelor.

Concluzie
OLEP este folosita din ce in ce mai mult datorita performantei superioare, a consistentei
puternice pe care o poate garanta, fiind si linear scalabila.
Spre deosebire de sistemele de date care folosesc log-urile pentru a oferi detalii interne de
implementare, OLEP foloseste log-urile ca un prim model de aplicatie care gestioneaza
datele.
Numeroasele avantaje ale acestei abordari fac ca OLEP sa fie din ce in ce mai popular in
randul sistemelor mari bazate pe tehnologii eterogene de stocare.