Kërkimi me shpejtësi 1 TB/s

TL;DR: Katër vjet më parë, unë u largova nga Google me idenë e një mjeti të ri për monitorimin e serverëve. Ideja ishte të bashkohen në një shërbim funksionet zakonisht të izoluar të mbledhjes dhe analizës së log-eve, mbledhjes së metricave, alarmet dhe panelit të monitorimit. Një nga parimet ishte që shërbimi duhet të jetë vërtet i shpejtë, duke i ofruar DevOps një përvojë të lehtë, interaktive dhe këndshme. Kjo kërkon përpunimin e grupeve të të dhënave që arrijnë disa gigabajt në një fraction sekonde, pa e tejkaluar buxhetin. Mjetet ekzistuese për punën me log-e shpesh janë të ngadalta dhe të pashkathtë, prandaj përballëm me një sfidë të bukur: të dizajnojmë me mençuri një mjet që t'u japë përdoruesve një përvoje të re në punë.

Në këtë artikull përshkruajmë se si ne në Scalyr e zgjidhëm këtë problem duke aplikuar metoda të shkollës së vjetër, një qasje të forcës bruto, duke eliminuar shtresat e panevojshme dhe duke shmangur struktura të komplikuara të të dhënave. Këto mësime mund t'i aplikoni në detyrat tuaja inxhinierike.

Forca e shkollës së vjetër

Analiza e log-eve zakonisht fillon me kërkimin: të gjejmë të gjitha mesazhet që përkojnë me ndonjë model. Në Scalyr, kjo përfshin dhjetëra ose qindra gigabajt log-e nga shumë serverë. Qasjet moderne zakonisht parashikojnë ndërtimin e një strukture të ndërlikuar të të dhënave, të optimizuar për kërkimin. Patjetër që kam parë diçka të tillë në Google, ku ata janë të mirë në këto gjëra. Por ne u ndalëm në një qasje shumë më të thjeshtë: skanimi linear i log-eve. Dhe kjo funksionoi – ne ofrojmë një ndërfaqe me kërkimin që është shumë më e shpejtë se ajo e konkurentëve (shihni animacionin në fund).

Zbulimi kyç ishte se procesorët modernë janë vërtet shumë të shpejtë në operacione të krijuara thjesht. Kjo lehtë mund të lihet pas dore në sisteme komplekse, me shumë shtresa, që varen nga shpejtësia I/O dhe operacioneve rrjetore, të cilat janë shumë të zakonshme sot. Kështu, ne zhvilluam një dizajn që minimizon numrin e shtresave dhe mbeturinave të panevojshme. Me disa procesorë dhe serverë në paralel, shpejtësia e kërkimit arrin deri në 1 TB në sekondë.

Pikat kyçe nga ky artikull:

  • Kërkimi i thjeshtë është një qasje mjaft e aplikueshme për të zgjidhur probleme reale dhe në shkallë.
  • Forca bruto është një teknikë dizajnimi, jo një justifikim për të shmangur punën. Si çdo teknikë, ajo është më e përshtatshme për disa probleme sesa për të tjera, dhe mund të zbatohen në mënyrë të keqe ose të mirë.
  • Forca bruto është sidomos e frytshme për arritjen në fazën e performancës.
  • Përdorimi efektiv i forcës bruto kërkon optimizimin e kodit dhe alokimin e duhur të burimeve në kohën e duhur. Ajo është e përshtatshme nëse serverët tuaj janë nën një ngarkesë të madhe, e cila nuk është e lidhur me përdoruesit, ndërsa operacionet e përdoruesve mbeten prioritet.
  • Performanca varet nga dizajni i tërë sistemit, jo vetëm nga algoritmi i ciklit të brendshëm.

(Ky artikull përshkruan kërkimin e të dhënave në memorje. Në shumicën e rasteve, kur një përdorues bën kërkimin në log-e, serverët Scalyr tashmë i kanë ruajtur ato nëCache. Në artikullin e ardhshëm do të diskutojmë kërkimin në log-e që nuk janë të ruajtura në Cache. Të njëjtat parime aplikohen: kod efektiv, metoda e forcës bruto me burime të mëdha kompjuterike).

Metoda e forcës bruto

Tradicionalisht, kërkimi në një grup të madh të dhënash bëhet përmes një indeksi të fjalëve kyçe. Në lidhje me log-et e serverëve, kjo do të thotë të kërkosh çdo fjalë unike në log. Për çdo fjalë, duhet të krijohet një listë e të gjitha përfshirjeve. Kjo e bën të lehtë të gjesh të gjitha mesazhet me atë fjalë, për shembull, ‘error’, ‘firefox’ ose ‘transaction_16851951’ – thjesht shikoni në indeks.

Kam përdorur një qasje të tillë në Google, dhe ajo ka funksionuar mirë. Por në Scalyr ne kërkojmë në log-e byte për byte.

Pse? Nga një pikëpamje algoritmike abstrakte, indekset e fjalëve kyçe janë shumë më efikase se kërkimi i thjeshtë. Sidoqoftë, ne nuk shesim algoritma, ne shesim performancë. Dhe performanca nuk lidhet vetëm me algoritmet, por edhe me inxhinierinë sistemore. Duhet të marrim parasysh gjithçka: volumin e të dhënave, llojin e kërkimit, pajisjet në dispozicion dhe kontekstin programues. Ne vendosëm se për problemin tonë specifik, një opsion si ‘grep’ është më i përshtatshëm se indeksi.

Indeksat janë të shkëlqyer, por ata kanë kufizime. Të gjesh një fjalë është e lehtë. Por kërkimi i mesazheve me disa fjalë, të tilla si ‘googlebot’ dhe ‘404’ është shumë më i komplikuar. Kërkimi i një fjalie si ‘uncaught exception’ kërkon një indeks më të ngarkuar, i cili regjistron jo vetëm të gjitha mesazhet me atë fjalë, por edhe vendndodhjen specifike të fjalës.

Vështirësia e vërtetë lind kur nuk po kërkoni fjalë. Supozoni se dëshironi të shihni sa trafik vjen nga bota. Mendimi i parë është të kërkoni në log për fjalën 'bot'. Kështu do të gjeni disa botë: Googlebot, Bingbot dhe shumë të tjerë. Por këtu 'bot' nuk është një fjalë, por një pjesë e saj. Nëse kërkoni 'bot' në indeks, nuk do të gjeni mesazhe që përmbajnë fjalën 'Googlebot'. Nëse kontrolloni çdo fjalë në indeks dhe më pas skanoni indeksin për fjalët e gjetura, kërkimi do të ngadalësohet shumë. Si rezultat, disa programe për trajtimin e log-eve nuk lejojnë kërkimin sipas pjesëve të fjalëve ose (në rastin më të mirë) lejojnë përdorimin e një sintaksë speciale me performancë më të ulët. Ne dëshirojmë të shmangim këtë.

Një problem tjetër është pikësimi. Dëshironi të gjeni të gjitha kërkesat nga 50.168.29.7? Что насчёт отладки логов, содержащих [error]? Индексы обычно пропускают пунктуацию.

Së fundi, inxhinierët preferojnë mjete të fuqishme, dhe ndonjëherë, problemi zgjidhet vetëm me shprehje të rregullta. Indeksi i fjalëve kyçe nuk është shumë i përshtatshëm për këtë.

Për më tepër, indekset janë të komplikuara.. Çdo mesazh duhet shtuar në disa lista të fjalëve kyçe. Këto lista duhet të mbahen vazhdimisht në një format të përshtatshëm për kërkim. Kërkesat me fraza, fragmente fjalësh ose shprehje të rregullta duhet të konvertohen në operacione me disa lista, dhe rezultatet duhet të skanohen e të bashkohen për të arritur një grup rezultatesh. Në kontekstin e një shërbimi shumëpërdorues të shkallës së gjerë, një kompleksitet i tillë krijon probleme në performancë që nuk duken gjatë analizimit të algoritmeve.

Indeksat e fjalëve kyçe gjithashtu zënë shumë hapësirë, dhe ruajtja është një artikull kryesor kostoje në sistemin e menaxhimit të log-eve.

Nga ana tjetër, për çdo kërkim mund të shpenzohet shumë fuqi llogaritëse. Përdoruesit tanë e vlerësojnë kërkimin me shpejtësi të lartë për kërkesa unike, por këto kërkesa bëhen relativisht rrallë. Për kërkesat tipike, për shembull, për panelin e monitorimit, ne aplikojmë teknika të veçanta (do t'i përshkruajmë në artikullin e ardhshëm). Kërkesa të tjera janë mjaft të rralla, ndaj zakonisht nuk është e nevojshme të trajtojmë më shumë se një shpesh. Por kjo nuk do të thotë se serverat tanë nuk janë të angazhuar: ata janë të ngarkuar me punën e pranuar, analizuar dhe kompresuar të dhënat e reja, duke vlerësuar njoftimet, duke kompresuar të dhënat e vjetra dhe kështu me radhë. Kështu, ne kemi një rezervë të konsiderueshme procesorësh që mund të angazhohen për të përmbushur kërkesat.

Forca e egër funksionon nëse keni një problem të egër (dhe shumë forcë)

Forca e egër funksionon më mirë në detyra të thjeshta me cikle të brendshme të vogla. Shpesh mund të optimizoni ciklin e brendshëm për të funksionuar me shpejtësi shumë të lartë. Nëse kodi është kompleks, është shumë më e vështirë ta optimizoni.

Fillimisht, në kodin tonë për kërkimin, kishte një cikël të brendshëm mjaft të madh. Ne ruajmë mesazhet në faqe prej 4K; çdo faqe përmban disa mesazhe (në UTF-8) dhe metadatat për secilin mesazh. Metadat janë një strukturë ku janë koduar gjatësia e vlerës, ID e brendshme e mesazhit dhe fusha të tjera. Cikli i kërkimit dukej si më poshtë:

Kërkimi me shpejtësi 1 TB/s

Ky është një version i thjeshtuar në krahasim me kodin real. Por edhe këtu, disa vendosje objektesh, kopje të të dhënave dhe thirrje funksionesh janë të dukshme. JVM optimizon mjaft mirë thirrjet e funksioneve dhe alokimin e objekteve efemerike, kështu që ky kod funksionoi më mirë se sa e merituam. Gjatë testimit, klientët e përdorën këtë mjaft me sukses. Por, në fund të fundit, ne kaluam në një nivel të ri.

(Mund të pyesni pse ne ruajmë mesazhet në një format të tillë me faqe prej 4K, tekst dhe metadatat, dhe jo duke punuar drejtpërdrejt me log-et. Ka shumë arsye që përfundojnë në faktin se brenda motorit Scalyr ngjan më shumë si një bazë të shpërndarë të dhënash sesa si një sistem skedari. Kërkimi i tekstit shpesh kombinohet me filtra të stilit DB në fusha pas analizimit të log-eve. Ne mund të kërkojmë njëkohësisht në mijëra log-eve, dhe skedarët e thjeshtë të tekstit nuk janë të përshtatshëm për menaxhimin tonë të të dhënave transaksionale, të replikueshëm dhe të shpërndarë).

Fillimisht dukej se një kod i tillë nuk ishte shumë i përshtatshëm për optimizim në metodën e forcës së egër. "Puna e vërtetë" në String.indexOf() as që nuk dominonte në profilin e CPU. Që do të thotë se optimizimi i vetëm i këtij metodi nuk do të kishte sjellë një efekt domethënës.

Kështu ndodhi që ne ruajmë metadatat në fillim të çdo faqeje, dhe teksti i të gjitha mesazheve në UTF-8 është i paketuar në skajin tjetër. Duke e shfrytëzuar këtë, ne e shkruam ciklin për të kërkuar menjëherë në të gjithë faqen:

Kërkimi me shpejtësi 1 TB/s

Versioni i tillë funksionon drejtpërdrejt mbi pamjen raw byte[] dhe bën kërkimin e të gjitha mesazheve menjëherë në të gjitha faqet 4K.

Kjo është shumë më e lehtë për t'u optimizuar për metodën e forcës bruto. Cikli i brendshëm i kërkimit thirret njëkohësisht për të gjithë faqen 4K, jo veç e veç për çdo mesazh. Nuk ka asnjë kopjim të të dhënave, as një veçim të objekteve. Dhe operacionet më të komplikuara me metadatat thirren vetëm kur ka një rezultat pozitiv, jo për çdo mesazh. Kështu, ne përjashtojmë një sasi të madhe të ngarkesës, dhe ngarkesa e mbetur përqendrohet në një cikël të vogël kërkimi të brendshëm, i cili është i përshtatshëm për optimizim të mëtejshëm.

Algoritmi ynë real i kërkimit bazohet në ide të shkëlqyera të Leonid Volnickit. Ai është i ngjashëm me algoritmin e Boyerit – Moore me një kalim të përafërt të gjatë të vargut kërkues në çdo hap. Dallimi kryesor është se ai verifikon dy byte në një kohë, për të minimizuar ndeshjet false.

Implementimi ynë kërkon krijimin e një tabele kërkimi 64K për çdo kërkesë, por kjo është një gjë e vogël krahas gigabaytëve të të dhënave në të cilat ne kërkojmë. Cikli i brendshëm përpunon disa gigabayt në sekondë në një bërthamë. Në praktikë, performanca e qëndrueshme arrin përafërsisht 1.25 GB në sekondë për secilën bërthamë, dhe ka potencial për përmirësimin. Disa ngarkesa jashtë ciklit të brendshëm mund të eliminohen, dhe ne planifikojmë të eksperimentojmë me ciklin e brendshëm në C në vend të Java.

Të aplikojmë forcën

Kemi diskutuar se kërkimi në loge mund të implementohet "brutal", por sa "forcë" kemi në dispozicion? Mjaft.

1 bërthamë: kur përdoret siç duhet, një bërthamë e procesorit modern është mjaft e fuqishme vetë.

8 bërthama: aktualisht ne po punojmë në serverët Amazon hi1.4xlarge dhe i2.4xlarge SSD, secili prej të cilëve ka 8 bërthama (16 thjesht). Siç u përmend më sipër, zakonisht këto bërthama janë të zëna me operacione të prapavijës. Kur një përdorues bën një kërkim, operacionet e prapavijës pezullohen, duke liruar të gjithë 8 bërthamat për kërkimin. Kërkimi zakonisht përfundon brenda një çastit, pas së cilës puna e prapavijës vazhdon (programi menaxhues garanton që fluksi i kërkimeve nuk do të pengojë punën e rëndësishme të prapavijës).

16 bërthama: për besueshmëri, ne organizojmë serverat në grupe master/slave. Çdo master ka në varësi një server SSD dhe një EBS. Nëse serveri kryesor bie, serveri SSD menjëherë zëvendëson atë. Pothuajse gjithnjë master dhe slave punojnë normalisht, kështu që çdo bllok të dhënash është i disponueshëm për kërkimin në dy servera të ndryshëm (serveri i varur EBS ka një procesor të dobët, kështu që nuk e marrim parasysh). Ndajmë detyrën në mesin e tyre, kështu që ne kemi gjithsej 16 bërthama të disponueshme.

Shumë bërthama: në të ardhmen e afërt, ne do të shpërndajmë të dhënat midis serverave në një mënyrë që të gjithë të përfshihen në përpunimin e çdo kërkese jo triviale. Çdo bërthamë do të funksionojë. [Shënim: ne kemi zbatuar një plan dhe rritur shpejtësinë e kërkimit në 1 TB/s, shihni shënimin në fund të artikullit].

Thjeshtësia siguron besueshmëri

Një tjetër avantazh i metodës së forcës bruto është performanca mjaft e qëndrueshme. Në përgjithësi, kërkimi nuk është shumë i ndjeshëm ndaj detajeve të detyrës dhe të dhënave (mendoj se për këtë arsye quhet „brutale“).

Indeksi i fjalëve kyçe ndonjëherë jep rezultate jashtëzakonisht të shpejta, por në raste të tjera jo. Le të supozojmë se keni 50 GB logesh, ku termi ‘customer_5987235982’ shfaqet saktësisht tre herë. Kërkimi për këtë term merr menjëherë nga indeksi tre vende dhe përfundon menjëherë. Por kërkimi kompleks me karaktere zëvendësuese mund të skanojë mijëra fjalë kyçe dhe të zgjasë shumë.

Nga ana tjetër, kërkimi me metodën e forcës bruto për çdo kërkesë përfundon me një shpejtësi më shumë ose më pak të njëjtë. Kërkimi i fjalëve të gjata është më i mirë, por edhe kërkimi i një simboli ndodh mjaft shpejt.

Thjeshtësia e metodës së forcës bruto do të thotë se performanca e saj është afërsisht në maksimumin teorik. Këtu ka më pak mundësi për ngarkesa të papritura në disqe, konflikte gjatë bllokimeve, ndjekjes së treguesve dhe mijëra arsyeve të tjera për dështime. Unë sapo e shikoja kërkesat e bërë nga përdoruesit Scalyr javën e kaluar në serverin tonë më të ngarkuar. Kishim 14,000 kërkesa. Saktësisht tetë prej tyre zgjatën më shumë se një sekondë; 99% u përfunduan brenda 111 milisekondave (nëse nuk keni përdorur mjete analize logesh, besoni: është shpejt).

Performanca e qëndrueshme, e besueshme është e rëndësishme për përvojën e përdoruesit. Nëse ai ngadalësohet herë pas here, përdoruesit do ta perceptojnë si të paqëndrueshëm dhe do të hezitojnë ta përdorin.

Kërkimi në loge në veprim

Këtu është një animacion i vogël që tregon kërkimin Scalyr në veprim. Ne kemi një llogari demo, ku importojmë çdo ngjarje në çdo depo publike Github. Në këtë demonstrim po shqyrtoj të dhënat për një javë: rreth 600 MB logj të papërpunuara.

Videoja është regjistruar në kohë reale, pa ndihmë të veçantë, në desktopin tim (rreth 5000 kilometra nga serveri). Performanca që do të shihni, në masë të madhe, është për shkak të optimizimit të aplikacionit web, si dhe backend-it të shpejtë dhe të besueshëm. Çdo herë që ka një pauzë pa indikatorin 'loading', unë bëj pauzë, në mënyrë që të keni kohë të lexoni se çfarë po përgatitem të klikoj.

Kërkimi me shpejtësi 1 TB/s

Në përfundim

Kur punoni me të dhëna të mëdha, është e rëndësishme të zgjidhni një algoritëm të mirë, por 'i mirë' nuk do të thotë 'i komplikuar'. Mendoni për mënyrën se si kodi juaj do të funksionojë në praktikë. Nga analiza teorike e algoritmeve, disa faktorë mund të përjashtohen që kanë rëndësi në botën reale. Algoritmet më të thjeshta janë më të lehta për t'u optimizuar dhe janë më stabile në situata ekstreme.

Mendoni gjithashtu për kontekstin në të cilin do të ekzekutohet kodi. Në rastin tonë, na duhen serverë mjaft të fuqishëm për të menaxhuar detyrat në sfond. Përdoruesit relativisht rrallë nisin kërkimin, prandaj ne mund të huazojmë një grup të tërë serverësh për një periudhë të shkurtër, të nevojshme për të kryer çdo kërkim.

Me metodën e kërkimit të fuqishëm, kemi realizuar një kërkim të shpejtë, të besueshëm dhe fleksibël në grupin e logjeve. Shpresojmë që këto ide të jenë të dobishme për projektet tuaja.

Redaktimi: titulli dhe teksti ndryshuan nga 'Kërkimi me shpejtësi 20 GB në sekondë' në 'Kërkimi me shpejtësi 1 TB në sekondë', për të reflektuar rritjen e performancës vitet e fundit. Ky rritje shpejtësie lidhet kryesisht me ndryshimin në llojin dhe numrin e serverëve EC2 që po ngrisim sot për të shërbyer një baze klientësh në rritje. Së shpejti priten ndryshime që do të sigurojnë një rritje tjetër drastike të efikasitetit të punës, dhe po presim me padurim mundësinë për ta njoftuar atë.

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster