sql >> Databasteknik >  >> NoSQL >> HBase

Apache HBase Write Path

Apache HBase är Hadoop-databasen och är baserad på Hadoop Distributed File System (HDFS ). HBase gör det möjligt att slumpmässigt komma åt och uppdatera data lagrade i HDFS, men filer i HDFS kan bara läggas till och är oföränderliga efter att de har skapats. Så du kan fråga dig hur HBase tillhandahåller läsning och skrivning med låg latens? I det här blogginlägget förklarar vi detta genom att beskriva skrivvägen för HBase — hur data uppdateras i HBase.

Skrivvägen är hur en HBase slutför put- eller raderingsoperationer. Den här sökvägen börjar vid en klient, flyttas till en regionserver och slutar när data så småningom skrivs till en HBase-datafil som kallas en HFile . Inkluderat i designen av skrivvägen finns funktioner som HBase använder för att förhindra dataförlust i händelse av ett regionserverfel. Därför kan en förståelse av skrivvägen ge insikt i HBases inbyggda mekanism för att förhindra dataförlust.

Varje HBase-tabell är värd och hanteras av uppsättningar servrar som delas in i tre kategorier:

  1. En aktiv huvudserver
  2. En eller flera backup-masterservrar
  3. Många regionservrar

Regionservrar bidrar till att hantera HBase-tabellerna. Eftersom HBase-tabeller kan vara stora, delas de upp i partitioner som kallas regioner. Varje regionserver hanterar en eller flera av dessa regioner. Observera att eftersom regionservrar är de enda servrarna som betjänar HBase-tabelldata, kan en masterserverkrasch inte orsaka dataförlust.

HBase-data är organiserade på samma sätt som en sorterad karta, med det sorterade nyckelutrymmet uppdelat i olika skärvor eller regioner. En HBase-klient uppdaterar en tabell genom att anropa sätta eller ta bort kommandon. När en klient begär en ändring dirigeras den begäran till en regionserver omedelbart som standard. Men programmässigt kan en klient cachelagra ändringarna på klientsidan och tömma dessa ändringar till regionservrar i en batch genom att stänga av autospolningen. Om autospolning är avstängd, cachelagras ändringarna tills flush-commits anropas, eller bufferten är full beroende på buffertstorleken som är inställd programmatiskt eller konfigurerad med parametern "hbase.client.write.buffer".

Eftersom radnyckeln är sorterad är det lätt att avgöra vilken regionserver som hanterar vilken nyckel. En ändringsförfrågan gäller en specifik rad. Varje radnyckel tillhör en specifik region som betjänas av en regionserver. Så baserat på put- eller delete-nyckeln kan en HBase-klient hitta en riktig regionserver. Till en början lokaliserar den adressen till regionservern som är värd för -ROOT- regionen från ZooKeepers kvorum. Från rotregionservern tar klienten reda på platsen för regionservern som är värd för -META- regionen. Från metaregionservern hittar vi äntligen den faktiska regionservern som betjänar den begärda regionen. Detta är en process i tre steg, så regionplatsen cachelagras för att undvika denna dyra serie operationer. Om den cachade platsen är ogiltig (till exempel får vi något okänt regionundantag), är det dags att lokalisera om regionen och uppdatera cachen.

Efter att begäran har tagits emot av rätt regionserver kan ändringen inte skrivas till en HF-fil omedelbart eftersom data i en HF-fil måste sorteras efter radnyckeln. Detta gör att du kan söka efter slumpmässiga rader effektivt när du läser data. Data kan inte infogas slumpmässigt i HF-filen. Istället måste ändringen skrivas till en ny fil. Om varje uppdatering skrevs till en fil skulle många små filer skapas. En sådan lösning skulle inte vara skalbar eller effektiv att slå samman eller läsa vid ett senare tillfälle. Därför skrivs ändringar inte omedelbart till en ny HF-fil.

Istället lagras varje ändring på en plats i minnet som kallas memstore , som billigt och effektivt stöder slumpmässiga skrivningar. Data i memstore sorteras på samma sätt som data i en HF-fil. När memstore ackumulerar tillräckligt med data skrivs hela den sorterade uppsättningen till en ny HF-fil i HDFS. Att slutföra en stor skrivuppgift är effektivt och drar fördel av HDFS styrkor.

Även om det är effektivt att skriva data till memstore, introducerar det också en riskfaktor:Information som lagras i memstore lagras i flyktigt minne, så om systemet misslyckas går all memstore-information förlorad. För att hjälpa till att minska denna risk sparar HBase uppdateringar i en write-ahead-logg (WAL ) innan du skriver informationen till memstore. På detta sätt, om en regionserver misslyckas, kan information som lagrades i den serverns memstore återställas från dess WAL.

Obs:Som standard är WAL aktiverat, men processen att skriva WAL-filen till disken förbrukar vissa resurser. WAL kan inaktiveras, men detta bör endast göras om risken för dataförlust inte är ett problem. Om du väljer att inaktivera WAL, överväg att implementera din egen katastrofåterställningslösning eller var beredd på möjligheten av dataförlust.

Data i en WAL-fil är organiserad annorlunda än HFile. WAL-filer innehåller en lista med redigeringar, med en redigering som representerar en enda sättning eller radering. Redigeringen innehåller information om ändringen och den region som ändringen gäller. Redigeringarna skrivs kronologiskt, så för beständigheten läggs tillägg till i slutet av WAL-filen som är lagrad på disken. Eftersom WAL-filer är ordnade kronologiskt, finns det aldrig ett behov av att skriva till en slumpmässig plats i filen.

När WAL växer stängs de så småningom och en ny aktiv WAL-fil skapas för att acceptera ytterligare redigeringar. Detta kallas att "rulla" WAL-filen. När en WAL-fil väl har rullats görs inga ytterligare ändringar i den gamla filen.

Som standard rullas WAL-filen när dess storlek är cirka 95 % av HDFS-blockstorleken. Du kan konfigurera multiplikatorn med parametern:"hbase.regionserver.logroll.multiplier", och blockstorleken med parametern:"hbase.regionserver.hlog.blocksize". WAL-filen rullas också periodiskt baserat på det konfigurerade intervallet "hbase.regionserver.logroll.period", en timme som standard, även WAL-filstorleken är mindre än den konfigurerade gränsen.

Att begränsa WAL-filstorleken underlättar effektiv återuppspelning av filer om en återställning krävs. Detta är särskilt viktigt under uppspelning av en regions WAL-fil eftersom när en fil spelas upp, är motsvarande region inte tillgänglig. Avsikten är att så småningom skriva alla ändringar från varje WAL-fil till disk och bevara det innehållet i en HF-fil. När detta är gjort kan WAL-filen arkiveras och den raderas så småningom av LogCleaner-demontråden. Observera att WAL-filer fungerar som en skyddsåtgärd. WAL-filer behöver bara spelas upp igen för att återställa uppdateringar som annars skulle gå förlorade efter en regionserverkrasch.

En regionserver betjänar många regioner, men har inte en WAL-fil för varje region. Istället delas en aktiv WAL-fil mellan alla regioner som betjänas av regionservern. Eftersom WAL-filer rullas regelbundet kan en regionserver ha många WAL-filer. Observera att det bara finns en aktiv WAL per regionserver vid en given tidpunkt.

Om man antar standard-HBase-roten för "/hbase", lagras alla WAL-filer för en regionserverinstans under samma rotmapp, vilket är följande:

/hbase/.logs/<host>,
<port>,<startcode>

Till exempel:

/hbase/.logs/srv.example.com,60020,1254173957298

WAL-loggfiler har följande namn:

/hbase/.logs/<host>,
<port>,<startcode>/<host>%2C
<port>%2C<startcode>.<timestamp>

Till exempel:

/hbase/.logs/srv.example.com,60020,1254173957298/srv.example.com%2C60020%2C1254173957298.1254173957495

Varje redigering i WAL-filen har ett unikt sekvens-ID. Detta id ökar för att bevara redigeringsordningen. Närhelst en loggfil rullas, läggs nästa sekvens-id och det gamla filnamnet i en karta i minnet. Den här informationen används för att spåra det maximala sekvens-ID:t för varje WAL-fil så att vi enkelt kan ta reda på om en fil kan arkiveras vid ett senare tillfälle när någon memstore töms till disken.

Redigeringar och deras sekvens-ID är unika inom en region. Varje gång en redigering läggs till i WAL-loggen, registreras även redigeringens sekvens-id som det sista sekvens-ID som skrevs. När memstore töms till disken rensas det sista sekvens-ID som skrivits för denna region. Om det sista sekvens-ID:t som skrevs till disken är detsamma som det maximala sekvens-ID:t för en WAL-fil, kan man dra slutsatsen att alla redigeringar i en WAL-fil för denna region har skrivits till disken. Om alla redigeringar för alla regioner i en WAL-fil har skrivits till disk, är det tydligt att ingen delning eller uppspelning kommer att krävas, och WAL-filen kan arkiveras.

WAL-filrullning och memstore-spolning är två separata åtgärder och behöver inte ske samtidigt. Vi vill dock inte behålla för många WAL-filer per regionserver för att undvika tidskrävande återställning i händelse av ett regionserverfel. Därför, när en WAL-fil rullas, kontrollerar HBase om det finns för många WAL-filer och bestämmer vilka regioner som ska tömmas så att vissa WAL-filer kan arkiveras.

I det här inlägget förklarar vi HBase-skrivvägen, vilket är hur data i HBase skapas och/eller uppdateras. Några viktiga delar av det är:

  1. Hur en klient lokaliserar en regionserver,
  2. Memstore som stöder snabb slumpmässig skrivning,
  3. WAL-filer som ett sätt att undvika dataförlust om regionservern misslyckas.

Vi kommer att prata om HF-filformat, WAL-fildelning och så vidare i efterföljande inlägg.


  1. Inkludera specifika fält i ett jokerteckenindex i MongoDB

  2. Slå samman två arrayfält i mongoDB

  3. räkna antal sessioner i connect-redis

  4. Redis Client List syfte och beskrivning