Teoria e pratica dell'uso di HBase

Buongiorno! Mi chiamo Danil Lipovoy e il nostro team in Sbertech ha iniziato a utilizzare HBase come archivio per i dati operativi. Durante i nostri studi, abbiamo accumulato esperienza che desideriamo sistematizzare e descrivere (speriamo sia utile a molti). Tutti gli esperimenti riportati di seguito sono stati condotti con le versioni HBase 1.2.0-cdh5.14.2 e 2.0.0-cdh6.0.0-beta1.

  1. Architettura generale
  2. Scrittura dei dati in HBASE
  3. Lettura dei dati da HBASE
  4. Caching dei dati
  5. Elaborazione batch dei dati MultiGet/MultiPut
  6. Strategia di suddivisione delle tabelle in regioni (sharding)
  7. Resilienza, compattazione e localizzazione dei dati
  8. Impostazioni e prestazioni
  9. Test di carico
  10. Conclusioni

1. Architettura generale

Teoria e pratica dell'uso di HBase
Il Master di riserva ascolta il heartbeat del Master attivo sul nodo ZooKeeper e, in caso di scomparsa, assume le funzioni del Master.

2. Scrittura dei dati in HBASE

Iniziamo esaminando il caso più semplice: la scrittura di un oggetto chiave-valore in una certa tabella tramite put(rowkey). Il client deve prima determinare dove si trova il server della regione radice (Root Region Server - RRS), che memorizza la tabella hbase:meta. Questa informazione viene ottenuta da ZooKeeper. Dopodiché, si rivolge al RRS e legge la tabella hbase:meta, da cui estrae le informazioni su quale RegionServer (RS) è responsabile della memorizzazione dei dati per la chiave rowkey nella tabella di interesse. Per utilizzi futuri, la tabella meta viene memorizzata nella cache dal client, e così i successivi accessi avvengono più velocemente, direttamente al RS.

Successivamente, il RS, ricevuto il comando, prima di tutto lo scrive nel WriteAheadLog (WAL), necessario per il ripristino in caso di crash. Poi salva i dati in MemStore. Questo è un buffer in memoria che contiene un insieme ordinato di chiavi di questa regione. La tabella può essere suddivisa in regioni (partizioni), ciascuna delle quali contiene un insieme di chiavi non sovrapposto. Questo consente, posizionando le regioni su server diversi, di ottenere prestazioni più elevate. Tuttavia, nonostante l'evidenza di questa affermazione, vedremo in seguito che non sempre funziona.

Dopo aver posizionato la registrazione in MemStore, al client viene restituita una risposta che indica che la registrazione è stata salvata con successo. In realtà, viene memorizzata solo nel buffer e finirà su disco solo dopo che sarà trascorso un certo intervallo di tempo o quando sarà piena di nuovi dati.

Teoria e pratica dell'uso di HBase
Nell'operazione «Delete», i dati non vengono fisicamente rimossi. Vengono semplicemente contrassegnati come eliminati, e la loro vera eliminazione avviene al momento della chiamata della funzione major compact, di cui si parla più dettagliatamente nel paragrafo 7.

I file in formato HFile si accumulano in HDFS e di tanto in tanto viene avviato il processo minor compact, che unisce semplicemente file piccoli in file più grandi, senza eliminare nulla. Col tempo, questo diventa un problema che si manifesta solo durante la lettura dei dati (ci torneremo più tardi).

Oltre al processo di caricamento descritto sopra, esiste una procedura molto più efficiente, che rappresenta probabilmente il punto di forza di questo database: il BulkLoad. Si tratta del caricamento autonomo degli HFiles direttamente su disco, il che consente di scalare in modo eccellente e raggiungere velocità molto soddisfacenti. In sostanza, il limite non è HBase, ma le capacità hardware. Di seguito sono riportati i risultati di caricamento su un cluster composto da 16 RegionServer e 16 NodeManager YARN (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread), versione HBase 1.2.0-cdh5.14.2.

Teoria e pratica dell'uso di HBase

Qui si può vedere che aumentando il numero di partizioni (regioni) nella tabella, così come gli executor Spark, otteniamo un incremento della velocità di caricamento. Anche la velocità dipende dalla quantità di scrittura. Blocchi grandi offrono un aumento in termini di MB/sec, mentre i blocchi piccoli in termini di numero di record inseriti in unità di tempo, a parità di altre condizioni.

È anche possibile avviare il caricamento in due tabelle contemporaneamente e ottenere un raddoppio della velocità. Qui si osserva che la scrittura di blocchi da 10 KB simultaneamente in due tabelle avviene a una velocità di circa 600 MB/sec ciascuna (complessivamente 1275 MB/sec), che corrisponde alla velocità di scrittura in una tabella di 623 MB/sec (vedi n. 11 sopra).

Teoria e pratica dell'uso di HBase
Tuttavia, il secondo avvio con scritture di 50 KB mostra che la velocità di caricamento cresce già in modo marginale, il che indica che ci si sta avvicinando ai valori limite. È importante notare che non viene praticamente generato alcun carico su HBase; tutto ciò che gli è richiesto è prima fornire i dati da hbase:meta, e dopo il caricamento di HFiles, svuotare i dati di BlockCache e salvare il buffer MemStore su disco, se non è vuoto.

3. Lettura dei dati da HBASE

Se consideriamo che tutte le informazioni da hbase:meta sono già disponibili per il cliente (vedi punto 2), la richiesta viene inviata direttamente al RS che conserva la chiave necessaria. Inizialmente, la ricerca avviene in MemCache. Indipendentemente dal fatto che ci siano dati o meno, la ricerca avviene anche nel buffer BlockCache e, se necessario, negli HFiles. Se i dati vengono trovati nel file, vengono collocati in BlockCache e nella richiesta successiva verranno restituiti più rapidamente. La ricerca in HFile avviene abbastanza rapidamente grazie all'uso del filtro di Bloom, cioè, leggendo un piccolo volume di dati, determina immediatamente se quel file contiene la chiave richiesta e, se non la contiene, passa al successivo.

Teoria e pratica dell'uso di HBase
Ricevuti i dati da queste tre fonti, il RS forma la risposta. In particolare, può restituire più versioni trovate dell'oggetto se il cliente richiede la versioning.

4. Caching dei dati

I buffer MemStore e BlockCache occupano fino all'80% della memoria on-heap dedicata del RS (il resto è riservato per le attività di servizio del RS). Se il modo tipico di utilizzo è tale che i processi scrivono e leggono immediatamente questi stessi dati, ha senso ridurre BlockCache e aumentare MemStore, poiché durante la scrittura i dati non vengono memorizzati nel cache di lettura, quindi l'uso di BlockCache avverrà meno frequentemente. Il buffer BlockCache è composto da due parti: LruBlockCache (sempre on-heap) e BucketCache (di solito off-heap o su SSD). È consigliabile utilizzare BucketCache quando ci sono molte richieste di lettura e non possono essere memorizzate in LruBlockCache, il che porta a un'attività intensa del Garbage Collector. Tuttavia, non ci si aspetti un aumento radicale delle prestazioni dall'uso del cache di lettura, ma ne parleremo più avanti nel punto 8.

Teoria e pratica dell'uso di HBase
BlockCache è uno per tutto il RS, mentre MemStore è unico per ogni tabella (uno per ogni Column Family).

Come è descritto In teoria, durante la scrittura i dati non vengono memorizzati nel cache e, in effetti, tali parametri CACHE_DATA_ON_WRITE per la tabella e 'Cache DATA on Write' per il RS sono impostati su false. Tuttavia, in pratica, se si scrivono dati in MemStore, poi si effettua un flush su disco (pulendo in questo modo), quindi si elimina il file risultante, eseguendo una richiesta get otteniamo comunque i dati. Inoltre, anche se si disattiva completamente BlockCache e si riempie la tabella con nuovi dati, poi si provoca un flush di MemStore su disco, si eliminano e si richiedono da un'altra sessione, i dati verranno comunque estratti da qualche parte. Quindi HBase conserva non solo i dati, ma anche misteri enigmatici.

hbase(main):001:0> crea 'ns:magic', 'cf'
Tabella ns:magic creata
Tempo impiegato 1.1533 secondi
hbase(main):002:0> metti 'ns:magic', 'key1', 'cf:c', 'provami_a_eliminare'
Tempo impiegato 0.2610 secondi
hbase(main):003:0> flush 'ns:magic'
Tempo impiegato 0.6161 secondi
hdfs dfs -mv /data/hbase/data/ns/magic/* /tmp/trash
hbase(main):002:0> ottieni 'ns:magic', 'key1'
 cf:c      timestamp=1534440690218, valore=provami_a_eliminare

Il parametro "Cache DATA on Read" è impostato su false. Se hai idee, sei il benvenuto a discuterne nei commenti.

5. Elaborazione batch di dati MultiGet/MultiPut

L'elaborazione delle richieste singole (Get/Put/Delete) è un'operazione piuttosto costosa, quindi è consigliabile unirle in un List o List, il che consente di ottenere un notevole miglioramento delle prestazioni. Questo è particolarmente vero per l'operazione di scrittura, ma quando si legge c'è il seguente problema. Nel grafico qui sotto è mostrato il tempo di lettura di 50.000 record da MemStore. La lettura è stata eseguita in un singolo thread e sull'asse orizzontale è mostrato il numero di chiavi nella richiesta. Qui si vede che aumentando fino a mille chiavi in una sola richiesta, il tempo di esecuzione diminuisce, cioè la velocità aumenta. Tuttavia, con la modalità MSLAB abilitata per impostazione predefinita, dopo questa soglia si verifica un drastico calo delle prestazioni, e più grande è il volume dei dati nel record, più lungo è il tempo di lavoro.

Teoria e pratica dell'uso di HBase

I test sono stati eseguiti su una macchina virtuale, 8 core, versione HBase 2.0.0-cdh6.0.0-beta1.

La modalità MSLAB è progettata per ridurre la frammentazione dell'heap, che si verifica a causa della mescolanza di dati di nuove e vecchie generazioni. Come soluzione al problema, quando MSLAB è abilitato, i dati vengono collocati in celle (chunk) relativamente piccole e vengono elaborati a porzioni. Di conseguenza, quando il volume nel pacchetto dati richiesto supera la dimensione assegnata, le prestazioni diminuiscono drasticamente. D'altro canto, disabilitare questa modalità non è desiderabile, poiché porterà a interruzioni a causa di GC nei momenti di intenso lavoro con i dati. Una buona soluzione è aumentare la dimensione delle celle, nel caso di scritture attive tramite put contemporaneamente alla lettura. È importante notare che il problema non si verifica se dopo la scrittura viene eseguito il comando flush, che scarica MemStore su disco, o se si esegue il caricamento tramite BulkLoad. Nella tabella sottostante è mostrato che le richieste da MemStore di dati di dimensioni maggiori (e numero uguale) portano a un rallentamento. Tuttavia, aumentando la chunksize, riportiamo il tempo di elaborazione alla normalità.

Teoria e pratica dell'uso di HBase
Oltre all'aumento del chunksize, aiuta anche la suddivisione dei dati per regioni, ovvero il partizionamento delle tabelle. Questo porta a una minore quantità di richieste per ogni regione e, se inserite in una cella, la risposta rimane buona.

6. Strategia di partizionamento delle tabelle per regioni (partitioning)

Poiché HBase è un archivio key-value e la partizione avviene per chiave, è fondamentale distribuire i dati uniformemente su tutte le regioni. Ad esempio, la partizione di una tabella in tre parti porterà a una divisione dei dati in tre regioni:

Teoria e pratica dell'uso di HBase
A volte, ciò può portare a un rallentamento significativo, se i dati caricati in seguito sono per esempio valori long che iniziano nella maggior parte dei casi con la stessa cifra, ad esempio:

1000001
1000002

1100003

Poiché le chiavi sono memorizzate come array di byte, tutte inizieranno allo stesso modo e si riferiranno a una regione #1 che memorizza questo intervallo di chiavi. Esistono diverse strategie di partizionamento:

HexStringSplit – Trasforma la chiave in una stringa con codifica esadecimale nell'intervallo "00000000" => "FFFFFFFF" riempiendo a sinistra con zeri.

UniformSplit – Trasforma la chiave in un array di byte con codifica esadecimale nell'intervallo "00" => "FF" riempiendo a destra con zeri.

Inoltre, è possibile specificare qualsiasi intervallo o insieme di chiavi per la partizione e configurare l'auto-partizionamento. Tuttavia, uno degli approcci più semplici ed efficaci è UniformSplit e l'uso della concatenazione dell'hash, ad esempio la coppia di byte più significativa derivante dall'elaborazione della chiave tramite la funzione CRC32(rowkey) e la chiave stessa:

hash + rowkey

In questo modo, tutti i dati saranno distribuiti uniformemente su tutte le regioni. Durante la lettura, i primi due byte vengono semplicemente scartati e rimane la chiave originale. Inoltre, il RS controlla la quantità di dati e chiavi nella regione e, al superamento dei limiti, la suddivide automaticamente.

7. Tolleranza ai guasti e località dei dati

Poiché ogni set di chiavi è gestito solo da una regione, la soluzione ai problemi legati alle cadute di RS o all'uscita di esercizio è conservare tutti i dati necessari in HDFS. Quando un RS cade, il master lo rileva tramite l'assenza del segnale di heartbeat sul nodo ZooKeeper. Allora assegna la regione a un altro RS e, poiché gli HFiles sono conservati nel file system distribuito, il nuovo proprietario li legge e continua a gestire i dati. Tuttavia, poiché parte dei dati potrebbe trovarsi in MemStore e non è ancora stata trasferita in HFiles, per recuperare la storia delle operazioni si utilizza WAL, che è anch'esso conservato in HDFS. Dopo aver applicato le modifiche, l'RS è in grado di rispondere alle richieste, ma il trasferimento comporta che parte dei dati e i processi che li gestiscono si trovino su nodi diversi, riducendo così la locality.

La soluzione al problema è la major compaction: questa procedura sposta i file sui nodi a cui sono assegnati (dove si trovano le loro regioni), il che provoca un aumento drastico del carico sulla rete e sui dischi durante questa procedura. Tuttavia, in seguito, l'accesso ai dati è notevolmente accelerato. Inoltre, la major_compaction unisce tutti gli HFiles in un unico file all'interno della regione e pulisce i dati in base alle impostazioni della tabella. Ad esempio, è possibile impostare il numero di versioni dell'oggetto da mantenere o il tempo di vita dopo il quale l'oggetto viene fisicamente eliminato.

Questa procedura può avere un impatto molto positivo sul funzionamento di HBase. Nella figura sottostante si può vedere come la performance sia degradata a causa di scritture attive di dati. Qui si nota come 40 thread stessero scrivendo in una tabella e 40 thread leggessero simultaneamente i dati. I thread di scrittura generano sempre più HFiles, che vengono letti da altri thread. Di conseguenza, occorre eliminare sempre più dati dalla memoria e alla fine inizia a funzionare il GC, che paralizza praticamente tutto il lavoro. L'avvio della major compaction ha portato alla pulizia dei cumuli formatisi e al ripristino della performance.

Teoria e pratica dell'uso di HBase
Il test è stato eseguito su 3 DataNode e 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Versione di HBase 1.2.0-cdh5.14.2

È importante notare che l'esecuzione della major compaction è avvenuta su una tabella "live", in cui venivano scritti e letti dati attivamente. Si è affermato in rete che questo potrebbe portare a risposte errate durante la lettura dei dati. Per verificare, è stato avviato un processo che generava nuovi dati e li scriveva nella tabella. Dopodiché, venivano subito letti e confrontati per vedere se il valore ottenuto corrispondeva a quello registrato. Durante il funzionamento di questo processo, la major compaction è stata eseguita circa 200 volte senza che si registrassero errori. È possibile che il problema si manifesti raramente e solo durante un carico elevato, quindi è più sicuro interrompere pianificatamente i processi di scrittura e lettura e eseguire la pulizia evitando tali cali del GC.

Inoltre, la major compaction non influisce sullo stato di MemStore; per il suo svuotamento su disco e la compattazione è necessario utilizzare flush (connection.getAdmin().flush(TableName.valueOf(tblName))).

8. Impostazioni e prestazioni

Come già detto, HBase ha il maggiore successo dove non deve fare nulla durante l'esecuzione di BulkLoad. In effetti, questo vale per la maggior parte dei sistemi e delle persone. Tuttavia, questo strumento è più adatto per la disposizione massiva di dati in grandi blocchi, mentre se il processo richiede l'esecuzione di molte richieste concorrenti di lettura e scrittura, si utilizzano i comandi Get e Put descritti sopra. Per determinare i parametri ottimali, sono stati effettuati avvii con diverse combinazioni di parametri delle tabelle e impostazioni:

  • Sono stati avviati 10 thread contemporaneamente per 3 volte di fila (chiamiamolo blocco di thread).
  • Il tempo di esecuzione di tutti i thread nel blocco è stato mediato e rappresentava il risultato finale del lavoro del blocco.
  • Tutti i thread hanno lavorato sulla stessa tabella.
  • Prima di ogni avvio del blocco di thread è stata eseguita una major compaction.
  • Ogni blocco ha eseguito solo una delle seguenti operazioni:

— Put
— Get
— Get+Put

  • Ogni blocco ha eseguito 50.000 ripetizioni della sua operazione.
  • La dimensione della registrazione nel blocco era di 100 byte, 1000 byte o 10.000 byte (random).
  • I blocchi venivano avviati con un numero variabile di chiavi richieste (o una chiave o 10).
  • I blocchi venivano eseguiti con diverse impostazioni della tabella. Sono stati modificati i parametri:

— BlockCache = acceso o spento
— BlockSize = 65 Kb o 16 Kb
— Partizioni = 1, 5 o 30
— MSLAB = acceso o spento

Pertanto, il blocco appare così:

a. La modalità MSLAB veniva accesa/spenta.
b. È stata creata una tabella a cui sono stati impostati i seguenti parametri: BlockCache = true/none, BlockSize = 65/16 Kb, Partizioni = 1/5/30.
c. È stata impostata la compressione GZ.
d. Sono stati avviati 10 thread che eseguivano simultaneamente 1/10 operazioni put/get/get+put su questa tabella, utilizzando record di 100/1000/10000 byte, effettuando 50.000 richieste consecutive (chiavi casuali).
e. Il punto d è stato ripetuto tre volte.
f. Il tempo di esecuzione di tutti i thread è stato mediato.

Sono state verificate tutte le possibili combinazioni. È prevedibile che l'aumento della dimensione del record comporti una diminuzione della velocità o che la disattivazione della cache porti a un rallentamento. Tuttavia, l'obiettivo era comprendere la misura e l'importanza dell'influenza di ciascun parametro, quindi i dati raccolti sono stati forniti come input a una funzione di regressione lineare, che consente di valutare l'affidabilità tramite t-statistica. Di seguito sono riportati i risultati delle operazioni di Put. L'insieme completo di combinazioni 2*2*3*2*3 = 144 varianti + 72 poiché alcune sono state eseguite due volte. Pertanto, il totale è di 216 esecuzioni.

Teoria e pratica dell'uso di HBase
Il test è stato eseguito su un mini-cluster composto da 3 DataNode e 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Versione HBase 1.2.0-cdh5.14.2.

La massima velocità di inserimento di 3,7 secondi è stata ottenuta con la modalità MSLAB disattivata, su una tabella con una sola partizione, con BlockCache attivato, BlockSize = 16, record di 100 byte in pacchetti da 10.
La minima velocità di inserimento di 82,8 secondi è stata ottenuta con la modalità MSLAB attivata, su una tabella con una sola partizione, con BlockCache attivato, BlockSize = 16, record di 10000 byte uno alla volta.

Ora diamo un'occhiata al modello. Vediamo una buona qualità del modello in base all'R2, ma è chiaramente evidente che l'estrapolazione qui è sconsigliata. Il comportamento reale del sistema alla variazione dei parametri sarà non lineare, questo modello è necessario non per previsioni, ma per comprendere cosa sia successo entro i parametri definiti. Ad esempio, qui vediamo che secondo il criterio di Student, per l'operazione Put non hanno rilevanza i parametri BlockSize e BlockCache (cosa che è del tutto prevedibile):

Teoria e pratica dell'uso di HBase
Tuttavia, il fatto che l'aumento del numero di partizioni porti a una diminuzione delle prestazioni è piuttosto inaspettato (abbiamo già osservato l'impatto positivo dell'aumento del numero di partizioni durante il BulkLoad), sebbene sia comprensibile. In primo luogo, per la lavorazione è necessario formare richieste a 30 regioni invece di una, e il volume dei dati non è tale da generare un guadagno. In secondo luogo, il tempo totale di esecuzione è determinato dal RS più lento; e poiché il numero di DataNode è inferiore al numero di RS, alcune regioni hanno località nulla. Ora diamo un'occhiata ai cinque leader:

Teoria e pratica dell'uso di HBase
Adesso valutiamo i risultati dell'esecuzione dei blocchi Get:

Teoria e pratica dell'uso di HBase
Il numero di partizioni ha perso significato, il che probabilmente si spiega con il fatto che i dati vengono ben memorizzati nella cache e la cache per la lettura è il parametro più significativo (statisticamente). Ovviamente, anche un aumento del numero di messaggi nella richiesta è molto utile per le prestazioni. I migliori risultati:

Teoria e pratica dell'uso di HBase
Infine, diamo un'occhiata al modello di blocco che ha eseguito prima get e poi put:

Teoria e pratica dell'uso di HBase
Qui tutti i parametri sono significativi. Ecco i risultati dei leader:

Teoria e pratica dell'uso di HBase

9. Test di carico

Infine, eseguiamo un carico ragionevolmente sostanzioso, ma è sempre più interessante quando c'è qualcosa con cui confrontarsi. Sul sito di DataStax, principale sviluppatore di Cassandra, ci sono i risultati NT di vari archivi NoSQL, tra cui HBase versione 0.98.6-1. Il caricamento è stato effettuato con 40 thread, dimensione dei dati 100 byte, dischi SSD. I risultati del test delle operazioni Read-Modify-Write hanno mostrato i seguenti risultati.

Teoria e pratica dell'uso di HBase
Da quello che ho capito, la lettura è stata effettuata a blocchi di 100 registrazioni e per 16 nodi, il test di DataStax per HBase ha mostrato una prestazione di 10.000 operazioni al secondo.

È fortunato che anche nel nostro cluster ci siano 16 nodi, ma non è molto „fortunato“ che ognuno di essi abbia 64 core (thread), mentre nel test di DataStax ce n'erano solo 4. D'altra parte, loro hanno dischi SSD, mentre noi abbiamo HDD e una versione più recente di HBase, e l'utilizzo della CPU durante il carico aumentava praticamente in modo non significativo (visivamente del 5-10 percento). Tuttavia, proviamo a partire con questa configurazione. Le impostazioni delle tabelle sono predefinite, la lettura viene effettuata nell'intervallo delle chiavi da 0 a 50 milioni in modo casuale (ossia, ogni volta un nuovo). Nella tabella ci sono 50 milioni di record, suddivisi in 64 partizioni. Le chiavi sono hashate tramite crc32. Le impostazioni delle tabelle sono predefinite, MSLAB è attivo. Avviamo 40 thread, ciascun thread legge un insieme di 100 chiavi casuali e subito scrive 100 byte generati su queste chiavi.

Teoria e pratica dell'uso di HBase
Setup: 16 DataNode e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Versione HBase 1.2.0-cdh5.14.2.

Il risultato medio si avvicina a 40 mila operazioni al secondo, il che è significativamente meglio rispetto al test di DataStax. Tuttavia, per scopi sperimentali possiamo modificare leggermente le condizioni. È piuttosto improbabile che tutto il lavoro venga eseguito esclusivamente su una sola tabella, e solo con chiavi uniche. Supponiamo che ci sia un certo insieme di chiavi „calde“ che genera il carico principale. Proveremo quindi a creare un carico con record più grandi (10 KB), anche in batch da 100, in 4 tabelle diverse, limitando l'intervallo delle chiavi richieste a 50 mila. Nel grafico sottostante è mostrato l'avvio di 40 thread, ciascun thread legge un insieme di 100 chiavi e immediatamente riscrive 10 KB casuali su queste chiavi.

Teoria e pratica dell'uso di HBase
Setup: 16 DataNode e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Versione HBase 1.2.0-cdh5.14.2.

Durante il carico è stata eseguita più volte la major compaction, come mostrato sopra, senza questa procedura le prestazioni degraderebbero gradualmente, tuttavia durante l'esecuzione si genera anche un carico aggiuntivo. I cali di prestazioni sono causati da diverse ragioni. A volte i thread terminavano il lavoro e, mentre venivano riavviati, si verificava una pausa; altre volte applicazioni esterne creavano carico sul cluster.

La lettura e la scrittura simultanee rappresentano uno degli scenari più complessi per HBase. Se si eseguono solo richieste di tipo put di piccole dimensioni, ad esempio di 100 byte, raggruppandole in pacchetti di 10-50.000 unità, si possono ottenere centinaia di migliaia di operazioni al secondo, e lo stesso vale per le richieste di sola lettura. È importante notare che i risultati sono radicalmente migliori rispetto a quelli ottenuti da DataStax, soprattutto grazie alle richieste in blocco da 50.000.

Teoria e pratica dell'uso di HBase
Setup: 16 DataNode e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 thread). Versione HBase 1.2.0-cdh5.14.2.

10. Conclusioni

Questo sistema è abbastanza flessibile, tuttavia l'impatto di un gran numero di parametri rimane ancora sconosciuto. Parte di essi è stata testata, ma non è stata inclusa nel set di risultati. Ad esempio, esperimenti preliminari hanno mostrato una significativa insignificanza di un parametro come DATA_BLOCK_ENCODING, che codifica le informazioni utilizzando i valori delle celle adiacenti, il che è abbastanza comprensibile per i dati generati casualmente. In caso di utilizzo di un grande numero di oggetti ripetuti, il guadagno può essere significativo. In generale, si può dire che HBase dà l'impressione di essere un database piuttosto serio e ben progettato, che può essere molto performante nelle operazioni con grandi blocchi di dati. Soprattutto se esiste la possibilità di temporizzare i processi di lettura e scrittura.

Se qualcosa non è sufficientemente chiaro, sono disponibile a fornire ulteriori dettagli. Ti invitiamo a condividere la tua esperienza o a discutere se non sei d'accordo su qualche punto.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster