Theorie und Praxis der Verwendung von HBase

Guten Tag! Mein Name ist Danil Lipovoy. Unser Team bei Sbertech hat begonnen, HBase als Speicher für Betriebsdaten zu verwenden. Im Laufe des Studiums haben sich Erfahrungen angesammelt, die ich systematisieren und beschreiben wollte (wir hoffen, dass sie für viele nützlich sein werden). Alle folgenden Experimente wurden mit den HBase-Versionen 1.2.0-cdh5.14.2 und 2.0.0-cdh6.0.0-beta1 durchgeführt.

  1. Allgemeine Architektur
  2. Daten in HBASE schreiben
  3. Daten aus HBASE lesen
  4. Daten-Caching
  5. Stapeldatenverarbeitung MultiGet/MultiPut
  6. Strategie zur Aufteilung von Tabellen in Regionen (Splitting)
  7. Fehlertoleranz, Kompaktifizierung und Datenlokalität
  8. Einstellungen und Leistung
  9. Belastbarkeitstest
  10. Befund

1. Allgemeine Architektur

Theorie und Praxis der Verwendung von HBase
Der Backup-Master hört auf den Heartbeat des aktiven auf dem ZooKeeper-Knoten und übernimmt im Falle seines Verschwindens die Funktionen des Masters.

2. Daten in HBASE schreiben

Schauen wir uns zunächst den einfachsten Fall an – das Schreiben eines Schlüsselwertobjekts in eine Tabelle mit put(rowkey). Der Client muss zunächst herausfinden, wo sich der Root Region Server (RRS) befindet, der die hbase:meta-Tabelle speichert. Diese Informationen erhält er von ZooKeeper. Anschließend greift es auf RRS zu und liest die hbase:meta-Tabelle, aus der es Informationen darüber extrahiert, welcher RegionServer (RS) für die Speicherung von Daten für einen bestimmten Zeilenschlüssel in der interessierenden Tabelle verantwortlich ist. Für die zukünftige Verwendung wird die Metatabelle vom Client zwischengespeichert, sodass nachfolgende Aufrufe schneller direkt an RS weitergeleitet werden.

Als nächstes schreibt RS, nachdem er eine Anfrage erhalten hat, diese zunächst in WriteAheadLog (WAL), was für die Wiederherstellung im Falle eines Absturzes erforderlich ist. Anschließend werden die Daten im MemStore gespeichert. Dies ist ein Puffer im Speicher, der einen sortierten Satz von Schlüsseln für eine bestimmte Region enthält. Eine Tabelle kann in Bereiche (Partitionen) unterteilt werden, von denen jeder einen disjunkten Satz von Schlüsseln enthält. Dadurch können Sie Regionen auf verschiedenen Servern platzieren, um eine höhere Leistung zu erzielen. Doch trotz der Offensichtlichkeit dieser Aussage werden wir später sehen, dass dies nicht in allen Fällen funktioniert.

Nach dem Platzieren eines Eintrags im MemStore wird eine Rückmeldung an den Client zurückgegeben, dass der Eintrag erfolgreich gespeichert wurde. In Wirklichkeit werden sie jedoch nur in einem Puffer gespeichert und gelangen erst nach Ablauf einer bestimmten Zeit oder wenn sie mit neuen Daten gefüllt ist, auf die Festplatte.

Theorie und Praxis der Verwendung von HBase
Beim Ausführen des Vorgangs „Löschen“ werden die Daten nicht physisch gelöscht. Sie werden einfach als gelöscht markiert und die eigentliche Zerstörung erfolgt im Moment des Aufrufs der Major-Compact-Funktion, die in Abschnitt 7 ausführlicher beschrieben wird.

Dateien im HFile-Format werden in HDFS gesammelt und von Zeit zu Zeit wird der kleinere Komprimierungsprozess gestartet, der kleine Dateien einfach zu größeren zusammenfügt, ohne etwas zu löschen. Mit der Zeit entwickelt sich daraus ein Problem, das nur beim Auslesen von Daten auftritt (wir kommen etwas später darauf zurück).

Zusätzlich zum oben beschriebenen Ladevorgang gibt es ein viel effektiveres Verfahren, das vielleicht die stärkste Seite dieser Datenbank ist – BulkLoad. Es liegt darin, dass wir unabhängig HFiles erstellen und auf die Festplatte legen, was uns eine perfekte Skalierung und sehr gute Geschwindigkeiten ermöglicht. Tatsächlich liegt die Einschränkung hier nicht bei HBase, sondern bei den Fähigkeiten der Hardware. Nachfolgend finden Sie die Startergebnisse für einen Cluster bestehend aus 16 RegionServern und 16 NodeManager YARN (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads), HBase-Version 1.2.0-cdh5.14.2.

Theorie und Praxis der Verwendung von HBase

Hier sehen Sie, dass wir durch die Erhöhung der Anzahl der Partitionen (Regionen) in der Tabelle sowie der Spark-Executoren eine Steigerung der Download-Geschwindigkeit erzielen. Außerdem hängt die Geschwindigkeit von der Aufnahmelautstärke ab. Große Blöcke erhöhen die MB/s, kleine Blöcke die Anzahl der eingefügten Datensätze pro Zeiteinheit, wenn alle anderen Bedingungen gleich bleiben.

Sie können auch mit dem Laden in zwei Tische gleichzeitig beginnen und so die Geschwindigkeit verdoppeln. Unten sehen Sie, dass das gleichzeitige Schreiben von 10-KB-Blöcken in zwei Tabellen mit einer Geschwindigkeit von jeweils etwa 600 MB/s (insgesamt 1275 MB/s) erfolgt, was mit der Geschwindigkeit des Schreibens in eine Tabelle von 623 MB/s übereinstimmt (siehe Nr. 11 oben)

Theorie und Praxis der Verwendung von HBase
Der zweite Durchlauf mit Datensätzen von 50 KB zeigt jedoch, dass die Download-Geschwindigkeit leicht zunimmt, was darauf hindeutet, dass sie sich den Grenzwerten nähert. Gleichzeitig müssen Sie bedenken, dass auf HBASE selbst praktisch keine Last entsteht. Sie müssen lediglich zuerst Daten von hbase:meta bereitstellen und nach dem Einlegen von HFiles die BlockCache-Daten zurücksetzen und speichern MemStore-Puffer auf die Festplatte, wenn er nicht leer ist.

3. Daten aus HBASE lesen

Gehen wir davon aus, dass der Client bereits über alle Informationen von hbase:meta verfügt (siehe Punkt 2), dann geht die Anfrage direkt an den RS, wo der benötigte Schlüssel gespeichert ist. Zunächst wird die Suche im MemCache durchgeführt. Unabhängig davon, ob dort Daten vorhanden sind oder nicht, erfolgt die Suche auch im BlockCache-Puffer und ggf. in HFiles. Wenn in der Datei Daten gefunden wurden, werden diese im BlockCache abgelegt und bei der nächsten Anfrage schneller zurückgegeben. Die Suche in HFile ist dank der Verwendung des Bloom-Filters relativ schnell, d. h. Nachdem es eine kleine Datenmenge gelesen hat, stellt es sofort fest, ob diese Datei den erforderlichen Schlüssel enthält, und geht, wenn nicht, mit der nächsten fort.

Theorie und Praxis der Verwendung von HBase
Nachdem RS Daten aus diesen drei Quellen erhalten hat, generiert es eine Antwort. Insbesondere können mehrere gefundene Versionen eines Objekts gleichzeitig übertragen werden, wenn der Client eine Versionierung anfordert.

4. Daten-Caching

Die MemStore- und BlockCache-Puffer belegen bis zu 80 % des zugewiesenen On-Heap-RS-Speichers (der Rest ist für RS-Dienstaufgaben reserviert). Wenn der typische Nutzungsmodus so ist, dass Prozesse dieselben Daten schreiben und sofort lesen, dann ist es sinnvoll, BlockCache zu reduzieren und MemStore zu erhöhen, weil Wenn Schreibdaten nicht zum Lesen in den Cache gelangen, wird BlockCache seltener verwendet. Der BlockCache-Puffer besteht aus zwei Teilen: LruBlockCache (immer auf dem Heap) und BucketCache (normalerweise außerhalb des Heaps oder auf einer SSD). BucketCache sollte verwendet werden, wenn viele Leseanfragen vorliegen und diese nicht in LruBlockCache passen, was zu einer aktiven Arbeit des Garbage Collectors führt. Gleichzeitig sollten Sie durch die Nutzung des Lesecaches keine radikale Leistungssteigerung erwarten, darauf kommen wir jedoch in Abschnitt 8 zurück

Theorie und Praxis der Verwendung von HBase
Es gibt einen BlockCache für den gesamten RS und einen MemStore für jede Tabelle (einen für jede Spaltenfamilie).

Как beschrieben Theoretisch gelangen die Daten beim Schreiben nicht in den Cache, und tatsächlich werden die Parameter CACHE_DATA_ON_WRITE für die Tabelle und „Cache DATA on Write“ für RS auf „false“ gesetzt. Wenn wir jedoch in der Praxis Daten in MemStore schreiben, sie dann auf die Festplatte schreiben (und somit löschen) und dann die resultierende Datei löschen, können wir die Daten durch Ausführen einer Get-Anfrage erfolgreich empfangen. Selbst wenn Sie BlockCache vollständig deaktivieren und die Tabelle mit neuen Daten füllen, dann den MemStore auf die Festplatte zurücksetzen, sie löschen und sie aus einer anderen Sitzung anfordern, werden sie dennoch von irgendwoher abgerufen. HBase speichert also nicht nur Daten, sondern auch mysteriöse Geheimnisse.

hbase(main):001:0> create 'ns:magic', 'cf'
Created table ns:magic
Took 1.1533 seconds
hbase(main):002:0> put 'ns:magic', 'key1', 'cf:c', 'try_to_delete_me'
Took 0.2610 seconds
hbase(main):003:0> flush 'ns:magic'
Took 0.6161 seconds
hdfs dfs -mv /data/hbase/data/ns/magic/* /tmp/trash
hbase(main):002:0> get 'ns:magic', 'key1'
 cf:c      timestamp=1534440690218, value=try_to_delete_me

Der Parameter „Cache DATA on Read“ ist auf „false“ gesetzt. Wenn Sie Ideen haben, können Sie diese gerne in den Kommentaren diskutieren.

5. Stapeldatenverarbeitung MultiGet/MultiPut

Die Verarbeitung einzelner Anfragen (Get/Put/Delete) ist ein recht kostspieliger Vorgang. Wenn möglich, sollten Sie sie daher in einer Liste oder Liste zusammenfassen, um eine deutliche Leistungssteigerung zu erzielen. Dies gilt insbesondere für den Schreibvorgang, beim Lesen gibt es jedoch folgende Gefahr. Die folgende Grafik zeigt die Zeit zum Lesen von 50 Datensätzen aus MemStore. Die Lesung wurde in einem Thread durchgeführt und die horizontale Achse zeigt die Anzahl der Schlüssel in der Anfrage. Hier sehen Sie, dass bei einer Erhöhung auf tausend Schlüssel in einer Anfrage die Ausführungszeit sinkt, d. h. Geschwindigkeit steigt. Wenn der MSLAB-Modus jedoch standardmäßig aktiviert ist, beginnt nach diesem Schwellenwert ein radikaler Leistungsabfall, und je größer die Datenmenge im Datensatz, desto länger die Betriebszeit.

Theorie und Praxis der Verwendung von HBase

Die Tests wurden auf einer virtuellen Maschine mit 8 Kernen und der Version HBase 2.0.0-cdh6.0.0-beta1 durchgeführt.

Der MSLAB-Modus soll die Heap-Fragmentierung reduzieren, die durch die Vermischung von Daten der neuen und alten Generation entsteht. Um dieses Problem zu umgehen, werden die Daten bei aktiviertem MSLAB in relativ kleinen Zellen (Blöcken) abgelegt und in Blöcken verarbeitet. Wenn das Volumen im angeforderten Datenpaket die zugewiesene Größe überschreitet, sinkt die Leistung daher stark. Andererseits ist das Ausschalten dieses Modus auch nicht ratsam, da es in Zeiten intensiver Datenverarbeitung zu Stopps aufgrund von GC führen kann. Eine gute Lösung ist die Vergrößerung des Zellenvolumens bei aktivem Schreiben per Put gleichzeitig mit dem Lesen. Beachten Sie, dass das Problem nicht auftritt, wenn Sie nach der Aufnahme den Flush-Befehl ausführen, der den MemStore auf die Festplatte zurücksetzt, oder wenn Sie mit BulkLoad laden. Die folgende Tabelle zeigt, dass Abfragen aus dem MemStore nach größeren (und gleichen) Datenmengen zu Verlangsamungen führen. Durch Erhöhen der Chunkgröße normalisieren wir jedoch die Verarbeitungszeit wieder.

Theorie und Praxis der Verwendung von HBase
Neben der Erhöhung der Blockgröße hilft auch die Aufteilung der Daten nach Regionen, d. h. Tischaufteilung. Dies führt dazu, dass in jeder Region weniger Anfragen eingehen, und wenn sie in eine Zelle passen, bleibt die Antwort gut.

6. Strategie zur Aufteilung von Tabellen in Regionen (Splitting)

Da es sich bei HBase um einen Schlüsselwertspeicher handelt und die Partitionierung nach Schlüssel erfolgt, ist es äußerst wichtig, die Daten gleichmäßig auf alle Regionen aufzuteilen. Wenn Sie beispielsweise eine solche Tabelle in drei Teile unterteilen, werden die Daten in drei Bereiche unterteilt:

Theorie und Praxis der Verwendung von HBase
Es kommt vor, dass dies zu einer starken Verlangsamung führt, wenn die später geladenen Daten beispielsweise wie lange Werte aussehen, von denen die meisten mit derselben Ziffer beginnen, zum Beispiel:

1000001
1000002
...
1100003

Da die Schlüssel als Byte-Array gespeichert werden, beginnen sie alle gleich und gehören zur selben Region Nr. 1, in der dieser Schlüsselbereich gespeichert ist. Es gibt mehrere Partitionierungsstrategien:

HexStringSplit – Wandelt den Schlüssel in eine hexadezimal codierte Zeichenfolge im Bereich „00000000“ => „FFFFFFFF“ um und füllt die linke Seite mit Nullen auf.

UniformSplit – Wandelt den Schlüssel in ein Byte-Array mit hexadezimaler Kodierung im Bereich „00“ => „FF“ um und füllt rechts mit Nullen auf.

Darüber hinaus können Sie einen beliebigen Bereich oder Satz von Schlüsseln für die Aufteilung angeben und die automatische Aufteilung konfigurieren. Einer der einfachsten und effektivsten Ansätze ist jedoch UniformSplit und die Verwendung der Hash-Verkettung, beispielsweise des höchstwertigen Bytepaars aus der Ausführung des Schlüssels über die CRC32(rowkey)-Funktion und dem Rowkey selbst:

Hash + Zeilenschlüssel

Dann werden alle Daten gleichmäßig auf die Regionen verteilt. Beim Lesen werden die ersten beiden Bytes einfach verworfen und der ursprüngliche Schlüssel bleibt erhalten. RS kontrolliert auch die Daten- und Schlüsselmenge in der Region und zerlegt sie bei Überschreitung der Grenzwerte automatisch in Teile.

7. Fehlertoleranz und Datenlokalität

Da für jeden Schlüsselsatz nur eine Region verantwortlich ist, besteht die Lösung für Probleme im Zusammenhang mit RS-Abstürzen oder der Außerbetriebnahme darin, alle erforderlichen Daten in HDFS zu speichern. Wenn RS fällt, erkennt der Master dies durch das Fehlen eines Heartbeats auf dem ZooKeeper-Knoten. Dann weist es die bediente Region einem anderen RS zu und da die HFiles in einem verteilten Dateisystem gespeichert sind, liest der neue Besitzer sie und stellt die Daten weiterhin bereit. Da sich einige der Daten jedoch möglicherweise im MemStore befinden und keine Zeit hatten, in HFiles zu gelangen, wird WAL, das auch in HDFS gespeichert ist, zum Wiederherstellen des Betriebsverlaufs verwendet. Nachdem die Änderungen übernommen wurden, ist RS in der Lage, auf Anfragen zu reagieren, aber der Umzug führt dazu, dass einige der Daten und die Prozesse, die sie bedienen, auf verschiedenen Knoten landen, d. h. Die Lokalität nimmt ab.

Die Lösung des Problems ist eine starke Komprimierung – dieser Vorgang verschiebt Dateien auf die dafür verantwortlichen Knoten (wo sich ihre Regionen befinden), wodurch während dieses Vorgangs die Belastung des Netzwerks und der Festplatten stark ansteigt. Zukünftig wird der Zugriff auf Daten jedoch spürbar beschleunigt. Darüber hinaus führt „major_compaction“ die Zusammenführung aller HFiles in einer Datei innerhalb einer Region durch und bereinigt außerdem Daten je nach Tabelleneinstellungen. Sie können beispielsweise die Anzahl der Versionen eines Objekts angeben, die aufbewahrt werden müssen, oder die Lebensdauer, nach der das Objekt physisch gelöscht wird.

Dieses Vorgehen kann sich sehr positiv auf den Betrieb von HBase auswirken. Das Bild unten zeigt, wie sich die Leistung aufgrund der aktiven Datenaufzeichnung verschlechtert. Hier können Sie sehen, wie 40 Threads in eine Tabelle geschrieben und 40 Threads gleichzeitig Daten gelesen haben. Schreibthreads erzeugen immer mehr HFiles, die von anderen Threads gelesen werden. Dadurch müssen immer mehr Daten aus dem Speicher entfernt werden und irgendwann fängt der GC an zu arbeiten, was praktisch alle Arbeit lahmlegt. Der Beginn einer umfassenden Verdichtung führte zur Beseitigung des entstandenen Schutts und zur Wiederherstellung der Produktivität.

Theorie und Praxis der Verwendung von HBase
Der Test wurde auf 3 DataNodes und 4 RS (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads) durchgeführt. HBase-Version 1.2.0-cdh5.14.2

Es ist erwähnenswert, dass die umfassende Komprimierung auf einer „Live“-Tabelle gestartet wurde, in die Daten aktiv geschrieben und gelesen wurden. Im Internet wurde darauf hingewiesen, dass dies beim Auslesen der Daten zu einer falschen Reaktion führen könnte. Zur Überprüfung wurde ein Prozess gestartet, der neue Daten generierte und in eine Tabelle schrieb. Danach habe ich sofort gelesen und überprüft, ob der resultierende Wert mit dem Aufgeschriebenen übereinstimmt. Während dieser Prozess ausgeführt wurde, wurde eine größere Verdichtung etwa 200 Mal durchgeführt und es wurde kein einziger Fehler aufgezeichnet. Möglicherweise tritt das Problem selten und nur bei hoher Auslastung auf. Daher ist es sicherer, die Schreib- und Lesevorgänge wie geplant zu stoppen und eine Reinigung durchzuführen, um solche GC-Entlastungen zu verhindern.

Außerdem wirkt sich eine größere Komprimierung nicht auf den Status des MemStore aus. Um ihn auf die Festplatte zu leeren und zu komprimieren, müssen Sie „flush“ (connection.getAdmin().flush(TableName.valueOf(tblName))) verwenden.

8. Einstellungen und Leistung

Wie bereits erwähnt zeigt HBase dort seinen größten Erfolg, wo es nichts tun muss, nämlich bei der Ausführung von BulkLoad. Dies gilt jedoch für die meisten Systeme und Menschen. Dieses Tool eignet sich jedoch besser zum Massenspeichern von Daten in großen Blöcken. Wenn der Prozess hingegen mehrere konkurrierende Lese- und Schreibanforderungen erfordert, werden die oben beschriebenen Get- und Put-Befehle verwendet. Um die optimalen Parameter zu ermitteln, wurden Starts mit verschiedenen Kombinationen von Tabellenparametern und Einstellungen durchgeführt:

  • 10 Threads wurden dreimal hintereinander gleichzeitig gestartet (nennen wir dies einen Thread-Block).
  • Die Betriebszeit aller Threads in einem Block wurde gemittelt und war das Endergebnis der Blockoperation.
  • Alle Threads arbeiteten mit derselben Tabelle.
  • Vor jedem Start des Thread-Blocks wurde eine größere Komprimierung durchgeführt.
  • Jeder Block führte nur eine der folgenden Operationen aus:

-Setzen
-Erhalten
– Holen+Put

  • Jeder Block führte 50 Iterationen seiner Operation durch.
  • Die Blockgröße eines Datensatzes beträgt 100 Byte, 1000 Byte oder 10000 Byte (zufällig).
  • Blöcke wurden mit unterschiedlicher Anzahl angeforderter Schlüssel gestartet (entweder ein Schlüssel oder 10).
  • Die Blöcke wurden unter verschiedenen Tabelleneinstellungen ausgeführt. Parameter geändert:

— BlockCache = aktiviert oder deaktiviert
— Blockgröße = 65 KB oder 16 KB
— Partitionen = 1, 5 oder 30
— MSLAB = aktiviert oder deaktiviert

Der Block sieht also so aus:

A. Der MSLAB-Modus wurde ein-/ausgeschaltet.
B. Es wurde eine Tabelle erstellt, für die folgende Parameter festgelegt wurden: BlockCache = true/none, BlockSize = 65/16 Kb, Partition = 1/5/30.
C. Die Komprimierung wurde auf GZ eingestellt.
D. Es wurden 10 Threads gleichzeitig gestartet, die 1/10 Put-/Get-/Get+Put-Vorgänge in dieser Tabelle mit Datensätzen von 100/1000/10000 Bytes ausführten und 50 Abfragen hintereinander (zufällige Schlüssel) durchführten.
e. Punkt d wurde dreimal wiederholt.
F. Die Betriebszeit aller Threads wurde gemittelt.

Alle möglichen Kombinationen wurden getestet. Es ist vorhersehbar, dass die Geschwindigkeit mit zunehmender Datensatzgröße abnimmt oder dass die Deaktivierung des Cachings zu einer Verlangsamung führt. Das Ziel bestand jedoch darin, den Grad und die Signifikanz des Einflusses jedes Parameters zu verstehen, weshalb die gesammelten Daten in die Eingabe einer linearen Regressionsfunktion eingespeist wurden, die es ermöglicht, die Signifikanz mithilfe der T-Statistik abzuschätzen. Nachfolgend finden Sie die Ergebnisse der Blöcke, die Put-Operationen ausführen. Vollständiger Kombinationssatz 2*2*3*2*3 = 144 Optionen + 72 tk. einige wurden zweimal gemacht. Somit gibt es insgesamt 216 Läufe:

Theorie und Praxis der Verwendung von HBase
Die Tests wurden auf einem Mini-Cluster bestehend aus 3 DataNodes und 4 RS (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads) durchgeführt. HBase-Version 1.2.0-cdh5.14.2.

Die höchste Einfügegeschwindigkeit von 3.7 Sekunden wurde bei ausgeschaltetem MSLAB-Modus, in einer Tabelle mit einer Partition, mit aktiviertem BlockCache, BlockSize = 16, Datensätzen von 100 Bytes, 10 Stück pro Packung erreicht.
Die niedrigste Einfügegeschwindigkeit von 82.8 Sekunden wurde mit aktiviertem MSLAB-Modus in einer Tabelle mit einer Partition, mit aktiviertem BlockCache, BlockSize = 16, Datensätzen von 10000 Bytes, jeweils 1, erreicht.

Schauen wir uns nun das Modell an. Wir sehen die gute Qualität des auf R2 basierenden Modells, es ist jedoch völlig klar, dass eine Extrapolation hier kontraindiziert ist. Das tatsächliche Verhalten des Systems bei Parameteränderungen ist nicht linear; dieses Modell wird nicht für Vorhersagen benötigt, sondern um zu verstehen, was innerhalb der gegebenen Parameter passiert ist. Hier sehen wir beispielsweise anhand des Student-Kriteriums, dass für die Put-Operation die Parameter BlockSize und BlockCache keine Rolle spielen (was im Allgemeinen ziemlich vorhersehbar ist):

Theorie und Praxis der Verwendung von HBase
Die Tatsache, dass eine Erhöhung der Anzahl der Partitionen zu einem Leistungsabfall führt, ist jedoch etwas unerwartet (wir haben bereits die positiven Auswirkungen einer Erhöhung der Anzahl der Partitionen mit BulkLoad gesehen), wenn auch verständlich. Erstens müssen Sie für die Verarbeitung Anfragen an 30 Regionen statt an eine generieren, und die Datenmenge ist nicht so groß, dass dies einen Gewinn bringt. Zweitens wird die Gesamtbetriebszeit durch den langsamsten RS bestimmt, und da die Anzahl der DataNodes geringer ist als die Anzahl der RSs, haben einige Regionen eine Nulllokalität. Schauen wir uns die Top XNUMX an:

Theorie und Praxis der Verwendung von HBase
Lassen Sie uns nun die Ergebnisse der Ausführung von „Get Blocks“ auswerten:

Theorie und Praxis der Verwendung von HBase
Die Anzahl der Partitionen hat an Bedeutung verloren, was wahrscheinlich darauf zurückzuführen ist, dass die Daten gut zwischengespeichert werden und der Lesecache der (statistisch) wichtigste Parameter ist. Natürlich ist die Erhöhung der Anzahl der Nachrichten in einer Anfrage auch für die Leistung sehr nützlich. Höchstpunktzahl:

Theorie und Praxis der Verwendung von HBase
Schauen wir uns zum Schluss noch das Modell des Blocks an, der zuerst get und dann put ausgeführt hat:

Theorie und Praxis der Verwendung von HBase
Alle Parameter sind hier von Bedeutung. Und die Ergebnisse der Führungskräfte:

Theorie und Praxis der Verwendung von HBase

9. Belastungstest

Nun, zum Schluss werden wir eine mehr oder weniger anständige Ladung auf den Markt bringen, aber es ist immer interessanter, wenn man etwas zum Vergleich hat. Auf der Website von DataStax, dem Hauptentwickler von Cassandra, gibt es Befund NT einer Reihe von NoSQL-Speichern, einschließlich HBase-Version 0.98.6-1. Das Laden erfolgte über 40 Threads, Datengröße 100 Byte, SSD-Festplatten. Das Ergebnis des Testens der Lese-, Änderungs- und Schreibvorgänge zeigte die folgenden Ergebnisse.

Theorie und Praxis der Verwendung von HBase
Soweit ich weiß, wurde das Lesen in Blöcken von 100 Datensätzen durchgeführt und für 16 HBase-Knoten zeigte der DataStax-Test eine Leistung von 10 Operationen pro Sekunde.

Es ist ein Glück, dass unser Cluster auch 16 Knoten hat, aber es ist kein großes „Glück“, dass jeder 64 Kerne (Threads) hat, während es im DataStax-Test nur 4 sind. Andererseits haben sie SSD-Laufwerke, während wir HDDs haben oder mehr die neue Version von HBase und die CPU-Auslastung während der Last stieg praktisch nicht wesentlich an (visuell um 5-10 Prozent). Versuchen wir jedoch, diese Konfiguration zu verwenden. Bei den Standardtabelleneinstellungen wird das Lesen im Schlüsselbereich von 0 bis 50 Millionen zufällig durchgeführt (d. h. im Wesentlichen jedes Mal neu). Die Tabelle enthält 50 Millionen Datensätze, aufgeteilt in 64 Partitionen. Die Schlüssel werden mit crc32 gehasht. Die Tabelleneinstellungen sind Standard, MSLAB ist aktiviert. Beim Starten von 40 Threads liest jeder Thread einen Satz von 100 zufälligen Schlüsseln und schreibt die generierten 100 Bytes sofort zurück in diese Schlüssel.

Theorie und Praxis der Verwendung von HBase
Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads). HBase-Version 1.2.0-cdh5.14.2.

Das durchschnittliche Ergebnis liegt näher bei 40 Operationen pro Sekunde, was deutlich besser ist als beim DataStax-Test. Zu Versuchszwecken können Sie die Bedingungen jedoch leicht ändern. Es ist ziemlich unwahrscheinlich, dass alle Arbeiten ausschließlich an einer Tabelle und auch nur an eindeutigen Schlüsseln ausgeführt werden. Nehmen wir an, dass es einen bestimmten „heißen“ Schlüsselsatz gibt, der die Hauptlast erzeugt. Versuchen wir daher, einen Ladevorgang mit größeren Datensätzen (10 KB) zu erstellen, ebenfalls in Stapeln von 100, in 4 verschiedenen Tabellen und mit einer Begrenzung des Bereichs der angeforderten Schlüssel auf 50. Die folgende Grafik zeigt den Start von 40 Threads, jeder Thread liest einen Satz von 100 Schlüsseln und schreibt sofort zufällig 10 KB auf diese Schlüssel zurück.

Theorie und Praxis der Verwendung von HBase
Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads). HBase-Version 1.2.0-cdh5.14.2.

Während des Ladevorgangs wurde, wie oben gezeigt, mehrmals eine große Verdichtung gestartet. Ohne diesen Vorgang wird die Leistung allmählich nachlassen, es entsteht jedoch auch während der Ausführung eine zusätzliche Belastung. Drawdowns werden aus verschiedenen Gründen verursacht. Manchmal beendeten die Threads ihre Arbeit und es gab eine Pause, während sie neu gestartet wurden, manchmal verursachten Anwendungen von Drittanbietern eine Belastung für den Cluster.

Lesen und sofort schreiben ist eines der schwierigsten Arbeitsszenarien für HBase. Wenn Sie nur kleine Put-Anfragen stellen, zum Beispiel 100 Bytes, und diese in Paketen von 10 bis 50 Stück kombinieren, können Sie Hunderttausende Operationen pro Sekunde erhalten, und die Situation ist bei schreibgeschützten Anfragen ähnlich. Es ist erwähnenswert, dass die Ergebnisse wesentlich besser sind als die von DataStax, was vor allem auf Anfragen in Blöcken von 50 zurückzuführen ist.

Theorie und Praxis der Verwendung von HBase
Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2.40 GHz * 64 Threads). HBase-Version 1.2.0-cdh5.14.2.

10. Schlussfolgerungen

Dieses System ist recht flexibel konfigurierbar, der Einfluss einer Vielzahl von Parametern ist jedoch noch unbekannt. Einige davon wurden getestet, waren jedoch nicht im resultierenden Testsatz enthalten. Vorläufige Experimente zeigten beispielsweise eine unbedeutende Bedeutung eines Parameters wie DATA_BLOCK_ENCODING, der Informationen mithilfe von Werten aus benachbarten Zellen kodiert, was für zufällig generierte Daten verständlich ist. Wenn Sie eine große Anzahl doppelter Objekte verwenden, kann der Gewinn erheblich sein. Im Allgemeinen können wir sagen, dass HBase den Eindruck einer recht seriösen und gut durchdachten Datenbank erweckt, die bei der Durchführung von Operationen mit großen Datenblöcken recht produktiv sein kann. Vor allem dann, wenn es gelingt, Lese- und Schreibvorgänge zeitlich zu trennen.

Wenn Ihrer Meinung nach etwas nicht ausreichend offengelegt wird, bin ich bereit, es Ihnen ausführlicher mitzuteilen. Wir laden Sie ein, Ihre Erfahrungen zu teilen oder zu diskutieren, wenn Sie mit etwas nicht einverstanden sind.

Source: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz und VPS-VDS-Servern 🔥 Kaufen Sie zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server | ProHoster