resenje za problem velikog broja podataka

Poruka
6.708
Pre no sto napisem o cemu se radi, samo da jos jednom napomenem da IT treba da ima podforum u kome bi bilo nesto drugo nego internet, igrice i hardware.

Elem, ovako....

Natrcao sam na interesantan real-life problem, pa bi me zanimalo od vas IT profesionalaca kako i odakle bi napali resenje problema.



Imate jedan (izvorni) server koji sadrzi recimo 500 miliona nekih objekata (na primer stringova). Treba da obradite podatke na drugom serveru preko rest apija (jer izvorni server nije dizajniran za tu vrstu obrade). API ocekuje samo listu IDjeva objekata da bi odradio svoj posao i vratio rezultat.

U datom trenutku korisnik nekm nacinom na izvornom serveru odabere za koje objekte je zainteresovan da se obrade, i time formira listu IDova objekata. I s pravom ocekuje da dobije rezultat u nekoliko sekundi (obrada zapravo i traje neke sekunde)

Sta je problem?

Problem je sto 'selektovana' lista IDova moze da ima recimo 80 miliona IDova (moze da bude i 250 miliona isto tako)

------------------------
slusam Ideje ...
a i ako treba nesto da pojasnim, pojasnicu
 
i time formira listu IDova objekata. I s pravom ocekuje da dobije rezultat u nekoliko sekundi (obrada zapravo i traje neke sekunde)
tesko da ce to za nekoliko sekundi, ako ima 30 miliona.
pretpostavljam da nije trivijalna obrada, cim ne moze na klijentu.
to je prakticno sve jedno dal ce ici 30 miliona malih requesta ili jedan veliki.
 
tesko da ce to za nekoliko sekundi, ako ima 30 miliona.
pretpostavljam da nije trivijalna obrada, cim ne moze na klijentu.
to je prakticno sve jedno dal ce ici 30 miliona malih requesta ili jedan veliki.
Da.


I jeste drugi (API) server je krckator (totalno drugaciji hardware, koji nema smisla da bude na izvornom serveru - izvorni je manje vise standardan za neki web app)
 
load balanser, pa rasporedis, no cisto sumnjam da jedan klijent moze da napravi vise od par hiljada
requesta u sekundi....

slazem se - ogranicenje je mreza pa makar islo na 3 krckatora, ali koliko znam problem nije tipa da moze da se podeli na delove (mada ne znam mozda i moze, morao bi da pitam, ali mozemo da podjemo od pretpostavke da ne moze parcijalno da se obradjuje). Ali, i dalje cak i na x krckatora i load balancerom moralo bi opet da se proturi tih xM/G/Tb preko mreze.

E da, primecujem da pominjes hiljade requestova - ne mora da se salje jedan po jedan, moze i sve odjednom, ili na chunks.
 
E da, primecujem da pominjes hiljade requestova - ne mora da se salje jedan po jedan, moze i sve odjednom, ili na chunks.
moze jedan, ali onda moras sam da pises load balanser....
edit:
30 miliona requsta za nekoliko sekundi, ne moze ni google ni amazon.
your best bet je 40-60k requsta u sekundi, bilo kao jedan veliiki
ili kao vise manjih.
 
Poslednja izmena:
Cek, ajmo ovako:
Korisnik nekako zna svih 500 miliona ID-eva za 500 miliona objekata, koji se cuvaju na ServeruB (data).
Korisnik iz neke aplikacije zove ServerA (API)
ServerA zove ServerB (data) da pokupi podatke, obradi, i vrati nazad.
Sad, problem:
Korisnikov request za ServerA moze da sadrzi listu od 60 miliona ID-eva, a request je ogranicen velicinom body-a POST requesta, koje je promenljivo i zavisi i od toga koliko browser dozvoli (sto mislim da je oko 2GB) i koliko web server dozvoli (tu ogranicenje moze biti i od nekoliko megabajta po requestu, to moras nekako da saznas).
Onda je posle toga prosto: kad odredis koliko ID-eva mozes da upakujes u jedan request, podelis na vise requestova, i odradis.
I to je to.

Sad, komunikacija ServerA i ServerB je druga prica, i to nisi nista rekao.
 
Evo, ugrubo sam proverio da bi request od 60 miliona id-eva, gde je Id u formatu GUID-a, iznosio oko 2.3 GB.
Dakle, ako tvoj browser podrzava 2GB, a server je podesen na ne manju vrednost od toga, onda 2 requesta bi bila dovoljna.
Sad, vreme procesuiranja na ServeruA je nesto sasvim drugo, zavisi od trilion stvari, najvise od toga da li sada ServerA pristupa dalje nekoj bazi podataka i kako je to realizovano, itd, itd.
Usko grlo je latency u pozivu i u otvaranju konekcije sa bazom. To su (vremenski) skupe operacije, i kada se radi sa milionima podataka, optimizacija se svodi na to da imas sto manje poziva, sto manje otvaranja konekcije sa bazom, pa tek onda na optimizaciju algoritma koji konkretno obradjuje te podatke.

Pre godinu dana sam samo redukcijom poziva prema bazi podataka, ubrzao peformanse neke obrade sa 15+ sekundi na red <10ms. Klijent skakao od srece :D
 
Cek, ajmo ovako:
Korisnik nekako zna svih 500 miliona ID-eva za 500 miliona objekata, koji se cuvaju na ServeruB (data).
Korisnik iz neke aplikacije zove ServerA (API)
Da.

Korisnik koristi web aplikaciju na serveru B i zna da ima 500 miliona objekata, kroz tu web aplikaciju odabere listu objekata koji hoce da obradjuje (po nekom kriterijumu). Zatim izda komandu da se zahtev obradi. Dalje u sledecem bloku.

ServerA zove ServerB (data) da pokupi podatke, obradi, i vrati nazad.
Server B (data) pita (zove) Server A (api): "daj mi rezultat za set podataka koje ti saljem" (recimo 80M IDjeva)
Implicitno, podrazumeva se da server B ima listu svih objekata, a posto se prenose samo IDjevi, to znaci i da server A ima sve te podatke kesovane (unapred, nekako)

Sad, problem:
Korisnikov request za ServerA moze da sadrzi listu od 60 miliona ID-eva, a request je ogranicen velicinom body-a POST requesta, koje je promenljivo i zavisi i od toga koliko browser dozvoli (sto mislim da je oko 2GB) i koliko web server dozvoli (tu ogranicenje moze biti i od nekoliko megabajta po requestu, to moras nekako da saznas).
Server A i Server B komuniciraju iza scene, browser (korisnik) prica samo sa Serverom B (data), a iza scene (backend) server B pita server A za obradu za taj set podataka.

Ogranicenje nije u velicini podataka koji se salju (moze bilo koja velicina da se progura na ovaj ili onaj nacin cak i svih 500M ID-ova odjednom), problem je vreme koje je sto pre da se dobije odgovor. Tako da korisnik ne ceka minute, pa i sate da dobije odgovor, nego sekunde. Sama obrada traje u sekundama, prenos tamo amo je ono sto je problem.

Onda je posle toga prosto: kad odredis koliko ID-eva mozes da upakujes u jedan request, podelis na vise requestova, i odradis.
I to je to.
Mogu svi podaci zahtevanog seta da se upakuju u 1 request (kontrola je potpuna na oba servera - moze da se konfigurise bilo sta)

ali pitanje je odlicno.

I to moram da ispitam - sta se zapravo vraca?

- u medjuvremenu za potrebe primera zadatka uzmimo da se vraca podset IDjeva. Znaci server A preko apija primi 80M IDjeva (ili mu B poslaje kako god - isto je) i vrati recimo 20.000 ID rezultata serveru B koji prikaze korisniku tih 20000 rezultata u browseru.

Sad, komunikacija ServerA i ServerB je druga prica, i to nisi nista rekao.

Server A i Server B su u nekom data centru, pretpostavka je da je izmedju njih maksimalna brzina mreze. To mi takodje nije poznato, ali to moze da bude znacajna stavka ako su Server A i B na razlicitim mrezama (sto je takodje vrlo moguc scenario).
 
Evo, ugrubo sam proverio da bi request od 60 miliona id-eva, gde je Id u formatu GUID-a, iznosio oko 2.3 GB.
Dakle, ako tvoj browser podrzava 2GB, a server je podesen na ne manju vrednost od toga, onda 2 requesta bi bila dovoljna.
Sad, vreme procesuiranja na ServeruA je nesto sasvim drugo, zavisi od trilion stvari, najvise od toga da li sada ServerA pristupa dalje nekoj bazi podataka i kako je to realizovano, itd, itd.
Usko grlo je latency u pozivu i u otvaranju konekcije sa bazom. To su (vremenski) skupe operacije, i kada se radi sa milionima podataka, optimizacija se svodi na to da imas sto manje poziva, sto manje otvaranja konekcije sa bazom, pa tek onda na optimizaciju algoritma koji konkretno obradjuje te podatke.

Pre godinu dana sam samo redukcijom poziva prema bazi podataka, ubrzao peformanse neke obrade sa 15+ sekundi na red <10ms. Klijent skakao od srece :D

To je smislena racunica, na svu srecu IDovi u ovom slucaju a koji bi se slali, su manji od GUID-a po zahtevnom prostoru, i svode se na intigere (racunam 32 bit integeri mogu da pokriju IDove do 4G objekata. Tako da bi to bilo baseline. 60M ideova bi onda bilo oko 228Mb upita. Moze da stane u memoriju s obe strane Posto je set transient (kratkoziveci i nebitan posle obrade) ne mora da se napravi permanentnim u nekoj bazi podataka samo se obradi. Naravno vraca se neki set rezultata.
 
Mnogo "ako" i mnogo nepoznanica.

Pokusao sam konceptualno da objasnim problem i da definisem sto je moguce vise apstraknto. Kroz dijalog, mogu da odgovorim na neka pitanja ili da shvatim da mi treba jos informacija koje treba definisati. Zato zasad i ima dosta 'ako' i 'nepoznanica'. Ideja i jeste da se kroz dijalog sagleda problem sire i pokapira sta bi mogla da budu resenja.

Kako vama odgovaram na pitanja i ja sam muckam po glavi razlicite aspekte problema (na sta obratiti paznju).

Na primer ono sto meni pada trenutno na pamet je da se korisnik ogranici da radi obradu ili do nekog smislenog broja izabranih objekata ili nad svim objektima.

U prvom slucaju (podskup) odredila bi se neka maksimalna kolicina IDova koja se dovoljno brzo prenosi i korisnik bi se obavestio ako nije izabrao dovoljno mali set da jos suzi set ako moze.

U drugom slucaju (svi podaci) ne treba ni jedan ID da se posalje jer se radi nad celim poznatim setom podataka.
 
lepo. sad nema problema, transfer nije problem, ako je brz link

mreza jeste kritican faktor. Mora da bude neki brzi link izmedju. Ili da nekako nategnemo da budu na istoj mrezi ako je ikako moguce (ovo drugo trenutno ne znam sad, ali vrv mogu da saznam).

Ima tu mesa i za tvoju ekspertizu (recimo u Rust ili Go da bude sto blize native to CPU).

Recimo da se smisli neki algoritam za kompresiju niza integera.
Recimo da set od recimo 100M integera kroz kompresiju moze da se smanji na 10% dakle da bude 10M umesto 100M integera. To bi pomoglo mnogo da se smanji pritisak na mrezu. Server B bi 'spakovao' niz za request. Server A bi 'raspakovao' niz za obradu.

Da li mislis da bi bilo bolje na 64bit arhitekturi da se obradjuju 32bitni integeri ili 64bitni integeri? Ako se koriste 64bit integeri onda su podaci duplo veci u prenosu. Ja bih isao za prenos u 32bita a interno moze i 64.
 
mreza jeste kritican faktor. Mora da bude neki brzi link izmedju. Ili da nekako nategnemo da budu na istoj mrezi ako je ikako moguce (ovo drugo trenutno ne znam sad, ali vrv mogu da saznam).

Ima tu mesa i za tvoju ekspertizu (recimo u Rust ili Go da bude sto blize native to CPU).

Recimo da se smisli neki algoritam za kompresiju niza integera.
Recimo da set od recimo 100M integera kroz kompresiju moze da se smanji na 10% dakle da bude 10M umesto 100M integera. To bi pomoglo mnogo da se smanji pritisak na mrezu. Server B bi 'spakovao' niz za request. Server A bi 'raspakovao' niz za obradu.

Da li mislis da bi bilo bolje na 64bit arhitekturi da se obradjuju 32bitni integeri ili 64bitni integeri? Ako se koriste 64bit integeri onda su podaci duplo veci u prenosu. Ja bih isao za prenos u 32bita a interno moze i 64.
moze kompresija bilo koja, u post request mozes da stavis binarne podatke. server to samo procita i dekompresuje istom metodom.
imas free libova za kompresiju.
 

Back
Top