6.1 Cine a inventat HBase și de ce

În această prelegere, vom vorbi despre un instrument atât de minunat precum Hbase, care a câștigat recent o mare popularitate: de exemplu, Facebook îl folosește ca bază a sistemului său de mesagerie, iar acest lucru spune deja multe.

Conferința va vorbi despre conceptul de Big Table și implementarea sa gratuită, caracteristicile de lucru și diferența față de bazele de date relaționale clasice (cum ar fi MySQL și Oracle) și stocarea cheie-valoare precum Redis, Aerospike și memcached. Ca de obicei, să începem cu istoricul problemei. Ca multe alte proiecte BigData, Hbase s-a născut dintr-un concept care a fost dezvoltat de Google. Principiile din spatele Hbase au fost descrise în articolul Bigtable: A Distributed Storage System for Structured Data .

Așa cum am discutat în prelegerile anterioare, fișierele obișnuite sunt destul de potrivite pentru procesarea datelor în lot folosind paradigma MapReduce. Pe de altă parte, informațiile stocate în fișiere sunt destul de incomod de actualizat; Fișierele sunt, de asemenea, private de posibilitatea de acces aleatoriu. Pentru o muncă rapidă și convenabilă cu acces aleatoriu, există o clasă de sisteme nosql, cum ar fi stocarea cheie-valoare, precum Aerospike, Redis, Couchbase, Memcached. Cu toate acestea, procesarea în lot este de obicei foarte incomod în aceste sisteme. Hbase este o încercare de a combina confortul procesării loturilor cu confortul actualizării și accesului aleatoriu.

6.2 Model de date

HBase este o bază de date distribuită, orientată pe coloane, cu mai multe versiuni cheie-valoare.

  • Datele sunt organizate în tabele indexate de o cheie primară numită RowKey în Hbase.
  • Pentru fiecare cheie RowKey, poate fi stocat un set nelimitat de atribute (sau coloane).
  • Coloanele sunt organizate în grupuri de coloane numite Familie de coloane. De regulă, coloanele care au același model de utilizare și stocare sunt combinate într-o singură familie de coloane.
  • Pentru fiecare atribut, pot fi stocate mai multe versiuni diferite. Versiunile diferite au marcaj de timp diferit.

Înregistrările sunt stocate fizic în ordinea sortată RowKey. În acest caz, datele corespunzătoare diferitelor familii de coloane sunt stocate separat, ceea ce permite, dacă este necesar, citirea datelor numai din familia de coloane dorită.

Când un anumit atribut este șters, acesta nu este șters fizic imediat, ci este doar marcat cu un steag special de piatră funerară. Ștergerea fizică a datelor va avea loc ulterior, când se efectuează operația de compactare majoră.

Atributele care aparțin aceluiași grup de coloane și care corespund aceleiași chei sunt stocate fizic ca o listă sortată. Orice atribut poate fi absent sau prezent pentru fiecare cheie, iar dacă atributul este absent, acest lucru nu provoacă suprasarcina de stocare a valorilor goale.

Numele listelor și grupurilor de coloane sunt fixe și au un aspect clar. La nivel de grup de coloane, sunt setați parametri precum timpul de viață (TTL) și numărul maxim de versiuni stocate. Dacă diferența dintre marcajul de timp pentru o anumită versiune și ora curentă este mai mare decât TTL, intrarea este marcată pentru ștergere. Dacă numărul de versiuni pentru un anumit atribut depășește numărul maxim de versiuni, înregistrarea este de asemenea marcată pentru ștergere.

Modelul de date Hbase poate fi reținut ca o potrivire cheie-valoare:

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

6.3 Operațiuni suportate

Lista operațiunilor acceptate în hbase este destul de simplă. Sunt suportate 4 operațiuni principale:

  • Put : adaugă o nouă intrare la hbase. Marca temporală a acestei intrări poate fi setată manual, altfel va fi setată automat la ora curentă.
  • Obține : Obține date pentru o anumită RowKey. Puteți specifica Familia de coloane din care vom lua datele și numărul de versiuni pe care dorim să le citim.
  • Scanare : citiți înregistrările una câte una. Puteti specifica inregistrarea din care incepem citirea, inregistrarea catre care sa citim, numarul de inregistrari de citit, Familia de Coloane din care se va efectua citirea si numarul maxim de versiuni pentru fiecare inregistrare.
  • Ștergere : Marcați o anumită versiune pentru ștergere. Nu va exista ștergere fizică, va fi amânată până la următoarea Compactare Majoră (vezi mai jos).

6.4 Arhitectură

HBase este o bază de date distribuită care poate rula pe zeci sau sute de servere fizice, asigurând funcționarea neîntreruptă chiar dacă unele dintre ele eșuează. Prin urmare, arhitectura HBase este destul de complexă în comparație cu bazele de date relaționale clasice.

HBase utilizează două procese principale pentru activitatea sa:

1. Server de regiune - Deservește una sau mai multe regiuni. O regiune este un interval de înregistrări care corespunde unui interval specific de taste de rând consecutive. Fiecare regiune conține:

  • Stocarea persistentă este principala stocare a datelor în HBase. Datele sunt stocate fizic pe HDFS, într-un format special HFile. Datele din HFile sunt stocate în ordinea sortată RowKey. O pereche (regiune, familie de coloane) corespunde cel puțin unui fișier HFI.
  • MemStore - tampon de scriere. Deoarece datele sunt stocate în HFile d în ordine sortată, este destul de costisitor să actualizați HFile pe înregistrare. În schimb, la scriere, datele intră într-o zonă specială de memorie MemStore, unde se acumulează de ceva timp. Când MemStore este umplut până la o valoare critică, datele sunt scrise într-un nou fișier HF.
  • BlockCache - cache pentru citire. Vă permite să economisiți timp semnificativ pe datele care sunt citite frecvent.
  • Write Ahead Log (WAL) . Deoarece datele sunt scrise în memstore, există un anumit risc de pierdere a datelor din cauza unui accident. Pentru a preveni acest lucru, toate operațiunile înainte de implementarea efectivă a manipulărilor se încadrează într-un fișier jurnal special. Acest lucru vă permite să recuperați datele după orice eșec.

2. Master Server - serverul principal din clusterul HBase. Maestrul gestionează distribuția regiunilor între serverele de regiune, menține un registru al regiunilor, gestionează lansarea sarcinilor obișnuite și face alte lucrări utile.

Pentru a coordona acțiunile între servicii, HBase folosește Apache ZooKeeper, un serviciu special conceput pentru a gestiona configurațiile și sincronizarea serviciilor.

Când cantitatea de date din regiune crește și atinge o anumită dimensiune, Hbase începe să divizeze, o operațiune care împarte regiunea cu 2. Pentru a evita divizarea constantă a regiunilor, puteți pre-seta limitele regiunilor și crește maximul acestora. mărimea.

Deoarece datele pentru o regiune pot fi stocate în mai multe fișiere HF, Hbase le îmbină periodic pentru a accelera munca. Această operație se numește compactare în Hbase. Compactările sunt de două tipuri:

  • Compactare minoră . Pornește automat, rulează în fundal. Are o prioritate scăzută în comparație cu alte operațiuni Hbase.
  • Compactare majoră . Este lansat manual sau la apariția anumitor declanșatori (de exemplu, de un cronometru). Are o prioritate mare și poate încetini semnificativ clusterul. Compactările majore se fac cel mai bine într-un moment în care sarcina pe cluster este mică. Major Compact șterge fizic și datele marcate anterior cu piatră funerară.

6.5 Modalități de a lucra cu HBase

Shell HBase

Cel mai simplu mod de a începe cu Hbase este să utilizați utilitarul shell hbase. Este disponibil imediat după instalarea hbase pe orice nod de cluster hbase.

Shell Hbase este o consolă jruby cu suport încorporat pentru toate operațiunile de bază Hbase. Următorul este un exemplu de creare a unui tabel de utilizatori cu două familii de coloane, efectuând câteva manipulări asupra acestuia și aruncând tabelul la sfârșit în shell hbase:

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'

API nativ

La fel ca majoritatea altor proiecte legate de hadoop, hbase este implementat în java, astfel încât API-ul nativ este disponibil în Java. API-ul nativ este destul de bine documentat pe site-ul oficial. Iată un exemplu de utilizare a API-ului Hbase luat de acolo:

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

Thrift, REST și suport pentru alte limbaje de programare

Pentru a funcționa din alte limbaje de programare, Hbase oferă API-ul Thrift și API-ul Rest. Pe baza acestora, clienții sunt construiți pentru toate limbajele de programare majore: python, PHP, Java Script etc.

6.6 Unele caracteristici ale lucrului cu HBase

  1. Hbase se integrează imediat cu MapReduce și poate fi folosit ca intrare și ieșire folosind TableInputFormat și TableOutputFormat.

  2. Este foarte important să alegeți RowKey potrivit. RowKey trebuie să ofere o distribuție bună uniformă între regiuni, altfel există riscul așa-numitelor „regiuni fierbinți” - regiuni care sunt folosite mult mai des decât altele, ceea ce duce la utilizarea ineficientă a resurselor sistemului.

  3. Dacă datele nu sunt încărcate individual, ci imediat în loturi mari, Hbase acceptă un mecanism special BulkLoad care vă permite să încărcați date mult mai rapid decât folosind Put-uri unice. BulkLoad este în esență o operațiune în doi pași:

    • Formarea HFile fără participarea puturilor folosind un job special MapReduce
    • Inserarea acestor fișiere direct în Hbase
  4. Hbase acceptă transmiterea valorilor sale către serverul de monitorizare Ganglia. Acest lucru poate fi foarte util atunci când administrați Hbase pentru a ajunge la fundul problemelor hbase.

cheie rând

RowKey este ID-ul utilizatorului, care este un GUUID, un șir special generat pentru a fi unic la nivel mondial. GUUID-urile sunt distribuite uniform, ceea ce oferă o bună distribuție a datelor între servere.

Familia de coloană

Stocarea noastră folosește două familii de coloane:

  • date. Acest grup de coloane stochează date care nu mai sunt relevante pentru scopuri publicitare, cum ar fi faptul că un utilizator a vizitat anumite adrese URL. TTL pentru această familie de coloane este setat la 2 luni, limita numărului de versiuni este de 2000.
  • longdata. Acest grup de coloane stochează date care nu își pierd relevanța în timp, cum ar fi sexul, data nașterii și alte caracteristici „eterne” ale utilizatorului.

difuzoare

Fiecare tip de informații despre utilizator este stocat într-o coloană separată. De exemplu, coloana Data:_v stochează adresele URL vizitate de utilizator, iar coloana LongData:gender stochează sexul utilizatorului.

Marca temporală a acestui fapt este stocată ca marca temporală. De exemplu, în coloana Data:_v, marcajul de timp este momentul în care utilizatorul a accesat o anumită adresă URL.

Această structură de stocare a datelor utilizatorilor se potrivește foarte bine cu modelul nostru de utilizare și vă permite să actualizați rapid datele despre utilizatori, să obțineți rapid toate informațiile necesare despre utilizatori și, folosind MapReduce, să procesați rapid datele despre toți utilizatorii simultan.

6.7 Alternative

HBase este destul de complex de administrat și utilizat, așa că înainte de a utiliza HBase este logic să analizăm alternativele:

  • Baze de date relaționale . O alternativă foarte bună, mai ales în cazul în care datele se potrivesc pe o singură mașină. De asemenea, în primul rând, ar trebui să vă gândiți la bazele de date relaționale în cazul în care tranzacțiile cu alți indici decât cei primari sunt importante.

  • Stocare cheie-valoare . Stocarele precum Redis și Aerospike sunt mai potrivite atunci când este nevoie de latență și procesarea loturilor este mai puțin importantă.

  • Fișierele și procesarea lor cu MapReduce . Dacă datele sunt doar adăugate și actualizate/modificate rar, atunci este mai bine să nu utilizați HBase, ci pur și simplu să stocați datele în fișiere. Pentru a simplifica munca cu fișierele, puteți utiliza instrumente precum Hive, Pig și Impala.

Utilizarea HBase este justificată atunci când:

  • Există o mulțime de date și nu se potrivesc pe un singur computer/server
  • Datele sunt actualizate și șterse frecvent
  • Există o „cheie” explicită în date, la care este convenabil să legați orice altceva
  • Necesită procesare în lot
  • Aveți nevoie de acces aleatoriu la date prin anumite chei