6.1 Vem uppfann HBase och varför

I den här föreläsningen kommer vi att prata om ett så underbart verktyg som Hbase, som nyligen har vunnit stor popularitet: till exempel använder Facebook det som grund för sitt meddelandesystem, och det säger redan en hel del.

Föreläsningen kommer att prata om konceptet Big Table och dess fria implementering, funktioner i arbete och skillnader från både klassiska relationsdatabaser (som MySQL och Oracle) och nyckel-värdelagringar som Redis, Aerospike och memcached. Låt oss som vanligt börja med problemets historia. Precis som många andra BigData-projekt föddes Hbase från ett koncept som utvecklats av Google. Principerna bakom Hbase beskrevs i artikeln Bigtable: A Distributed Storage System for Structured Data .

Som vi diskuterade i tidigare föreläsningar är vanliga filer ganska väl lämpade för batchdatabehandling med hjälp av MapReduce-paradigmet. Å andra sidan är information som lagras i filer ganska obekväm att uppdatera; Filer fråntas också möjligheten till slumpmässig åtkomst. För snabbt och bekvämt arbete med slumpmässig åtkomst finns det en klass av nosql-system som lagring av nyckel-värden, som Aerospike, Redis, Couchbase, Memcached. Batchbearbetning är emellertid vanligtvis mycket obekväm i dessa system. Hbase är ett försök att kombinera bekvämligheten med batchbearbetning med bekvämligheten med uppdatering och direktåtkomst.

6.2 Datamodell

HBase är en distribuerad, kolumnorienterad nyckel-värdesdatabas med flera versioner.

  • Datan är organiserad i tabeller som indexeras av en primärnyckel som kallas RowKey i Hbase.
  • För varje RowKey-nyckel kan en obegränsad uppsättning attribut (eller kolumner) lagras.
  • Kolumner är organiserade i grupper av kolumner som kallas Kolumnfamilj. Som regel kombineras kolumner som har samma användnings- och lagringsmönster till en kolumnfamilj.
  • För varje attribut kan flera olika versioner lagras. Olika versioner har olika tidsstämpel.

Posterna lagras fysiskt i RowKey-sorterad ordning. I detta fall lagras data som motsvarar olika kolumnfamiljer separat, vilket gör det möjligt att om nödvändigt läsa data endast från den önskade kolumnfamiljen.

När ett visst attribut raderas raderas det inte fysiskt omedelbart, utan markeras endast med en speciell gravstensflagga. Den fysiska raderingen av data kommer att ske senare, när den stora komprimeringen utförs.

Attribut som tillhör samma kolumngrupp och som motsvarar samma nyckel lagras fysiskt som en sorterad lista. Vilket attribut som helst kan vara frånvarande eller närvarande för varje nyckel, och om attributet saknas, orsakar detta inte överkostnader för att lagra tomma värden.

List- och kolumngruppsnamnen är fasta och har en tydlig layout. På kolumngruppsnivå ställs parametrar som time to live (TTL) och det maximala antalet lagrade versioner. Om skillnaden mellan tidsstämpeln för en viss version och den aktuella tiden är större än TTL, markeras posten för radering. Om antalet versioner för ett visst attribut överstiger det maximala antalet versioner, markeras även posten för radering.

Hbase-datamodellen kan komma ihåg som en nyckel-värde-matchning:

<table, RowKey, Column Family, Column, timestamp> -> Value

6.3 Operationer som stöds

Listan över stödda operationer i hbase är ganska enkel. 4 huvudoperationer stöds:

  • Put : lägg till en ny post i hbase. Tidsstämpeln för denna post kan ställas in för hand, annars ställs den in automatiskt till den aktuella tiden.
  • Hämta : Hämta data för en specifik radnyckel. Du kan ange från vilken kolumnfamilj vi ska hämta data och antalet versioner vi vill läsa.
  • Skanna : läs poster en efter en. Du kan ange posten från vilken vi börjar läsa, posten som vi ska läsa, antalet poster som ska läsas, kolumnfamiljen från vilken läsningen kommer att utföras och det maximala antalet versioner för varje post.
  • Ta bort : Markera en specifik version för radering. Det kommer inte att ske någon fysisk radering, den kommer att skjutas upp till nästa större packning (se nedan).

6.4 Arkitektur

HBase är en distribuerad databas som kan köras på dussintals eller hundratals fysiska servrar, vilket säkerställer oavbruten drift även om några av dem misslyckas. Därför är arkitekturen för HBase ganska komplex jämfört med klassiska relationsdatabaser.

HBase använder två huvudprocesser för sitt arbete:

1. Regionserver - Betjänar en eller flera regioner. En region är ett intervall av poster som motsvarar ett specifikt intervall av på varandra följande radnycklar. Varje region innehåller:

  • Persistent Storage är den huvudsakliga datalagringen i HBase. Data lagras fysiskt på HDFS, i ett speciellt HFile-format. Data i HFile lagras i RowKey-sorterad ordning. Ett par (region, kolumnfamilj) motsvarar minst en HFIle.
  • MemStore - skrivbuffert. Eftersom data lagras i HF-fil d i sorterad ordning är det ganska dyrt att uppdatera HF-filen per post. Istället, när du skriver, kommer data in i ett speciellt MemStore-minnesområde, där det ackumuleras under en tid. När MemStore är fylld till något kritiskt värde skrivs data till en ny HF-fil.
  • BlockCache - cache för läsning. Ger dig möjlighet att avsevärt spara tid på data som läses ofta.
  • Write Ahead Log (WAL) . Eftersom data skrivs till memstore finns det en viss risk för dataförlust på grund av en krasch. För att förhindra att detta inträffar, hamnar alla operationer innan den faktiska implementeringen av manipulationerna i en speciell loggfil. Detta gör att du kan återställa data efter eventuella fel.

2. Master Server - huvudservern i HBase-klustret. Mästaren hanterar fördelningen av regioner mellan regionservrar, upprätthåller ett register över regioner, sköter lanseringen av vanliga uppgifter och gör annat användbart arbete.

För att koordinera åtgärder mellan tjänster använder HBase Apache ZooKeeper, en speciell tjänst utformad för att hantera konfigurationer och synkronisera tjänster.

När mängden data i regionen ökar och den når en viss storlek startar Hbase split, en operation som delar upp regionen med 2. För att undvika konstanta uppdelningar av regioner kan du förinställa gränserna för regionerna och öka deras maximum storlek.

Eftersom data för en region kan lagras i flera HFiles, slår Hbase samman dem med jämna mellanrum för att påskynda arbetet. Denna operation kallas komprimering i Hbase. Komprimeringarna är av två typer:

  • Mindre packning . Startar automatiskt, körs i bakgrunden. Har låg prioritet jämfört med andra Hbase-verksamheter.
  • Stor packning . Den startas för hand eller vid förekomsten av vissa triggers (till exempel av en timer). Det har hög prioritet och kan avsevärt bromsa klustret. Större packningar görs bäst vid en tidpunkt då belastningen på klustret är liten. Major Compaction raderar också fysiskt data som tidigare markerats med gravsten.

6.5 Sätt att arbeta med HBase

HBase Shell

Det enklaste sättet att komma igång med Hbase är att använda skalverktyget hbase. Den är tillgänglig direkt efter installation av hbase på valfri hbase-klusternod.

Hbase-skal är en jruby-konsol med inbyggt stöd för alla grundläggande Hbase-operationer. Följande är ett exempel på att skapa en användartabell med två kolumnfamiljer, göra några manipulationer på den och släppa tabellen i slutet i hbase-skalet:

create 'users', {NAME => 'user_profile', VERSIONS => 5}, {NAME => 'user_posts', VERSIONS => 1231231231} 
put 'users', 'id1', 'user_profile:name', 'alexander' 
put 'users', 'id1', 'user_profile:second_name', 'alexander' 
get 'users', 'id1' 
put 'users', 'id1', 'user_profile:second_name', 'kuznetsov' 
get 'users', 'id1' 
get 'users', 'id1', {COLUMN => 'user_profile:second_name', VERSIONS => 5} 
put 'users', 'id2', 'user_profile:name', 'vasiliy' 
put 'users', 'id2', 'user_profile:second_name', 'ivanov' 
scan 'users', {COLUMN => 'user_profile:second_name', VERSIONS => 5} 
delete 'users', 'id1', 'user_profile:second_name' 
get 'users', 'id1' 
disable 'users' 
drop 'users'

Native API

Liksom de flesta andra hadoop-relaterade projekt är hbase implementerat i java, så det ursprungliga api:et är tillgängligt i Java. Native API är ganska väl dokumenterat på den officiella webbplatsen. Här är ett exempel på hur man använder Hbase API hämtat därifrån:

import java.io.IOException;

import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

public class MyLittleHBaseClient {
  public static void main(String[] args) throws IOException {
	Configuration config = HBaseConfiguration.create();
	Connection connection = ConnectionFactory.createConnection(config);
	try {
  	Table table = connection.getTable(TableName.valueOf("myLittleHBaseTable"));
  	try {
    	Put p = new Put(Bytes.toBytes("myLittleRow"));
    	p.add(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"),
    	Bytes.toBytes("Some Value"));
    	table.put(p);

    	Get g = new Get(Bytes.toBytes("myLittleRow"));
    	Result r = table.get(g);
    	byte [] value = r.getValue(Bytes.toBytes("myLittleFamily"),
      	Bytes.toBytes("someQualifier"));

    	String valueStr = Bytes.toString(value);
    	System.out.println("GET: " + valueStr);

    	Scan s = new Scan();
    	s.addColumn(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"));
    	ResultScanner scanner = table.getScanner(s);
    	try {
       	for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
         	System.out.println("Found row: " + rr);
       	}
     	} finally {
       	scanner.close();
     	}
   	} finally {
     	if (table != null) table.close();
   	}
 	} finally {
   	connection.close();
 	}
  }
}

Sparsamhet, REST och stöd för andra programmeringsspråk

För att arbeta från andra programmeringsspråk tillhandahåller Hbase Thrift API och Rest API. Baserat på dem är klienter byggda för alla större programmeringsspråk: python, PHP, Java Script, etc.

6.6 Några funktioner för att arbeta med HBase

  1. Hbase integreras direkt med MapReduce och kan användas som input och output med hjälp av det speciella TableInputFormat och TableOutputFormat.

  2. Det är mycket viktigt att välja rätt RowKey. RowKey ska ge en bra jämn fördelning mellan regioner, annars finns det risk för så kallade "hot regions" - regioner som används mycket oftare än andra, vilket leder till ineffektiv användning av systemresurser.

  3. Om data inte laddas upp enskilt, utan omedelbart i stora partier, stöder Hbase en speciell BulkLoad-mekanism som gör att du kan ladda upp data mycket snabbare än att använda enstaka Puts. BulkLoad är i huvudsak en operation i två steg:

    • Bildande av HFile utan deltagande av puts med hjälp av ett speciellt MapReduce-jobb
    • Infogar dessa filer direkt i Hbase
  4. Hbase stöder utmatning av dess mätvärden till Ganglia-övervakningsservern. Detta kan vara till stor hjälp när du administrerar Hbase för att komma till botten med hbase-problem.

radnyckel

RowKey är användar-ID, vilket är ett GUUID, en sträng speciellt skapad för att vara unik över hela världen. GUUID:er fördelas jämnt, vilket ger en bra fördelning av data över servrar.

Kolumn Familj

Vår lagring använder två kolumnfamiljer:

  • data. Denna grupp av kolumner lagrar data som inte längre är relevant för reklamändamål, till exempel det faktum att en användare har besökt vissa webbadresser. TTL för denna kolumnfamilj är satt till 2 månader, gränsen för antalet versioner är 2000.
  • långa data. Denna grupp av kolumner lagrar data som inte förlorar sin relevans med tiden, såsom kön, födelsedatum och andra "eviga" användaregenskaper.

högtalare

Varje typ av användarfakta lagras i en separat kolumn. Till exempel lagrar kolumnen Data:_v webbadresserna som besökts av användaren, och kolumnen LongData:gender lagrar användarens kön.

Tidsstämpeln för detta faktum lagras som en tidsstämpel. Till exempel, i kolumnen Data:_v är tidsstämpeln den tid då användaren besökte en specifik webbadress.

Denna lagringsstruktur för användardata passar mycket bra med vårt användningsmönster och låter dig snabbt uppdatera användardata, snabbt få all nödvändig information om användare och, med hjälp av MapReduce, snabbt bearbeta data om alla användare på en gång.

6.7 Alternativ

HBase är ganska komplicerat att administrera och använda, så innan du använder HBase är det vettigt att titta på alternativen:

  • Relationsdatabaser . Ett mycket bra alternativ, speciellt i de fall då data får plats på en maskin. Först och främst bör du också tänka på relationsdatabaser i de fall då transaktioner av andra index än de primära är viktiga.

  • Nyckel-värde lagring . Lagringar som Redis och Aerospike är bättre lämpade när latens behövs och batchbearbetning är mindre viktig.

  • Filer och deras bearbetning med MapReduce . Om data bara läggs till och sällan uppdateras/ändras, så är det bättre att inte använda HBase, utan helt enkelt lagra data i filer. För att förenkla arbetet med filer kan du använda verktyg som Hive, Pig och Impala.

Användningen av HBase är motiverad när:

  • Det finns mycket data, och de får inte plats på en dator/server
  • Data uppdateras och raderas ofta
  • Det finns en uttrycklig "nyckel" i data, som det är bekvämt att binda allt annat till
  • Behöver batchbearbetning
  • Behöver slumpmässig tillgång till data med specifika nycklar