Lær om designbeslutningerne bag HBases nye understøttelse af MOB'er.
Apache HBase er en distribueret, skalerbar, effektiv, konsistent nøgleværdidatabase, der kan gemme en række binære datatyper. Det udmærker sig ved at gemme mange relativt små værdier (<10K) og give læsning og skrivning med lav latens.
Der er dog en stigende efterspørgsel efter lagring af dokumenter, billeder og andre moderate objekter (MOB'er) i HBase, samtidig med at der opretholdes lav latenstid for læsning og skrivning. En sådan use case er en bank, der opbevarer underskrevne og scannede kundedokumenter. Som et andet eksempel vil transportbureauer måske gemme snapshots af trafik og biler i bevægelse. Disse MOB'er skrives normalt én gang.
Desværre kan ydeevnen forringes i situationer, hvor mange moderate værdier (100K til 10MB) lagres på grund af det stadigt stigende I/O-tryk, der skabes af komprimeringer. Overvej det tilfælde, hvor 1 TB fotos fra trafikkameraer, hver 1 MB i størrelse, gemmes i HBase dagligt. Dele af de lagrede filer komprimeres flere gange via mindre komprimeringer, og til sidst bliver data omskrevet ved større komprimeringer. Sammen med akkumulering af disse MOB'er vil I/O skabt af komprimeringer bremse komprimeringerne, blokere memstore flushing yderligere og til sidst blokere opdateringer. En stor MOB-butik vil udløse hyppige regionopdelinger, hvilket reducerer tilgængeligheden af de berørte regioner.
For at løse disse ulemper har Cloudera- og Intel-ingeniører implementeret MOB-understøttelse i en HBase-gren (hbase-11339:HBase MOB). Denne gren vil blive flettet til masteren i HBase 1.1 eller 1.2 og er allerede til stede og understøttet også i CDH 5.4.x.
Operationer på MOB'er er normalt skrivetunge med sjældne opdateringer eller sletninger og relativt sjældne læsninger. MOB'er gemmes normalt sammen med deres metadata. Metadata relateret til MOB'er kan for eksempel omfatte bilnummer, hastighed og farve. Metadata er meget små i forhold til MOB'erne. Metadata er normalt tilgået til analyse, mens MOB'er normalt kun tilgås tilfældigt, når de eksplicit anmodes om med rækketaster.
Brugere ønsker at læse og skrive MOB'erne i HBase med lav latenstid i de samme API'er og ønsker stærk konsistens, sikkerhed, snapshot og HBase-replikering mellem klynger og så videre. For at nå disse mål blev MOB'er flyttet ud af HBases hoved-I/O-sti og ind i en ny I/O-sti.
I dette indlæg lærer du om denne designtilgang, og hvorfor den blev valgt.
Mulige tilgange
Der var et par mulige tilgange til dette problem. Den første tilgang, vi overvejede, var at gemme MOB'er i HBase med en tunet opdeling og komprimeringspolitikker - en større ønsket MaxFileSize reducerer frekvensen af regionopdeling, og færre eller ingen komprimeringer kan undgå skriveforstærkningsstraffen. Den tilgang ville forbedre skriveforsinkelse og gennemløb betydeligt. Men sammen med det stigende antal lagrede filer ville der være for mange åbne læsere i en enkelt butik, endda flere end hvad der er tilladt af OS. Som følge heraf ville en masse hukommelse blive forbrugt, og læseydelsen ville forringes.
En anden tilgang var at bruge en HBase + HDFS-model til at gemme metadata og MOB'er separat. I denne model er en enkelt fil forbundet med en post i HBase. Dette er en klientløsning, og transaktionen styres af klienten - ingen HBase-sidehukommelser forbruges af MOB'er. Denne tilgang ville fungere for objekter større end 50 MB, men for MOB'er fører mange små filer til ineffektiv HDFS-brug, da standardblokstørrelsen i HDFS er 128 MB.
Lad os for eksempel sige, at en NameNode har 48 GB hukommelse, og hver fil er 100 KB med tre replikaer. Hver fil tager mere end 300 bytes i hukommelsen, så en NameNode med 48 GB hukommelse kan rumme omkring 160 millioner filer, hvilket ville begrænse os til kun at gemme 16 TB MOB-filer i alt.
Som en forbedring kunne vi have samlet de små MOB-filer til større - det vil sige, en fil kunne have flere MOB-poster - og gemme forskydningen og længden i HBase-tabellen for hurtig læsning. Det er dog vanskeligt at opretholde datakonsistens og administrere slettede MOB'er og små MOB-filer i komprimeringer.
Desuden, hvis vi skulle bruge denne tilgang, ville vi være nødt til at overveje nye sikkerhedspolitikker, miste atomicitetsegenskaber ved skrivninger og potentielt miste sikkerhedskopieringen og katastrofegendannelsen leveret af replikering og snapshots.
HBase MOB-design
I sidste ende, fordi de fleste bekymringer omkring lagring af MOB'er i HBase involverer I/O skabt af komprimeringer, var nøglen at flytte MOB'er ud af administration af normale regioner for at undgå regionopdelinger og komprimeringer der.
HBase MOB-design ligner HBase + HDFS-tilgangen, fordi vi gemmer metadata og MOB'er separat. Forskellen ligger dog i et serversidedesign:memstore cacher MOB'erne, før de tømmes til disken, MOB'erne skrives ind i en HF-fil kaldet "MOB-fil" i hver flush, og hver MOB-fil har flere indgange i stedet for en enkelt fil i HDFS for hver MOB. Denne MOB-fil er gemt i et særligt område. Al læsning og skrivning kan bruges af de nuværende HBase API'er.
Skriv og læs
Hver MOB har en tærskel:hvis værdilængden af en celle er større end denne tærskel, betragtes denne celle som en MOB-celle.
Når MOB-cellerne er opdateret i regionerne, skrives de til WAL og memstore, ligesom de normale celler. Ved flushing tømmes MOB'erne til MOB-filer, og metadataene og stierne til MOB-filer tømmes for at gemme filer. Datakonsistensen og HBase-replikeringsfunktionerne er indbygget i dette design.
MOB-redigeringerne er større end normalt. I synkroniseringen er den tilsvarende I/O også større, hvilket kan bremse WAL's synkroniseringsoperationer. Hvis der er andre regioner, der deler den samme WAL, kan skrivelatensen for disse regioner blive påvirket. Men hvis datakonsistensen og ikke-volatiliteten er nødvendig, er WAL et must.
Cellerne har tilladelse til at flytte mellem lagrede filer og MOB-filer i komprimeringerne ved at ændre tærsklen. Standardgrænsen er 100KB.
Som illustreret nedenfor kaldes de celler, der indeholder stierne til MOB-filer, referenceceller . Mærkerne bevares i cellerne, så vi kan fortsætte med at stole på HBase-sikkerhedsmekanismen.
Referencecellerne har referencemærker, der adskiller dem fra normale celler. Et referencemærke antyder en MOB-celle i en MOB-fil, og der er derfor behov for yderligere løsning ved læsning.
Under læsning åbner butiksscanneren scannere for at memstore og gemme filer. Hvis en referencecelle er opfyldt, læser scanneren filstien fra celleværdien og søger den samme rækkenøgle fra den fil. Blokcachen kan aktiveres for MOB-filerne i scanning, hvilket kan fremskynde søgningen.
Det er ikke nødvendigt at åbne læsere til alle MOB-filer; kun én er nødvendig, når det er nødvendigt. Denne tilfældige læsning påvirkes ikke af antallet af MOB-filer. Så vi behøver ikke at komprimere MOB-filerne igen og igen, når de er store nok.
MOB-filnavnet er læsbart og består af tre dele:MD5 for startnøglen, den seneste dato for celler i denne MOB-fil og en UUID. Den første del er startnøglen for regionen, hvorfra denne MOB-fil skylles. Normalt har MOB'erne en brugerdefineret TTL, så du kan finde og slette udløbne MOB-filer ved at sammenligne den anden del med TTL'en.
Snapshot
For at være mere venlige over for snapshottet, gemmes MOB-filerne i en speciel dummy-region, hvorved snapshot, tabeleksport/kloning og arkiv fungerer som forventet.
Når man gemmer et snapshot til en tabel, opretter man MOB-regionen i snapshotet og tilføjer de eksisterende MOB-filer til manifestet. Når du gendanner snapshottet, skal du oprette fillinks i MOB-området.
Rengøring og komprimering
Der er to situationer, hvor MOB-filer skal slettes:når MOB-filen er udløbet, og når MOB-filen er for lille og bør flettes sammen til større for at forbedre HDFS-effektiviteten.
HBase MOB har en opgave i master:den scanner MOB-filerne, finder de udløbne, bestemt af datoen i filnavnet, og sletter dem. Diskplads genvindes således med jævne mellemrum ved at forælde udløbne MOB-filer.
MOB-filer kan være relativt små sammenlignet med en HDFS-blok, hvis du skriver rækker, hvor kun nogle få poster kvalificerer som MOB'er; også kan der være slettede celler. Du skal droppe de slettede celler og flette de små filer til større for at forbedre HDFS-udnyttelsen. MOB-komprimeringerne komprimerer kun de små filer, og de store filer bliver ikke rørt, hvilket undgår gentagen komprimering til store filer.
Nogle andre ting at huske på:
- Vid, hvilke celler der slettes. I hver HBase større komprimering skrives slettemarkørerne til en del-fil, før de slippes.
- I det første trin af MOB-komprimeringer bliver disse delfiler slået sammen til større.
- Alle små MOB-filer er valgt. Hvis antallet af små filer er lig med antallet af eksisterende MOB-filer, betragtes denne komprimering som en større komprimering og kaldes en ALL_FILES komprimering.
- Disse valgte filer er opdelt efter startnøglen og datoen i filnavnet. De små filer i hver partition komprimeres med del-filer, så slettede celler kan slettes; i mellemtiden genereres en ny HF-fil med nye referenceceller, komprimatoren commiterer den nye MOB-fil, og derefter masseindlæser den denne HF-fil i HBase.
- Når komprimeringer i alle partitioner er afsluttet, arkiveres del-filerne, hvis en ALL_FILES-komprimering er involveret.
MOB-filernes livscyklus er illustreret nedenfor. Grundlæggende oprettes de, når memstore tømmes, og slettes af HFileCleaner fra filsystemet, når de ikke refereres af snapshottet eller udløber i arkivet.
Konklusion
Sammenfattende flytter det nye HBase MOB-design MOB'er ud af HBases primære I/O-sti, mens de bevarer de fleste sikkerheds-, komprimerings- og snapshot-funktioner. Det tager højde for egenskaberne ved operationer i MOB, gør skriveforstærkningen af MOB'er mere forudsigelig og holder lave latenser i både læsning og skrivning.
Jincheng Du er softwareingeniør hos Intel og en HBase-bidragyder.
Jon Hsieh er softwareingeniør hos Cloudera og HBase-committer/PMC-medlem. Han er også grundlæggeren af Apache Flume, og en committer på Apache Sqoop.