6.1 Wie heeft HBase uitgevonden en waarom

In deze lezing zullen we het hebben over zo'n geweldige tool als Hbase, die onlangs enorm populair is geworden: Facebook gebruikt het bijvoorbeeld als basis van zijn berichtensysteem, en dit zegt al veel.

De lezing zal het hebben over het concept van Big Table en de gratis implementatie ervan, de kenmerken van werk en het verschil met zowel klassieke relationele databases (zoals MySQL en Oracle) als key-value storages zoals Redis, Aerospike en memcached. Laten we zoals gewoonlijk beginnen met de geschiedenis van het probleem. Net als veel andere BigData-projecten is Hbase ontstaan ​​uit een concept dat is ontwikkeld door Google. De principes achter Hbase zijn beschreven in het artikel Bigtable: A Distributed Storage System for Structured Data .

Zoals we in eerdere lezingen hebben besproken, zijn gewone bestanden redelijk geschikt voor batchverwerking van gegevens met behulp van het MapReduce-paradigma. Aan de andere kant is informatie die is opgeslagen in bestanden nogal onhandig om bij te werken; Bestanden worden ook de mogelijkheid van willekeurige toegang ontnomen. Voor snel en gemakkelijk werken met willekeurige toegang is er een klasse van nosql-systemen zoals sleutel-waardeopslag, zoals Aerospike, Redis, Couchbase, Memcached. Batchverwerking is echter meestal erg onhandig in deze systemen. Hbase is een poging om het gemak van batchverwerking te combineren met het gemak van updaten en willekeurige toegang.

6.2 Gegevensmodel

HBase is een gedistribueerde, kolomgeoriënteerde sleutel-waardedatabase met meerdere versies.

  • De gegevens zijn georganiseerd in tabellen die zijn geïndexeerd door een primaire sleutel genaamd RowKey in Hbase.
  • Voor elke RowKey-sleutel kan een onbeperkte set attributen (of kolommen) worden opgeslagen.
  • Kolommen zijn georganiseerd in groepen kolommen die Column Family worden genoemd. In de regel worden kolommen met hetzelfde gebruiks- en opslagpatroon gecombineerd tot één Column Family.
  • Voor elk attribuut kunnen verschillende versies worden opgeslagen. Verschillende versies hebben verschillende tijdstempels.

Records worden fysiek opgeslagen in RowKey gesorteerde volgorde. In dit geval worden de gegevens die overeenkomen met verschillende kolomfamilies afzonderlijk opgeslagen, waardoor, indien nodig, alleen gegevens van de gewenste kolomfamilie kunnen worden gelezen.

Wanneer een bepaald attribuut wordt verwijderd, wordt het niet direct fysiek verwijderd, maar alleen gemarkeerd met een speciale tombstone-vlag. De fysieke verwijdering van de gegevens zal later plaatsvinden, wanneer de Major Compaction-bewerking wordt uitgevoerd.

Attributen die tot dezelfde kolomgroep behoren en overeenkomen met dezelfde sleutel worden fysiek opgeslagen als een gesorteerde lijst. Elk attribuut kan afwezig of aanwezig zijn voor elke sleutel, en als het attribuut afwezig is, veroorzaakt dit niet de overhead van het opslaan van lege waarden.

De lijst- en kolomgroepnamen zijn vast en hebben een duidelijke lay-out. Op kolomgroepniveau worden parameters zoals time to live (TTL) en het maximum aantal opgeslagen versies ingesteld. Als het verschil tussen de tijdstempel voor een bepaalde versie en de huidige tijd groter is dan TTL, wordt de invoer gemarkeerd voor verwijdering. Als het aantal versies van een bepaald attribuut het maximale aantal versies overschrijdt, wordt het record ook gemarkeerd voor verwijdering.

Het Hbase-gegevensmodel kan worden onthouden als een sleutel-waarde-overeenkomst:

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

6.3 Ondersteunde operaties

De lijst met ondersteunde bewerkingen in hbase is vrij eenvoudig. Er worden 4 hoofdbewerkingen ondersteund:

  • Put : voeg een nieuw item toe aan hbase. Het tijdstempel van dit item kan met de hand worden ingesteld, anders wordt het automatisch op de huidige tijd gezet.
  • Get : Haal gegevens op voor een specifieke RowKey. U kunt de kolomfamilie specificeren waaruit we de gegevens halen en het aantal versies dat we willen lezen.
  • Scannen : records één voor één lezen. U kunt het record opgeven van waaruit we beginnen met lezen, het record waarnaar moet worden gelezen, het aantal records dat moet worden gelezen, de kolomfamilie waaruit het lezen zal worden uitgevoerd en het maximum aantal versies voor elk record.
  • Verwijderen : Markeer een specifieke versie voor verwijdering. Er vindt geen fysieke verwijdering plaats, deze wordt uitgesteld tot de volgende grote verdichting (zie hieronder).

6.4 Architectuur

HBase is een gedistribueerde database die op tientallen of honderden fysieke servers kan draaien, waardoor een ononderbroken werking wordt gegarandeerd, zelfs als sommige uitvallen. Daarom is de architectuur van HBase behoorlijk complex in vergelijking met klassieke relationele databases.

HBase gebruikt twee hoofdprocessen voor zijn werk:

1. Regioserver - bedient een of meer regio's. Een regio is een bereik van records dat overeenkomt met een specifiek bereik van opeenvolgende rijsleutels. Elke regio bevat:

  • Persistent Storage is de belangrijkste gegevensopslag in HBase. De gegevens worden fysiek opgeslagen op HDFS, in een speciaal HFile-formaat. Gegevens in HFile worden opgeslagen in RowKey gesorteerde volgorde. Eén paar (regio, kolomfamilie) komt overeen met ten minste één HFIle.
  • MemStore - schrijfbuffer. Aangezien de gegevens in gesorteerde volgorde in HFile d worden opgeslagen, is het vrij duur om de HFile per record bij te werken. In plaats daarvan komen gegevens tijdens het schrijven een speciaal geheugengebied van MemStore binnen, waar het zich enige tijd ophoopt. Wanneer de MemStore tot een kritische waarde is gevuld, worden de gegevens naar een nieuw HFile geschreven.
  • BlockCache - cache voor lezen. Hiermee kunt u aanzienlijk tijd besparen op gegevens die vaak worden gelezen.
  • Vooruit schrijven logboek (WAL) . Aangezien de gegevens naar de memstore worden geschreven, bestaat er enig risico op gegevensverlies als gevolg van een crash. Om dit te voorkomen, vallen alle bewerkingen vóór de daadwerkelijke uitvoering van de manipulaties in een speciaal logbestand. Hierdoor kunt u gegevens herstellen na een eventuele storing.

2. Master Server - de hoofdserver in het HBase-cluster. De Master beheert de verdeling van regio's over regioservers, houdt een register bij van regio's, beheert de lancering van reguliere taken en doet ander nuttig werk.

Om acties tussen services te coördineren, gebruikt HBase Apache ZooKeeper, een speciale service die is ontworpen om configuraties te beheren en services te synchroniseren.

Wanneer de hoeveelheid gegevens in de regio toeneemt en deze een bepaalde grootte bereikt, start Hbase splitsen, een bewerking die de regio door 2 splitst. Om constante verdelingen van regio's te voorkomen, kunt u de grenzen van de regio's vooraf instellen en hun maximum verhogen maat.

Aangezien gegevens voor één regio in verschillende HFiles kunnen worden opgeslagen, voegt Hbase ze periodiek samen om het werk te versnellen. Deze bewerking wordt verdichting genoemd in Hbase. Verdichtingen zijn van twee soorten:

  • Kleine verdichting . Start automatisch, draait op de achtergrond. Heeft een lage prioriteit in vergelijking met andere Hbase-bewerkingen.
  • Grote verdichting . Het wordt met de hand gelanceerd of bij het optreden van bepaalde triggers (bijvoorbeeld door een timer). Het heeft een hoge prioriteit en kan het cluster aanzienlijk vertragen. Grote verdichtingen kunnen het beste worden uitgevoerd op een moment dat de belasting van het cluster klein is. Major Compaction verwijdert ook fysiek gegevens die eerder met een tombstone waren gemarkeerd.

6.5 Manieren om met HBase te werken

HBase-shell

De gemakkelijkste manier om met Hbase aan de slag te gaan, is door het hulpprogramma hbase shell te gebruiken. Het is direct beschikbaar na installatie van hbase op elk hbase-clusterknooppunt.

Hbase shell is een jruby-console met ingebouwde ondersteuning voor alle basis Hbase-bewerkingen. Het volgende is een voorbeeld van het maken van een gebruikerstabel met twee kolomfamilies, het uitvoeren van enkele bewerkingen en het neerzetten van de tabel aan het einde in de hbase-shell:

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

Net als de meeste andere hadoop-gerelateerde projecten, wordt hbase geïmplementeerd in Java, dus de native API is beschikbaar in Java. De Native API is vrij goed gedocumenteerd op de officiële website. Hier is een voorbeeld van het gebruik van de Hbase API die daar vandaan is gehaald:

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();
 	}
  }
}

Spaarzaamheid, REST en ondersteuning voor andere programmeertalen

Om vanuit andere programmeertalen te werken, biedt Hbase Thrift API en Rest API. Op basis daarvan worden clients gebouwd voor alle belangrijke programmeertalen: python, PHP, Java Script, enz.

6.6 Enkele kenmerken van het werken met HBase

  1. Hbase integreert out of the box met MapReduce en kan worden gebruikt als invoer en uitvoer met behulp van de speciale TableInputFormat en TableOutputFormat.

  2. Het is erg belangrijk om de juiste RowKey te kiezen. RowKey moet zorgen voor een goede, gelijkmatige verdeling over de regio's, anders bestaat het risico van zogenaamde "hete regio's" - regio's die veel vaker worden gebruikt dan andere, wat leidt tot inefficiënt gebruik van systeembronnen.

  3. Als de gegevens niet afzonderlijk, maar direct in grote batches worden geüpload, ondersteunt Hbase een speciaal BulkLoad-mechanisme waarmee u gegevens veel sneller kunt uploaden dan met enkele Puts. BulkLoad is in wezen een bewerking in twee stappen:

    • Vorming van HFile zonder de deelname van puts met behulp van een speciale MapReduce-taak
    • Deze bestanden rechtstreeks in Hbase invoegen
  4. Hbase ondersteunt het uitvoeren van zijn statistieken naar de Ganglia-bewakingsserver. Dit kan erg handig zijn bij het beheer van Hbase om hbase-problemen op te lossen.

rij sleutel

De RowKey is de gebruikers-ID, een GUUID, een tekenreeks die speciaal is gegenereerd om wereldwijd uniek te zijn. GUUID's worden gelijkmatig verdeeld, wat zorgt voor een goede verdeling van gegevens over servers.

Kolom Familie

Onze opslag gebruikt twee kolomfamilies:

  • gegevens. In deze groep kolommen worden gegevens opgeslagen die niet langer relevant zijn voor advertentiedoeleinden, zoals het feit dat een gebruiker bepaalde URL's heeft bezocht. De TTL voor deze Column Family is ingesteld op 2 maanden, de limiet op het aantal versies is 2000.
  • lange gegevens. In deze groep kolommen worden gegevens opgeslagen die in de loop van de tijd niet aan relevantie verliezen, zoals geslacht, geboortedatum en andere 'eeuwige' gebruikerskenmerken.

luidsprekers

Elk type gebruikersfeiten wordt opgeslagen in een aparte kolom. In de kolom Data:_v worden bijvoorbeeld de door de gebruiker bezochte URL's opgeslagen en in de kolom LongData:gender wordt het geslacht van de gebruiker opgeslagen.

Het tijdstempel van dit feit wordt opgeslagen als een tijdstempel. In de kolom Data:_v is de tijdstempel bijvoorbeeld het tijdstip waarop de gebruiker een specifieke URL heeft bezocht.

Deze opslagstructuur voor gebruikersgegevens past heel goed bij ons gebruikspatroon en stelt u in staat om snel gebruikersgegevens bij te werken, snel alle benodigde informatie over gebruikers te krijgen en, met behulp van MapReduce, snel gegevens over alle gebruikers tegelijk te verwerken.

6.7 Alternatieven

HBase is vrij complex om te beheren en te gebruiken, dus voordat u HBase gebruikt, is het zinvol om naar de alternatieven te kijken:

  • relationele databases . Een heel goed alternatief, zeker als de data op één machine passen. Ook moet u allereerst nadenken over relationele databases in het geval dat transacties van andere dan de primaire indexen belangrijk zijn.

  • Sleutel-waarde opslag . Storages zoals Redis en Aerospike zijn beter geschikt wanneer latentie nodig is en batchverwerking minder belangrijk is.

  • Bestanden en hun verwerking met MapReduce . Als de gegevens alleen worden toegevoegd en zelden worden bijgewerkt/gewijzigd, dan kunt u beter geen gebruik maken van HBase, maar de gegevens gewoon opslaan in bestanden. Om het werken met bestanden te vereenvoudigen, kunt u tools gebruiken zoals Hive, Pig en Impala.

Het gebruik van HBase is gerechtvaardigd wanneer:

  • Er is veel data, en die passen niet op één computer/server
  • Gegevens worden regelmatig bijgewerkt en verwijderd
  • Er is een expliciete "sleutel" in de gegevens, waaraan het handig is om al het andere te binden
  • Batchverwerking nodig
  • Willekeurige toegang tot gegevens nodig met specifieke sleutels