Kako smo ukrotili HBase?

Share

Pre nešto više od godinu dana postala sam deo Ibis Instruments Big Data tima u ulozi Big Data softverskog inženjera. Ibis Instruments se već značajno vreme bavi oblasti Big Data i u proteklih nekoliko godina uspeli smo da razvijemo sopstveno Big Data rešenje Ibis Performance Insights, iPi. Do sada smo  razvili nekoliko iPi Big Data okruženja i kao što to obično biva u developerskom svetu, tokom svakog smo nailazili na različite izazove i prepreke. Stoga sam odlučila da sa vama podelim jedno od naših najznačajnih iskustava koje se tiče HBase-a i njegovog uticaja na jedno od naših najvećih i najznačajnijih Big Data okruženja. Međutim, pre nego što dublje uronimo u tematiku ovog posta, važno je da vas na kratko upoznam sa arhitekturom iPi-ja.

Šta je iPi?

iPi je Big Data rešenje zasnovano na open source tehnologijama. U njegovoj osnovi nalazi se izuzetno moćna Hadoop platforma koja zajedno sa ostalim Big Data komponentama čini jedan veliki ekosistem odgovoran za skladištenje, procesuiranje i obradu velikih količina podataka u gotovo realnom vremenu. Ova platforma distribuirana je na nekoliko mašina koje zajedno čine Big Data klaster i organizovane su u master-slave arhitekturu. Dve od ovih mašina, takozvani namenode-ovi, imaju ulogu u administraciji i skladištenju bitnih informacija o sistemu, dok slave mašine, odnosno datanode-ovi, imaju ulogu u izvršavanju taskova zadatih od strane aktivnog namenoda-a i odgovorni su za pouzdano i efikasno skladištenje i obradu podataka.

Drugi značajan deo iPi-ja čini web aplikacija, koja služi za prikazivanje rezultata dobijenih pomoću Big Data klastera, ali kako bi ovaj post zadržao konciznost i jasnoću, ova aplikacija biće tema nekog od narednih postova.

Pošto sam već napisala par redova o Hadoop platformi, možete pretpostaviti da smo ulogu pouzdanog skladištenja podatka prepustili upravo jednoj od osnovnih komponenti Hadoop-a, a to je HDFS (Hadoop Distributed File System). HDFS je izuzetno značajna komponenta, jer može da podrži skladištenje velikih količina podataka, vrlo lako postižući fault-tolerant stanje kopirajući podatke u preciziran broj instanci. Međutim, ove značajne kvalitete HDFS plaća I/O kašnjenjem i tu na scenu stupa upravo HBase, distribuirano, skalabilno skladište podataka koje radi preko HDFS-a. HBase predstavlja ključnu komponentu za IPI jer je dizajniran tako da podrži brz pristup tabelama koje sadrže bilione redova i milione kolona što mu omogućava da efikasno opslužuje aplikacije koje zahtevaju brz, proizvoljan pristup velikim setovima podataka što posebno odgovara našoj web aplikaciji u okviru iPi-ja. Dodatno, radi optimizacije brzog čitanja i upisa velike količine Time Series podataka, preko HBase-a instaliran je specijalizovan layer za brz upis i čitanje podataka, pri čemu instanca ovog alata postoji na svakoj mašini u Big Data klasteru. Sve ove instance gledaju u istu HBase tabelu u kojoj se nalaze podaci, pri čemu se instance na datanode-ovima koriste isključivo za upis, a instance na namenode-ovima za čitanje podataka.

Problem!!!

Već sam napomenula da je Big Data okruženje koje je tema ovog posta jedno od naših najvećih i najznačajnih okruženja. Big Data klaster ovog okruženja sastoji se od 11 mašina kapaciteta od oko 10TB i 64GB RAM-a, pri čemu devet datanode-ova trenutno ima zadatak da pouzdano i efikasno skladišti i obradi 50TB kompresovanih podataka, a podrazumeva se da će ovaj broj nastaviti da raste.

Big Data oblast iz dana u dan postaje sve popularnija i sve više evoluira, pa ukoliko želite da ostanete relevantni na ovom polju, nedopustivo je da sebi dozvolite stagnaciju u bilo kom aspektu. Stoga smo se mi kao tim trudili da u što kraćem vremenskom roku razvijemo i implementiramo što više novih funkcionalnosti u okviru iPi-ja, što je često značilo znatno veći read i write load na klaster. Iako je zauzeće prostora na HDFS-u blizu 50%, broj read i write zahteva upućenih klasteru se strmoglavo povećao i brzo je postalo očigledno da inicijalna konfiguracija sa kojom smo započeli celu iPi priču više nije odgovarala, što se veoma loše odrazilo na performanse sistema. Iako sam u prethodnom odeljku imala samo reči hvale o HBase-u i njegovim performansama, u našem slučaju je epicentar svih problema upravo bio HBase. HBase je baziran na JAVA-i, što znači da automatski menadžment memorije, odnosno JAVA Garbage Collection, ima krucijalan uticaj na njegove performanse.

Podaci koje koristimo u okviru Big Data okruženja su u HBase-u organizovani u obliku jedne velike tabele distribuirane na datanode-ovima u okviru klastera. Ova tabela izdeljena je na delove koji se nazivaju regionima i na svakom datanode-u nalazi se proces HBase RegionServer koji je zadužen za pristupanje regionima u okviru svog datanode-a prilikom read i write operacija. Kada se broj read i write zahteva upućenih RegionServer-u strmoglavo poveća, a inicijalna konfiguracija ne može da podrži ovaj load, dolazi do takozvanih „stop the world“ pauza. Tokom ovih pauza, RegionServer sve svoje resurse koristi za čišćenje heap-a što onemogućava pravilan rad sistema. U našem slučaju, dešavalo se da ove pauze traju po nekoliko minuta u najkritičnijim situacijama, što znači da u tih nekoliko minuta RegionServer nije mogao da izvrši read ili write zahtev. Ovakve situacije imale su direktan uticaj na web aplikaciju, što je veliki problem kako za nas, tako i za korisnika. Web aplikacija je radila vrlo usporeno, a dešavalo se da su podaci prikazivani na izveštajima nerealni i besmisleni. Jasno, neophodno je bilo brzo pronaći efikasno i dugotrajno rešenje.

Za rešenje ovakvih situacija postoje tri opcije: smanjenje load-a na sistem, dodavanje novih datanode-ova u klaster ili HBase tjuning. U našem slučaju, prva opcija ne predstavlja rešenje jer naš dugoročni plan ne obuhvata bilo kakav downgrade iPi-ja. Druga opcija, koja zapravo predstavlja i najjednostavnije rešenje, nije bila moguća u tako kratkom vremenskom roku. Stoga smo bili prinuđeni na promenu konfiguracije HBase-a, odnosno HBase tjuning.

Kako smo to uradili?

Prvi korak u rešavanju našeg problema bilo je detaljno razumevanje procesa koji dovodi do „stop the world“ pauza koje stopiraju aplikaciju.

Naša inicijalna konfiguracija podrazumevala je Garbage First Collector, što je sasvim razumljivo na veličinu heap-a od 8GB. Ovaj Garbage Collector predstavlja jedan od najefikasnijih i najperformantnijih Garbage Collector-a razvijenih za multiprocesorske mašine sa veličinama heap-a iznad 6GB. Stoga nismo želeli da menjamo ovaj parametar, ali smo imali u vidu mogućnost povećanja heap-a.

Takođe, naša inicijalna konfiguracija podrazumevala je željenu GC pauzu od 200ms. Prateći stanje na graficima za trajanje Garbage Collection-a, primetili smo da se ova situacija dešava u samo 2% vremena. Trajanje Garbage Collection-a je imalo velike oscilacije, od 150ms do 80s, a problematični Garbage Collection se izvršavao na svakih sat vremena. Grafik koji se tiče zauzeća heap-a prikazivao je konstatnu vrednost zauzeća od 6GB.

Zatim smo pogledali i dve najznačajnije in-memory komponente RegionServera-a, MemStore i BlockCache. Najprostije, rečeno MemStore prestavlja write cache koji ima ulogu storage-a za nove podatke koji još uvek nisu upisani na disk. Kada se u MemStore-u nakupi dovoljno podataka (u našem slučaju je to 128MB), podaci se spajaju u HFile-ove i upisuju na disk. Slično, BlockCache predstavlja read cache. U našem slučaju, obe ove komponente bile su konfigurisane tako da zauzimaju maksimalno po 40% heap-a.

Jedna od najznačajnih informacija koja nas je usmerila ka optimalnom rešenju problema jeste bila vreme tokom kojeg je trajanje Garbage Collection-a bilo najduže. Ovo vreme podudaralo se sa upisom najveće količine podataka na klaster. Takođe, u logovima za HBase Region Server su se u to vreme mogle videti informacije o tome kako su fajlovi veličine čak 5MB bili upisani na disk, što se nije poklopalo sa našom željenom vrednošću od 128MB. Zbog toga smo dolazili u situacije zauzeća celokupnog MemStore-a. U takvim situacijama, HBase vrši nasilno upisivanje fajlova na disk (flush-ing) i blokira svaki update. U prilog ovoj tvrdnji ide i činjenica da su se na klasteru tokom najdužeg trajanja Garbage Collection-a javljala Flush Queue Size upozorenja.

Kako količina MemStore-a očigledno nije bila dovoljna za write load na naš klaster,odlučili smo da povećamo heap na 12GB. 50% toga podredili smo MemStore-u, a  30% BlockCache-u. Na taj način veličina BlockCache-a koji je i ranije imao dovoljno prostora nije značajno promenjena, a veličina MemStore je imala značajno proširenje. Nažalost, ne postoji univerzalna formula koja govori koliko heap-a je potrebno dodeliti kom sistemu. Naš izbor veličine heap-a je rezultat mnogobrojnih testiranja, ali sveopšta preporuka jeste da veličina heap-a ne bi trebalo da prelazi 16GB. Naravno, mora se imati u vidu i kapacitet mašine.

Pored ovih parametara, bilo je potrebno uvesti još neke kako bi se problem u potpunosti otklonio. Željena GC pauza je ostala na istoj vrednosti od 200ms, pri čemu su prema Oracle preporuci uvedeni još neki parametri koji pomažu dostizanju ove vrednosti. Sigurna preporuka je parametar -XX:+ParallelRefProcEnabled.  Primećeno je da ovaj parametar smanjuje GC pauze za čak 30%, što je bio I naš slučaj. Finalno, parametar –XX:InitiatingHeapOccupancyPercent govori koliko treba biti minimalno zauzeće heap-a pri kom treba započeti marking fazu. Ovaj parametar umnogome može pomoći performansama, ali ukoliko je pogrešno postavljen, može imati poguban uticaj po performanse, bez obzira na veličinu heap-a. Default vrednost je 45%, iako postoji neformalno pravilo da ova vrednost treba biti veća od veličine MemStore-a i BlockCache-a zajedno. Kako nismo želeli da rizikujemo sa značajnim okruženjem, testiranjem smo došli do zaključka da je u našem slučaju 70% ipak optimalna vrednost.

Šta smo postigli?

Nakon izmene konfiguracije HBase-a, nismo imali problema sa performansama sistema. Web aplikacija je nastavila da radi optimalno, a prethodna upozorenja se ne javljaju. Prosečna GC pauza je 215ms, sa standardnom devijacijom od 10ms, što je solidan rezultat.

Takođe, svesni smo da postoji znatno veći izbor parametara, ali tokom pronalaženja optimalne konfiguracije nosili smo se mišlju da ona bude što je jednostavnija moguća, zbog rizika koju svaka komplikovana konfiguracija sa sobom nosi.

HBase Garbage Collection je krucijalan, ali i vrlo nepredvidiv faktor koji se tiče optimalnog rada Big Data okruženja. Ukoliko JVM parametri nisu dobro podešeni može doći do katastrofalnih posledica po ceo sistem. U našem slučaju, katastrofa je izbegnuta i pronađeno je optimalno rešenje. Nažalost, ne postoji univerzalna formula kojom se dolazi do najboljeg rešenja jer svaki sistem ima drugačije zahteve i namene, ali postoje smernice koje vam značajno mogu olakšati put. Cilj ovog posta je da kroz naše iskustvo ukažemo na neke faktore koji mogu doprineti rešavanju ovakvih problema i nadamo se da smo u tome uspeli.

 

 

Share

Prijavi se da prvi dobijaš nove blogove i vesti.

Ostavite odgovor

Aleksandra Mandić

Big Data Software Engineer @ Ibis Instruments
mm

Big Data entuzijasta. Svakodnevno se bori sa izazovima koje pred nju postavljaju HDFS, HBase, Hive, Impala, Oozie I ostali članovi Hadoop zoološkog vrta. U tome joj najviše pomažu Python, JAVA I R.
Slobodno vreme koristi za putovanja I gimnastiku.

Prijavi se da prvi dobijaš nove blogove i vesti.

Kategorije