Guten Tag! Mein Name ist Danil Lipova, unser Team in Sbertech hat begonnen, HBase als Repository für Betriebsdaten zu verwenden. Während seines Studiums wurden Erfahrungen gesammelt, die ich systematisieren und beschreiben wollte (wir hoffen, dass dies für viele nützlich sein wird). Alle folgenden Experimente wurden mit Versionen von HBase 1.2.0-cdh5.14.2 und 2.0.0-cdh6.0.0-beta1 durchgeführt.
- Allgemeine Architektur
- Daten in HBASE schreiben
- Daten aus HBASE lesen
- Daten-Caching
- Stapelverarbeitung MultiGet / MultiPut
- Strategie zum Aufteilen von Tabellen in Regionen (Verschütten)
- Fehlertoleranz, Verdichtung und Datenlokalität
- Einstellungen und Leistung
- Lasttest
- Schlussfolgerungen
1. Allgemeine Architektur
Der Standby-Master hört den aktiven Herzschlag auf dem ZooKeeper-Knoten und übernimmt im Falle eines Verschwindens die Funktionen des Masters.
2. Daten in HBASE schreiben
Betrachten Sie zunächst den einfachsten Fall: Schreiben eines Schlüsselwertobjekts in eine bestimmte Tabelle mit put (Zeilenschlüssel). Der Client muss zuerst herausfinden, wo sich der Root-Region-Server (RRS) befindet, auf dem die Meta-Tabelle hbase: gespeichert ist. Er erhält diese Informationen von ZooKeeper. Dann wendet er sich an RRS und liest die Tabelle hbase: meta, aus der er die Informationen abruft, für die RegionServer (RS) verantwortlich ist, um Daten für den angegebenen Zeilenschlüssel in der für ihn interessanten Tabelle zu speichern. Für die zukünftige Verwendung wird die Metatabelle vom Client zwischengespeichert, und nachfolgende Aufrufe werden daher schneller direkt an RS weitergeleitet.
Nachdem RS die Anforderung erhalten hat, schreibt er sie zunächst in WriteAheadLog (WAL), das 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. Die Tabelle kann in Regionen (Partitionen) unterteilt werden, von denen jede einen disjunkten Satz von Schlüsseln enthält. Dies ermöglicht das Platzieren von Regionen auf verschiedenen Servern, um eine höhere Leistung zu erzielen. Trotz der Offensichtlichkeit dieser Aussage werden wir später sehen, dass dies nicht in allen Fällen funktioniert.
Nach dem Platzieren des Datensatzes in MemStore erhält der Client eine Antwort, dass der Datensatz erfolgreich gespeichert wurde. Gleichzeitig wird es wirklich nur im Puffer gespeichert und gelangt erst nach Ablauf einer bestimmten Zeit oder wenn es mit neuen Daten gefüllt ist, auf die Festplatte.
Bei der Ausführung des Löschvorgangs wird keine physische Datenlöschung durchgeführt. Sie werden einfach als gelöscht markiert, und die Zerstörung selbst tritt auf, wenn die Hauptkompaktfunktion aufgerufen wird, die in Abschnitt 7 ausführlicher beschrieben wird.
Dateien im HFile-Format werden in HDFS gesammelt, und von Zeit zu Zeit beginnt der kleinere Kompaktprozess, bei dem kleine Dateien einfach in größere Dateien eingeklebt werden, ohne dass etwas gelöscht wird. Im Laufe der Zeit wird dies zu einem Problem, das sich nur beim Lesen von Daten manifestiert (wir werden später darauf zurückkommen).
Zusätzlich zu dem oben beschriebenen Startvorgang gibt es ein viel effizienteres Verfahren, das wahrscheinlich die leistungsstärkste Seite dieser Datenbank ist - BulkLoad. Es besteht darin, dass wir HFiles unabhängig voneinander erstellen und auf die Festplatte legen, wodurch wir perfekt skalieren und sehr anständige Geschwindigkeiten erreichen können. In der Tat ist die Einschränkung hier nicht HBase, sondern die Möglichkeiten von Eisen. Nachfolgend sind die Ergebnisse des Ladens in einen Cluster bestehend aus 16 RegionServern und 16 NodeManager YARN (CPU Xeon E5-2680 v4 bei 2,40 GHz * 64 Threads), Version HBase 1.2.0-cdh5.14.2, aufgeführt.

Es ist ersichtlich, dass durch Erhöhen der Anzahl der Partitionen (Regionen) in der Tabelle sowie der ausführbaren Dateien Spark die Download-Geschwindigkeit erhöht wird. Die Geschwindigkeit hängt auch von der Aufnahmemenge ab. Große Blöcke erhöhen die Messung von MB / s, kleine Blöcke die Anzahl der eingefügten Datensätze pro Zeiteinheit, alle anderen Dinge sind gleich.
Sie können auch gleichzeitig in zwei Tabellen laden und die Geschwindigkeit verdoppeln. Es ist unten zu sehen, dass 10-KB-Blöcke mit einer Geschwindigkeit von jeweils etwa 600 Mbit / s (insgesamt 1275 Mbit / s) gleichzeitig in zwei Tabellen geschrieben werden, was mit der Schreibgeschwindigkeit von 623 MB / s in eine Tabelle übereinstimmt (siehe Nr. 11 oben).
Der zweite Start mit Aufzeichnungen von 50 KB zeigt jedoch, dass die Download-Geschwindigkeit bereits leicht ansteigt, was auf eine Annäherung an die Grenzwerte hinweist. Es sollte beachtet werden, dass HBASE selbst praktisch nicht belastet wird. Alles, was dazu erforderlich ist, ist, zuerst die Daten von hbase: meta anzugeben und nach dem Auskleiden von HFiles die BlockCache-Daten zu leeren und den MemStore-Puffer auf der Festplatte zu speichern, wenn dies nicht der Fall ist leer.
3. Lesen von Daten aus HBASE
Wenn wir davon ausgehen, dass alle Informationen von hbase: meta bereits einen Client haben (siehe Abschnitt 2), geht die Anfrage sofort an die RS, wo der gewünschte Schlüssel gespeichert ist. Zuerst wird die Suche in MemCache durchgeführt. Unabhängig davon, ob dort Daten vorhanden sind oder nicht, wird die Suche auch im BlockCache-Puffer und gegebenenfalls in HFiles durchgeführt. Wenn die Daten in einer Datei gefunden wurden, werden sie in BlockCache abgelegt und bei der nächsten Anforderung schneller zurückgegeben. HFile-Suchen sind aufgrund der Verwendung des Bloom-Filters relativ schnell, d.h. Nachdem er eine kleine Datenmenge gelesen hat, stellt er sofort fest, ob diese Datei den gewünschten Schlüssel enthält, und fährt dann mit dem nächsten fort.
Nachdem RS Daten aus diesen drei Quellen erhalten hat, bildet es eine Antwort. Insbesondere können mehrere Versionen des gefundenen Objekts gleichzeitig übertragen werden, wenn der Client die Versionierung angefordert hat.
4. Daten-Caching
MemStore- und BlockCache-Puffer belegen bis zu 80% des zugewiesenen RS-Speichers auf dem Heap (der Rest ist für RS-Serviceaufgaben reserviert). Wenn der typische Verwendungsmodus so ist, dass die Prozesse dieselben Daten schreiben und sofort lesen, ist es sinnvoll, BlockCache zu reduzieren und MemStore zu erhöhen, weil Wenn das Schreiben von Daten in den Lesecache nicht abfällt, 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 der SSD). BucketCache sollte verwendet werden, wenn viele Leseanforderungen vorliegen und diese nicht in LruBlockCache passen, was zur aktiven Arbeit von Garbage Collector führt. Gleichzeitig sollten Sie mit der Verwendung des Lesecaches keine radikale Leistungssteigerung erwarten, aber wir werden in Abschnitt 8 darauf zurückkommen

BlockCache ist einer für den gesamten RS, und MemStore hat einen eigenen für jede Tabelle (einen für jede Spaltenfamilie).
Wie theoretisch
beschrieben , werden solche Parameter CACHE_DATA_ON_WRITE für die Tabelle und "Cache DATA on Write" für RS auf false gesetzt, wenn das Schreiben von Daten nicht in den Cache fällt. Wenn Sie jedoch in der Praxis Daten in MemStore schreiben, diese dann auf die Festplatte leeren (auf diese Weise bereinigen), dann die resultierende Datei löschen und durch Ausführen einer Abrufanforderung die Daten erfolgreich empfangen. Und selbst wenn Sie BlockCache vollständig deaktivieren und die Tabelle mit neuen Daten füllen, den MemStore auf die Festplatte bringen, löschen und von einer anderen Sitzung anfordern, werden sie dennoch von irgendwoher abgerufen. HBase speichert also nicht nur Daten, sondern auch mysteriöse Rätsel.
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
Cache DATA on Read ist auf false gesetzt. Wenn Sie Ideen haben, können Sie diese gerne in den Kommentaren diskutieren.
5. Stapelverarbeitung von MultiGet / MultiPut-Daten
Das Verarbeiten einzelner Anforderungen (Abrufen / Einfügen / Löschen) ist ein ziemlich teurer Vorgang. Sie sollten sie daher so weit wie möglich in einer Liste oder Liste kombinieren, um eine erhebliche Leistungssteigerung zu erzielen. Dies gilt insbesondere für die Schreiboperation, aber beim Lesen gibt es die folgende Gefahr. Die folgende Grafik zeigt die Lesezeit von 50.000 Datensätzen aus MemStore. Das Lesen wurde in einem Stream durchgeführt und die horizontale Achse zeigt die Anzahl der Schlüssel in der Anforderung. Es ist ersichtlich, dass die Ausführungszeit sinkt, wenn Sie in einer Anforderung auf tausend Schlüssel erhöhen, d. H. Geschwindigkeit steigt. Wenn der MSLAB-Modus jedoch standardmäßig aktiviert ist, beginnt nach diesem Schwellenwert ein dramatischer Leistungsabfall. Je größer die Datenmenge im Datensatz ist, desto länger ist die Zeit.

Die Tests wurden auf einer virtuellen Maschine mit 8 Kernen, HBase Version 2.0.0-cdh6.0.0-beta1, durchgeführt.
Der MSLAB-Modus wurde entwickelt, um die Heap-Fragmentierung zu reduzieren, die durch das Mischen von Daten der neuen und alten Generation entsteht. Als Lösung für das Problem, wenn MSLAB aktiviert ist, werden Daten in relativ kleinen Zellen (Chunk) abgelegt und stapelweise verarbeitet. Wenn das Volumen im angeforderten Datenpaket die zugewiesene Größe überschreitet, sinkt die Leistung daher stark. Andererseits ist es auch nicht ratsam, diesen Modus auszuschalten, da dies in Momenten intensiver Datenarbeit zu GC-Stopps führen kann. Ein guter Ausweg besteht darin, das Volumen der Zelle zu erhöhen, wenn beim aktiven Schreiben über das Put gleichzeitig mit dem Lesen gearbeitet wird. Es ist zu beachten, dass das Problem nicht auftritt, wenn Sie nach der Aufzeichnung den Befehl flush ausführen, mit dem MemStore auf die Festplatte geleert wird, oder wenn das Laden mit BulkLoad ausgeführt wird. Die folgende Tabelle zeigt, dass Abfragen von MemStore-Daten eines größeren Volumens (und derselben Menge) zu einer Verlangsamung führen. Durch Erhöhen der Blockgröße wird jedoch die normale Verarbeitungszeit wiederhergestellt.

Zusätzlich zur Erhöhung der Blockgröße hilft die Fragmentierung von Daten nach Region, d.h. Tischaufteilung. Dies führt dazu, dass weniger Anforderungen in jede Region kommen und wenn sie in einer Zelle platziert werden, bleibt die Antwort gut.
6. Die Strategie der Aufteilung von Tabellen in Regionen (Schneiden)
Da HBase ein Schlüsselwertspeicher ist und die Partitionierung nach Schlüsseln erfolgt, ist es äußerst wichtig, Daten gleichmäßig über alle Regionen hinweg zu teilen. Wenn Sie beispielsweise eine solche Tabelle in drei Teile unterteilen, werden die Daten in drei Bereiche unterteilt:
Es kommt vor, dass dies zu einer starken Verlangsamung führt, wenn die in Zukunft 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 Array von Bytes gespeichert sind, beginnen alle auf dieselbe Weise und gehören zu derselben Region Nr. 1, in der dieser Schlüsselbereich gespeichert ist. Es gibt verschiedene Split-Strategien:
HexStringSplit - Verwandelt den Schlüssel in eine Zeichenfolge mit hexadezimaler Codierung im Bereich "00000000" => "FFFFFFFF" und füllt ihn links mit Nullen.
UniformSplit - Verwandelt einen Schlüssel in ein Byte-Array mit hexadezimaler Codierung im Bereich "00" => "FF" und füllt es rechts mit Nullen.
Darüber hinaus können Sie einen beliebigen Bereich oder Schlüsselsatz zum Teilen und Einrichten der automatischen Aufteilung angeben. Einer der einfachsten und effektivsten Ansätze ist jedoch UniformSplit und die Verwendung der Hash-Verkettung, z. B. ein hohes Bytepaar, wenn ein Schlüssel über die CRC32-Funktion (Zeilenschlüssel) und den Zeilenschlüssel selbst ausgeführt wird:
Hash + Rowkey
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 steuert auch die Daten- und Schlüsselmenge in der Region. Wenn Grenzwerte überschritten werden, werden diese automatisch in Teile zerlegt.
7. Fehlertoleranz und Datenlokalität
Da nur eine Region für jeden Schlüsselsatz verantwortlich ist, besteht die Lösung für Probleme im Zusammenhang mit RS-Abstürzen oder Außerbetriebnahme darin, alle erforderlichen Daten in HDFS zu speichern. Wenn RS abstürzt, erkennt der Master dies durch das Fehlen eines Herzschlags auf dem ZooKeeper-Knoten. Dann weist er die bediente Region einer anderen RS zu, und da die HFiles in einem verteilten Dateisystem gespeichert sind, liest der neue Host sie und bedient die Daten weiterhin. Da sich einige der Daten möglicherweise im MemStore befinden und keine Zeit hatten, in HFiles zu gelangen, werden WALs, die ebenfalls in HDFS gespeichert sind, zum Wiederherstellen des Betriebsverlaufs verwendet. Nach dem Rollover von Änderungen kann RS auf Anforderungen reagieren. Die Verschiebung führt jedoch dazu, dass sich ein Teil der Daten und ihre Prozesse auf verschiedenen Knoten befinden, d. H. verminderte Lokalität.
Die Lösung des Problems ist eine umfassende Komprimierung. Durch diese Prozedur werden Dateien auf die für sie verantwortlichen Knoten (wo sich ihre Regionen befinden) verschoben, wodurch die Belastung des Netzwerks und der Festplatten während dieser Prozedur stark zunimmt. In Zukunft wird der Zugriff auf Daten jedoch spürbar beschleunigt. Darüber hinaus kombiniert major_compaction alle HFiles in einer Datei innerhalb der Region und bereinigt die Daten abhängig von den Tabelleneinstellungen. Beispielsweise können Sie die Anzahl der Versionen eines Objekts, die Sie speichern möchten, oder seine Lebensdauer angeben. Danach wird das Objekt physisch gelöscht.
Dieses Verfahren kann sich sehr positiv auf HBase auswirken. Das folgende Bild zeigt, wie sich die Leistung durch aktive Datenaufzeichnung verschlechtert. Hier können Sie sehen, wie 40 Streams in eine Tabelle geschrieben wurden und 40 Streams gleichzeitig Daten lesen. Schreibströme bilden immer mehr HFiles, die von anderen Strömen gelesen werden. Infolgedessen müssen immer mehr Daten aus dem Speicher gelöscht werden, und am Ende beginnt der GC zu arbeiten, was praktisch die gesamte Arbeit lähmt. Der Start einer größeren Verdichtung führte zur Beseitigung der daraus resultierenden Blockaden und zur Wiederherstellung der Leistung.
Der Test wurde mit 3 DataNode 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 der Start der Hauptverdichtung an einer "Live" -Tabelle durchgeführt wurde, in die Daten aktiv geschrieben und gelesen wurden. Im Netzwerk gab es eine Erklärung, dass dies beim Lesen von Daten zu einer falschen Antwort führen könnte. Zur Überprüfung wurde ein Prozess gestartet, der neue Daten generierte und in die Tabelle schrieb. Danach habe ich sofort gelesen und überprüft, ob der erhaltene Wert mit dem aufgezeichneten Wert übereinstimmt. Während dieses Prozesses wurde die Hauptverdichtung ungefähr 200 Mal gestartet und kein einziger Fehler wurde aufgezeichnet. Möglicherweise tritt das Problem selten und nur bei hoher Last auf. Daher ist es sicherer, die Schreib- und Lesevorgänge weiterhin planmäßig anzuhalten und die Reinigung durchzuführen, ohne solche GC-Drawdowns zuzulassen.
Außerdem wirkt sich eine größere Komprimierung nicht auf den Status von 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 den größten Erfolg, wenn bei der Ausführung von BulkLoad nichts unternommen werden muss. Dies gilt jedoch für die meisten Systeme und Personen. Dieses Tool eignet sich jedoch besser für das Massenstapeln von Daten in großen Blöcken. Wenn für den Prozess viele konkurrierende Lese- und Schreibanforderungen erforderlich sind, werden die oben beschriebenen Befehle Get und Put verwendet. Um die optimalen Parameter zu bestimmen, wurden Starts mit verschiedenen Kombinationen von Tabellenparametern und Einstellungen durchgeführt:
- 10 Threads wurden dreimal hintereinander gleichzeitig gestartet (nennen wir es einen Threadblock).
- Die Betriebszeit aller Flüsse im Block wurde gemittelt und war das Endergebnis des Betriebs des Blocks.
- Alle Threads arbeiteten mit derselben Tabelle.
- Vor jedem Start des Thread-Blocks wurde eine größere Komprimierung ausgeführt.
- Jeder Block führte nur eine der folgenden Operationen aus:
- Put
- bekommen
- Holen Sie sich + Put
- Jeder Block führte 50.000 Wiederholungen seiner Operation durch.
- Die Datensatzgröße im Block beträgt 100 Byte, 1000 Byte oder 10000 Byte (zufällig).
- Blöcke wurden mit einer anderen Anzahl angeforderter Schlüssel (entweder einem Schlüssel oder 10) gestartet.
- Blöcke wurden bei verschiedenen Tabelleneinstellungen gestartet. Parameter geändert:
- BlockCache = ein- oder ausgeschaltet
- BlockSize = 65 Kb oder 16 Kb
- Partitionen = 1, 5 oder 30
- MSLAB = ein oder aus
Der Block sieht also folgendermaßen aus:
a. MSLAB-Modus ein- / ausgeschaltet.
b. Es wurde eine Tabelle erstellt, für die die folgenden Parameter festgelegt wurden: BlockCache = true / none, BlockSize = 65/16 Kb, Partitions = 1/5/30.
c. Stellen Sie die Komprimierung GZ ein.
d. 10 Threads wurden gleichzeitig gestartet, wobei 1/10 der Put / Get / Get + Put-Operationen in dieser Tabelle mit Datensätzen von 100/1000/10000 Bytes ausgeführt wurden, wobei 50.000 Abfragen hintereinander ausgeführt wurden (zufällige Schlüssel).
e. Punkt d wurde dreimal wiederholt.
f. Die Betriebszeit aller Threads wurde gemittelt.
Alle möglichen Kombinationen wurden überprüft. Es ist vorhersehbar, dass mit zunehmender Aufnahmegröße die Geschwindigkeit abnimmt oder das Deaktivieren des Cachings langsamer wird. Ziel war es jedoch, den Grad und die Bedeutung des Einflusses jedes Parameters zu verstehen. Daher wurden die gesammelten Daten in die Eingabe der linearen Regressionsfunktion eingespeist, wodurch die Zuverlässigkeit mithilfe von t-Statistiken bewertet werden kann. Nachfolgend sind die Ergebnisse der Blöcke aufgeführt, die Put-Operationen ausführen. Ein vollständiger Satz von Kombinationen 2 * 2 * 3 * 2 * 3 = 144 Optionen + 72 seit einige wurden zweimal durchgeführt. Daher werden insgesamt 216 Starts durchgeführt:
Die Tests wurden an einem Mini-Cluster durchgeführt, der aus 3 DataNode und 4 RS (CPU Xeon E5-2680 v4 bei 2,40 GHz * 64 Streams) bestand. HBase Version 1.2.0-cdh5.14.2.
Die höchste Einfügungsgeschwindigkeit von 3,7 Sekunden wurde erreicht, wenn der MSLAB-Modus auf einer Tabelle mit einer Partition mit aktiviertem BlockCache, BlockSize = 16, Datensätzen von 100 Bytes mit 10 Teilen pro Packung deaktiviert wurde.
Die niedrigste Einfügungsgeschwindigkeit von 82,8 Sekunden wurde erreicht, wenn der MSLAB-Modus in einer Tabelle mit einer Partition mit aktiviertem BlockCache, BlockSize = 16, Datensätzen mit jeweils 10.000 Byte aktiviert wurde.
Schauen wir uns nun das Modell an. Wir sehen ein Modell von guter Qualität für R2, aber es ist klar, dass eine Extrapolation hier kontraindiziert ist. Das tatsächliche Verhalten des Systems beim Ändern der Parameter ist nicht linear. Dieses Modell wird nicht für Prognosen benötigt, sondern um zu verstehen, was innerhalb der angegebenen 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 vorhersehbar ist):

Die Tatsache, dass eine Erhöhung der Anzahl der Partitionen zu einer Verringerung der Leistung führt, ist jedoch etwas unerwartet (wir haben bereits den positiven Effekt einer Erhöhung der Anzahl der Partitionen mit BulkLoad gesehen), obwohl dies verständlich ist. Erstens ist es für die Verarbeitung erforderlich, Abfragen an 30 Regionen anstatt an eine zu bilden, und die Datenmenge ist nicht so, dass sie einen Gewinn ergibt. Zweitens wird die Gesamtbetriebszeit durch die langsamste RS bestimmt, und da die Anzahl der Datenknoten geringer als die Anzahl der RS ist, haben einige Regionen keine Lokalität. Schauen wir uns die Top 5 an:
Lassen Sie uns nun die Ergebnisse der Ausführung von Get-Blöcken auswerten:
Die Anzahl der Partitionen hat an Bedeutung verloren, was wahrscheinlich darauf zurückzuführen ist, dass die Daten gut zwischengespeichert sind und der Lesecache der signifikanteste (statistisch) Parameter ist. Natürlich ist das Erhöhen der Anzahl von Nachrichten in einer Anforderung auch für die Leistung sehr nützlich. Die besten Ergebnisse:
Schauen Sie sich zum Schluss zuerst das Modell des ausgeführten Blocks an und setzen Sie dann:
Hier sind alle Parameter von Bedeutung. Und die Ergebnisse der Führer:
9. Lasttest
Nun, endlich werden wir eine mehr oder weniger anständige Ladung starten, aber es ist immer interessanter, wenn es etwas zu vergleichen gibt. Die Site von DataStax, einem Schlüsselentwickler von Cassandra, enthält die
Ergebnisse von NT einer Reihe von NoSQL-Repositorys, einschließlich HBase Version 0.98.6-1. Das Laden wurde von 40 Streams, Datengröße 100 Bytes, SSD-Festplatten durchgeführt. Das Ergebnis des Testens von Lese-, Änderungs- und Schreibvorgängen zeigte diese Ergebnisse.
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.000 Operationen pro Sekunde.
Es ist ein Glück, dass unser Cluster auch 16 Knoten hat, aber nicht sehr "glücklich", dass jeder 64 Kerne (Threads) hat, während der DataStax-Test nur 4 hat. Andererseits haben sie SSD-Festplatten und wir haben HDD und mehr Die neue Version der HBase- und CPU-Auslastung während des Ladens stieg praktisch nicht signifikant an (visuell um 5-10 Prozent). Trotzdem werden wir versuchen, mit dieser Konfiguration zu beginnen. Tabelleneinstellungen Standardmäßig wird das Lesen in einem Bereich von Tasten von 0 bis 50 Millionen zufällig durchgeführt (d. H. Tatsächlich jedes Mal, wenn eine neue erstellt wird). In der Tabelle sind 50 Millionen Einträge in 64 Partitionen unterteilt. Schlüssel sind crc32 gehasht. Tabelleneinstellungen sind voreingestellt, MSLAB ist aktiviert. Ab 40 Threads liest jeder Thread einen Satz von 100 zufälligen Schlüsseln und schreibt die generierten 100 Bytes sofort auf diese Schlüssel zurück.

Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2,40 GHz * 64 Streams). HBase Version 1.2.0-cdh5.14.2.
Das durchschnittliche Ergebnis liegt näher bei 40.000 Vorgängen pro Sekunde, was deutlich besser ist als im DataStax-Test. Für die Zwecke des Experiments können die Bedingungen jedoch geringfügig geändert werden. Es ist ziemlich unwahrscheinlich, dass alle Arbeiten ausschließlich mit einem Tisch sowie nur mit eindeutigen Schlüsseln ausgeführt werden. Angenommen, es gibt einen bestimmten „heißen“ Schlüsselsatz, der die Hauptlast erzeugt. Daher werden wir versuchen, eine Last mit größeren Datensätzen (10 KB), ebenfalls in Packungen zu je 100, in 4 verschiedenen Tabellen zu erstellen und den Bereich der angeforderten Schlüssel auf 50.000 zu begrenzen. Die folgende Grafik zeigt den Beginn von 40 Threads, jeder Stream liest einen Satz von 100 Schlüsseln und schreibt sofort zufällige 10 KB auf diesen Schlüsseln zurück.
Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2,40 GHz * 64 Streams). HBase Version 1.2.0-cdh5.14.2.
Während des Ladens wurde mehrmals eine größere Verdichtung gestartet, wie oben gezeigt, ohne dieses Verfahren. Die Leistung wird allmählich beeinträchtigt, es tritt jedoch auch eine zusätzliche Last während der Ausführung auf. Drawdowns werden aus verschiedenen Gründen verursacht. Manchmal wurden Threads beendet und während des Neustarts gab es eine Pause. Manchmal haben Anwendungen von Drittanbietern den Cluster belastet.
Sofortiges Lesen und Schreiben ist eines der schwierigsten Arbeitsszenarien für HBase. Wenn Sie nur Put-Anforderungen mit einer geringen Größe, z. B. jeweils 100 Byte, in Stapeln von 10 bis 50.000 Teilen platzieren, können Sie Hunderttausende von Vorgängen pro Sekunde ausführen, und die Situation ist bei schreibgeschützten Anforderungen ähnlich. Es ist erwähnenswert, dass die Ergebnisse radikal besser sind als diejenigen, die bei DataStax vor allem aufgrund von Anfragen in Blöcken von 50.000 erhalten wurden.

Stand: 16 DataNode und 16 RS (CPU Xeon E5-2680 v4 bei 2,40 GHz * 64 Streams). HBase Version 1.2.0-cdh5.14.2.
10. Schlussfolgerungen
Dieses System ist flexibel genug, um konfiguriert zu werden, aber die Auswirkung einer großen Anzahl von Parametern ist noch unbekannt. Einige von ihnen wurden getestet, waren jedoch nicht in der resultierenden Testsuite enthalten. Zum Beispiel zeigten vorläufige Experimente die Bedeutungslosigkeit eines Parameters wie DATA_BLOCK_ENCODING, der Informationen unter Verwendung von Werten aus benachbarten Zellen codiert, was für zufällig generierte Daten durchaus verständlich ist. Bei Verwendung einer großen Anzahl sich wiederholender Objekte kann die Verstärkung erheblich sein. Generell kann man sagen, dass HBase den Eindruck einer ziemlich seriösen und gut durchdachten Datenbank erweckt, die bei großen Datenblöcken sehr produktiv sein kann. Insbesondere wenn es möglich ist, die Lese- und Schreibvorgänge rechtzeitig zu verteilen.
Wenn etwas Ihrer Meinung nach nicht ausreichend offengelegt wird, bin ich bereit, dies genauer zu erläutern. Wir empfehlen Ihnen, Ihre Erfahrungen mitzuteilen oder zu debattieren, wenn Sie mit etwas nicht einverstanden sind.