Apache Druid: realaus laiko analizė

Kas yra Apache Druid ir kodėl jis svarbus

Kai kalbame apie duomenų analizę realiu laiku, dažnai susiduriame su problema – tradicinės duomenų bazės tiesiog nesupranta, ką reiškia „greitis”. Galite turėti galingiausią PostgreSQL ar MySQL serverį, bet kai reikia analizuoti milijardus įvykių per sekundę ir atsakymus gauti per milisekundes, standartinės reliacinės duomenų bazės pradeda prakaitavoti.

Čia į sceną įžengia Apache Druid – atvirojo kodo duomenų bazė, specialiai sukurta realaus laiko analitikai. Šis projektas gimė LinkedIn kompanijoje 2011 metais, kai inžinieriai susidūrė su problema: kaip efektyviai analizuoti milijardus įvykių, kurie plūsta iš jų platformos? Tradicinės sistemos tiesiog negalėjo susidoroti su tokiu apkrovimu.

Druid nėra dar viena NoSQL duomenų bazė, bandanti būti visur ir visur. Tai labai specializuotas įrankis, sukurtas vienam tikslui – analizuoti laiko eilutes (time-series) ir įvykių duomenis žaibišku greičiu. Jei jūsų verslas reikalauja analizuoti vartotojų elgesį realiuoju laiku, stebėti tūkstančius metrikų ar kurti interaktyvius dashboard’us su milijardais įrašų – Druid turėtų būti jūsų radaruose.

Architektūra, kuri veikia kaip gerai suderintas orkestras

Druid architektūra iš pirmo žvilgsnio gali atrodyti sudėtinga, bet tai yra jos stiprybė. Sistema susideda iš kelių specializuotų komponentų, kur kiekvienas atlieka savo darbą ir daro jį puikiai.

Historical nodes – tai Druid atmintis. Šie mazgai saugo visus istorinius duomenis segmentų pavidalu. Segmentai yra nepriklausomi duomenų blokai, paprastai apimantys tam tikrą laiko periodą. Kai užklausite duomenų už praėjusį mėnesį, būtent historical nodes grąžins atsakymą. Šie mazgai gali būti horizontaliai plečiami – tiesiog pridėkite daugiau serverių, ir sistema automatiškai paskirstys duomenis.

Real-time nodes (arba Indexing Service) – čia vyksta magija su šviežiais duomenimis. Šie komponentai priima naujus duomenis iš Kafka, Kinesis ar kitų srautų, indeksuoja juos ir daro prieinamus užklausoms beveik akimirksniu. Tai tas pats komponentas, kuris leidžia matyti, kas vyksta jūsų sistemoje dabar, o ne prieš valandą.

Broker nodes – tai Druid smegenys. Kai siunčiate užklausą, ji patenka į broker’į, kuris supranta, kurie segmentai turi reikalingus duomenis, paskirsto užklausą tarp atitinkamų historical ir real-time mazgų, surenka rezultatus ir grąžina jums. Broker’iai taip pat naudoja pažangų kešavimą, todėl dažnai kartojamos užklausos grąžinamos beveik akimirksniu.

Coordinator nodes – sistema, kuri valdo duomenų paskirstymą klasteryje. Jie sprendžia, kurie segmentai turėtų būti įkelti į historical nodes, tvarko replikaciją ir užtikrina, kad duomenys būtų optimaliai paskirstyti.

Papildomai yra Overlord (valdo indeksavimo užduotis) ir Router (nukreipia užklausas į tinkamus broker’ius). Taip, tai daug komponentų, bet kiekvienas iš jų gali būti plečiamas nepriklausomai, o tai reiškia, kad galite optimizuoti sistemą pagal savo specifinius poreikius.

Duomenų struktūra ir indeksavimas – kodėl Druid toks greitas

Druid greitis nėra atsitiktinumas. Tai rezultatas kelių protingų sprendimų, kaip duomenys saugomi ir indeksuojami.

Pirmiausia, Druid naudoja stulpelinį saugojimą (columnar storage). Vietoj to, kad saugotų duomenis eilutėmis, kaip tradicinės duomenų bazės, Druid saugo kiekvieną stulpelį atskirai. Kodėl tai svarbu? Kai analizuojate duomenis, dažniausiai jums reikia tik kelių stulpelių iš dešimčių ar šimtų. Su stulpeliniu saugojimu Druid skaito tik tuos duomenis, kurių iš tikrųjų reikia.

Antra, Druid agresyviai naudoja suspaudimą. Kadangi kiekvienas stulpelis saugomas atskirai, galima pritaikyti specifines suspaudimo technikas, kurios geriausiai tinka konkrečiam duomenų tipui. Dimensijų stulpeliai dažnai suspaudžiami naudojant dictionary encoding, o metrikų stulpeliai – naudojant LZ4 ar kitą greitą algoritmą.

Trečia, Druid turi bitmap indeksus kiekvienam dimensijos stulpeliui. Tai leidžia neįtikėtinai greitai filtruoti duomenis. Pavyzdžiui, jei norite rasti visus įvykius iš Lietuvos, Druid gali tai padaryti naudodamas bitmap operacijas, kurios yra ekstremaliai greitos.

Štai paprastas pavyzdys, kaip galėtų atrodyti duomenų schema:

„`json
{
„dataSource”: „user_events”,
„timestampColumn”: „timestamp”,
„dimensions”: [
„country”,
„device_type”,
„user_id”,
„event_type”
],
„metrics”: [
{„name”: „count”, „type”: „count”},
{„name”: „session_duration”, „type”: „doubleSum”}
],
„granularity”: „minute”
}
„`

Ši schema apibrėžia, kad saugosime vartotojų įvykius su keliomis dimensijomis ir metrikomis. Druid automatiškai sukurs indeksus visoms dimensijoms ir optimizuos metrikų saugojimą.

Realaus laiko duomenų įkėlimas ir integracijos

Vienas iš didžiausių Druid pranašumų yra gebėjimas dirbti su duomenų srautais realiu laiku. Sistema puikiai integruojasi su Apache Kafka, Amazon Kinesis, Apache Pulsar ir kitais pranešimų brokeriais.

Įsivaizduokite, kad turite e-komercijos platformą, kuri generuoja tūkstančius įvykių per sekundę – puslapio peržiūros, pridėjimai į krepšelį, pirkimai. Norite, kad jūsų analitikai galėtų matyti, kas vyksta dabar, o ne tik vakar ar praėjusią savaitę.

Su Druid galite sukonfigūruoti streaming ingestion iš Kafka per kelias minutes:

„`json
{
„type”: „kafka”,
„spec”: {
„dataSchema”: {
„dataSource”: „ecommerce_events”,
„timestampSpec”: {
„column”: „timestamp”,
„format”: „iso”
},
„dimensionsSpec”: {
„dimensions”: [
„product_id”,
„user_id”,
„category”,
„country”
]
},
„metricsSpec”: [
{„name”: „count”, „type”: „count”},
{„name”: „revenue”, „type”: „doubleSum”, „fieldName”: „price”}
],
„granularitySpec”: {
„segmentGranularity”: „hour”,
„queryGranularity”: „minute”
}
},
„ioConfig”: {
„topic”: „events”,
„consumerProperties”: {
„bootstrap.servers”: „kafka:9092”
}
}
}
}
„`

Ši konfigūracija pasakys Druid, kad reikia klausytis Kafka topic’o, indeksuoti duomenis pagal nurodytą schemą ir daryti juos prieinamus užklausoms beveik akimirksniu. Duomenys bus saugomi valandiniais segmentais, bet užklausos galės agregavus duomenis iki minutės tikslumo.

Jei naudojate batch processing, Druid taip pat puikiai dirba su Hadoop, Spark ar paprastais failais S3 bucket’e. Galite įkelti istorinius duomenis iš Parquet, ORC ar CSV failų.

Užklausų kalbos ir API – kaip bendrauti su Druid

Druid palaiko kelis būdus užklausoms siųsti. Pagrindinis būdas yra native JSON užklausos, kurios suteikia pilną kontrolę ir maksimalų našumą. Štai pavyzdys, kaip gauti top 10 produktų pagal pardavimus per paskutinę valandą:

„`json
{
„queryType”: „topN”,
„dataSource”: „ecommerce_events”,
„intervals”: [„2024-01-15T10:00:00/2024-01-15T11:00:00”],
„granularity”: „all”,
„dimension”: „product_id”,
„metric”: „revenue”,
„threshold”: 10,
„aggregations”: [
{„type”: „doubleSum”, „name”: „revenue”, „fieldName”: „price”},
{„type”: „count”, „name”: „sales_count”}
]
}
„`

Bet jei JSON užklausos atrodo per sudėtingos, Druid palaiko SQL. Taip, paprastą, senąjį gerąjį SQL:

„`sql
SELECT
product_id,
SUM(price) as revenue,
COUNT(*) as sales_count
FROM ecommerce_events
WHERE __time >= CURRENT_TIMESTAMP – INTERVAL ‘1’ HOUR
GROUP BY product_id
ORDER BY revenue DESC
LIMIT 10
„`

SQL užklausos yra konvertuojamos į natyvias Druid užklausas, todėl našumas išlieka puikus. Tai labai patogu, nes daugelis analitikų ir duomenų mokslininkų jau žino SQL ir gali pradėti dirbti su Druid be didelės mokymosi kreivės.

Druid taip pat turi REST API, todėl galite lengvai integruoti jį į savo aplikacijas. Python, Java, JavaScript – bet kuri kalba, kuri gali siųsti HTTP užklausas, gali dirbti su Druid.

Našumo optimizavimas ir geriausi praktikos

Net ir su tokia galinga sistema kaip Druid, yra būdų, kaip išspausti dar daugiau našumo. Štai keletas praktinių patarimų, kuriuos išmokau dirbdamas su Druid produkcijoje.

Pasirinkite tinkamą segmentų granuliarumą. Jei jūsų duomenų srautas yra didelis, valandiniai segmentai yra geras pasirinkimas. Jei duomenų mažiau, dieniniai segmentai gali būti efektyvesni. Per maži segmentai sukuria per daug metadata, per dideli – lėtina užklausas, nes reikia skaityti daugiau nereikalingų duomenų.

Naudokite roll-up. Tai Druid funkcija, kuri automatiškai agregavus duomenis įkėlimo metu. Jei jums nereikia individualių įvykių, o tik agregavus metrikų, roll-up gali sumažinti duomenų kiekį 10-100 kartų. Pavyzdžiui, vietoj saugojimo kiekvieno puslapio peržiūros atskirai, galite saugoti puslapio peržiūrų skaičių per minutę.

Optimizuokite dimensijų kardinalumą. Dimensijos su labai dideliu kardinalumu (pvz., user_id su milijonais unikalių reikšmių) gali sulėtinti užklausas. Jei jums nereikia grupuoti pagal tokias dimensijas, geriau jų neįtraukti arba naudoti kaip metrikos dalį.

Konfigūruokite kešavimą. Broker nodes turi kelių lygių kešavimą. Tinkamas kešo dydžio nustatymas gali dramatiškai pagerinti dažnai kartojamų užklausų našumą. Rekomenduoju skirti bent 50% broker’io RAM kešui.

Stebėkite cluster’io sveikatą. Druid eksponuoja daug metrikų per JMX ir HTTP endpointus. Integruokite juos su Prometheus, Grafana ar kita monitoring sistema. Ypač svarbu stebėti segment availability, query latency ir ingestion lag.

Štai pavyzdys, kaip galėtų atrodyti Druid konfigūracija su roll-up:

„`json
{
„dataSchema”: {
„dataSource”: „web_analytics”,
„granularitySpec”: {
„segmentGranularity”: „hour”,
„queryGranularity”: „minute”,
„rollup”: true
},
„dimensionsSpec”: {
„dimensions”: [
„page_url”,
„country”,
„device_type”
]
},
„metricsSpec”: [
{„name”: „pageviews”, „type”: „count”},
{„name”: „unique_visitors”, „type”: „hyperUnique”, „fieldName”: „user_id”},
{„name”: „avg_load_time”, „type”: „doubleSum”, „fieldName”: „load_time”}
]
}
}
„`

Su šia konfigūracija Druid automatiškai agregavus visus įvykius per minutę, skaičiuos puslapio peržiūras, unikalius lankytojus (naudojant HyperLogLog algoritmą) ir vidutinį puslapio įkėlimo laiką.

Kada Druid yra tinkamas pasirinkimas ir kada ne

Būkime sąžiningi – Druid nėra universalus sprendimas. Yra situacijų, kai jis puikiai tinka, ir situacijų, kai geriau rinktis kažką kita.

Druid puikiai tinka, kai:

Analizuojate didelius kiekius įvykių ar laiko eilučių duomenų. Jei turite milijardus įrašų ir norite juos analizuoti interaktyviai, Druid yra puikus pasirinkimas.

Jums reikia realaus laiko analitikos. Jei verslui svarbu matyti, kas vyksta dabar, o ne vakar, Druid streaming ingestion yra neįkainojamas.

Kuriate interaktyvius dashboard’us. Druid užklausų greitis (dažnai < 100ms) leidžia kurti tikrai interaktyvius vartotojo sąsajas, kur filtrai ir grupavimas veikia akimirksniu. Jums reikia high availability. Druid architektūra su replikacija ir automatišku failover užtikrina, kad sistema veiktų net kai kai kurie komponentai išjungiami. Druid nėra geriausias pasirinkimas, kai:

Jums reikia transakcijų. Druid nėra transakcinis sistema ir nepalaiko ACID garantijų. Jei jums reikia atnaujinti ar ištrinti individualius įrašus, geriau naudoti tradicinę duomenų bazę.

Jūsų duomenų kiekis mažas. Jei analizuojate tik kelis milijonus įrašų, Druid bus overkill. PostgreSQL su tinkamais indeksais greičiausiai bus pakankamai greitas ir daug paprastesnis.

Jums reikia sudėtingų join’ų. Nors Druid palaiko tam tikrus join’us, jis nėra optimizuotas sudėtingoms reliacinėms užklausoms. Jei jūsų užklausos reikalauja daug join’ų tarp skirtingų lentelių, geriau naudoti tradicinę analitinę duomenų bazę.

Neturite resursų cluster’io valdymui. Druid reikalauja bent kelių serverių ir tam tikro DevOps įgūdžių. Jei jūsų komanda maža, galbūt geriau rinktis managed sprendimą ar paprastesnę sistemą.

Praktinis scenarijus: IoT duomenų analizė

Leiskite pasidalinti realiu pavyzdžiu, kaip Druid gali būti naudojamas IoT aplinkoje. Įsivaizduokite, kad turite 10,000 sensorių, kurie siunčia temperatūros, drėgmės ir slėgio duomenis kas 10 sekundžių. Tai 3,000 įrašų per sekundę arba apie 260 milijonų įrašų per dieną.

Pirmiausia, sukonfigūruojame duomenų įkėlimą iš Kafka:

„`json
{
„type”: „kafka”,
„spec”: {
„dataSchema”: {
„dataSource”: „iot_sensors”,
„timestampSpec”: {
„column”: „timestamp”,
„format”: „millis”
},
„dimensionsSpec”: {
„dimensions”: [
„sensor_id”,
„location”,
„sensor_type”
]
},
„metricsSpec”: [
{„name”: „count”, „type”: „count”},
{„name”: „avg_temperature”, „type”: „doubleSum”, „fieldName”: „temperature”},
{„name”: „avg_humidity”, „type”: „doubleSum”, „fieldName”: „humidity”},
{„name”: „avg_pressure”, „type”: „doubleSum”, „fieldName”: „pressure”}
],
„granularitySpec”: {
„segmentGranularity”: „hour”,
„queryGranularity”: „minute”,
„rollup”: true
}
},
„ioConfig”: {
„topic”: „sensor_data”,
„consumerProperties”: {
„bootstrap.servers”: „kafka:9092”
},
„taskDuration”: „PT1H”
},
„tuningConfig”: {
„type”: „kafka”,
„maxRowsPerSegment”: 5000000
}
}
}
„`

Su roll-up įjungtu, vietoj saugojimo 260 milijonų individualių įrašų per dieną, saugosime tik apie 14 milijonus agregavus įrašų (10,000 sensorių × 24 valandos × 60 minučių). Tai 18 kartų sumažina duomenų kiekį!

Dabar galime užklausti duomenis labai greitai:

„`sql
SELECT
TIME_FLOOR(__time, ‘PT1H’) as hour,
location,
AVG(avg_temperature / count) as temperature,
AVG(avg_humidity / count) as humidity
FROM iot_sensors
WHERE __time >= CURRENT_TIMESTAMP – INTERVAL ’24’ HOUR
AND location IN (‘warehouse_1’, ‘warehouse_2’)
GROUP BY 1, 2
ORDER BY 1 DESC
„`

Ši užklausa grąžins vidutines temperatūras ir drėgmę per paskutines 24 valandas dviem sandėliams, agregavus kas valandą. Su tinkamu Druid cluster’iu, ši užklausa turėtų grįžti per 50-100 milisekundžių.

Ateitis su Druid: kas laukia priekyje

Apache Druid bendruomenė aktyviai vystosi, ir artimiausioje ateityje matome keletą įdomių krypčių. Multi-stage query engine, kuris leis efektyvesnius join’us ir sudėtingesnes transformacijas, jau yra beta versijoje. Tai gali reikšmingai išplėsti Druid panaudojimo atvejus.

Taip pat matome vis daugiau integracijų su machine learning platformomis. Druid greitis daro jį puikiu pasirinkimu feature store’ui – sistemai, kuri teikia požymius ML modeliams realiu laiku. Įsivaizduokite fraud detection sistemą, kuri per milisekundes gali gauti agregavus vartotojo elgesio metrikas iš paskutinių 24 valandų.

Cloud-native funkcionalumas taip pat stiprėja. Nors Druid visada buvo horizontaliai plečiamas, naujos versijos dar geriau integruojasi su Kubernetes, auto-scaling ir serverless paradigmomis. Tai reiškia, kad galėsite lengviau valdyti Druid cluster’ius ir mokėti tik už tai, ką naudojate.

Praktiškai kalbant, jei jūsų organizacija dirba su dideliais duomenų kiekiais ir jums reikia greičio, verta investuoti laiką į Druid išmokimą. Taip, mokymosi kreivė egzistuoja, bet rezultatai gali būti įspūdingi. Pradėkite nuo nedidelio proof-of-concept projekto, eksperimentuokite su skirtingomis konfigūracijomis ir matuokite našumą. Druid dokumentacija yra išsami, o bendruomenė – aktyvi ir pasiruošusi padėti.

Svarbiausia – neįsivaikite hype. Įvertinkite savo realius poreikius, duomenų kiekius ir komandos gebėjimus. Jei Druid tinka jūsų atvejui, jis gali tapti neįkainojamu įrankiu jūsų analitikos arsenale. Jei ne – nėra gėdos pripažinti, kad paprastesnis sprendimas gali būti geresnis pasirinkimas.

Daugiau

Legendos būsena: reagavimo būsena