Teoria i praktyka wykorzystania HBase

Dzień dobry Nazywam się Danil Lipovoy, nasz zespół w Sbertech zaczął używać HBase jako magazynu danych operacyjnych. W trakcie jego studiowania zgromadziło się doświadczenie, które chciałem usystematyzować i opisać (mamy nadzieję, że dla wielu będzie przydatne). Wszystkie poniższe eksperymenty przeprowadzono z wersjami HBase 1.2.0-cdh5.14.2 i 2.0.0-cdh6.0.0-beta1.

  1. Architektura ogólna
  2. Zapisywanie danych do HBASE
  3. Odczyt danych z HBASE
  4. Buforowanie danych
  5. Wsadowe przetwarzanie danych MultiGet/MultiPut
  6. Strategia podziału tabel na regiony (dzielenie)
  7. Tolerancja błędów, kompaktyfikacja i lokalizacja danych
  8. Ustawienia i wydajność
  9. Test naprężeń
  10. odkrycia

1. Architektura ogólna

Teoria i praktyka wykorzystania HBase
Zapasowy Master nasłuchuje bicia serca aktywnego w węźle ZooKeeper i w przypadku zaginięcia przejmuje funkcje mastera.

2. Zapisz dane w HBASE

Najpierw spójrzmy na najprostszy przypadek - zapisanie obiektu klucz-wartość do tabeli za pomocą metody put(rowkey). Klient musi najpierw dowiedzieć się, gdzie znajduje się serwer regionu głównego (RRS), który przechowuje tabelę hbase:meta. Otrzymuje te informacje od ZooKeeper. Po czym uzyskuje dostęp do RRS i odczytuje tabelę hbase:meta, z której wydobywa informację o tym, który RegionServer (RS) jest odpowiedzialny za przechowywanie danych dla danego klucza wiersza w interesującej nas tabeli. Do wykorzystania w przyszłości metatabela jest buforowana przez klienta, dzięki czemu kolejne wywołania przebiegają szybciej, bezpośrednio do RS.

Następnie RS po otrzymaniu żądania zapisuje je najpierw do WriteAheadLog (WAL), który jest niezbędny do odzyskania danych w przypadku awarii. Następnie zapisuje dane w MemStore. Jest to bufor w pamięci zawierający posortowany zestaw kluczy dla danego regionu. Tabela może być podzielona na regiony (partycje), z których każda zawiera rozłączny zestaw kluczy. Pozwala to na umieszczenie regionów na różnych serwerach w celu osiągnięcia wyższej wydajności. Jednak pomimo oczywistości tego stwierdzenia, zobaczymy później, że nie działa to we wszystkich przypadkach.

Po umieszczeniu wpisu w MemStore do klienta zwracana jest odpowiedź, że wpis został pomyślnie zapisany. Jednak w rzeczywistości jest on przechowywany jedynie w buforze i trafia na dysk dopiero po upływie określonego czasu lub po zapełnieniu go nowymi danymi.

Teoria i praktyka wykorzystania HBase
Podczas wykonywania operacji „Usuń” dane nie są fizycznie usuwane. Są one po prostu oznaczane jako usunięte, a samo zniszczenie następuje w momencie wywołania funkcji zwartej głównej, co opisano szerzej w paragrafie 7.

Pliki w formacie HFile gromadzone są w HDFS i od czasu do czasu uruchamiany jest niewielki proces kompaktowy, który po prostu łączy małe pliki w większe, bez usuwania czegokolwiek. Z biegiem czasu zamienia się to w problem, który pojawia się tylko przy odczycie danych (powrócimy do tego nieco później).

Oprócz opisanego powyżej procesu ładowania istnieje znacznie skuteczniejsza procedura, która jest chyba najmocniejszą stroną tej bazy danych - BulkLoad. Polega to na tym, że samodzielnie tworzymy HFiles i umieszczamy je na dysku, co pozwala nam idealnie skalować i osiągać bardzo przyzwoite prędkości. Tak naprawdę ograniczeniem nie jest tutaj HBase, ale możliwości sprzętu. Poniżej znajdują się wyniki rozruchu w klastrze składającym się z 16 RegionServers i 16 NodeManager YARN (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki), wersja HBase 1.2.0-cdh5.14.2.

Teoria i praktyka wykorzystania HBase

Tutaj widać, że zwiększając liczbę partycji (regionów) w tabeli, a także executorów Spark, uzyskujemy wzrost prędkości pobierania. Prędkość zależy również od głośności nagrywania. Duże bloki powodują wzrost MB/s, małe bloki liczby wstawianych rekordów na jednostkę czasu, przy wszystkich pozostałych czynnikach bez zmian.

Możesz także rozpocząć ładowanie do dwóch tabel jednocześnie i uzyskać dwukrotnie większą prędkość. Poniżej widać, że zapis bloków o wielkości 10 KB do dwóch tablic jednocześnie odbywa się z szybkością około 600 MB/s w każdej (łącznie 1275 MB/s), co pokrywa się z szybkością zapisu do jednej tabeli wynoszącą 623 MB/s (patrz nr 11 powyżej)

Teoria i praktyka wykorzystania HBase
Jednak drugi bieg z rekordami 50 KB pokazuje, że prędkość pobierania nieznacznie rośnie, co wskazuje, że zbliża się do wartości granicznych. Jednocześnie należy pamiętać, że na samym HBASE praktycznie nie tworzy się żadne obciążenie, wystarczy, że najpierw poda dane z hbase:meta, a po linijce HFiles zresetuje dane BlockCache i zapisze Bufor MemStore na dysk, jeśli nie jest pusty.

3. Odczyt danych z HBASE

Jeśli założymy, że klient posiada już wszystkie informacje z hbase:meta (patrz punkt 2), to żądanie trafia bezpośrednio do RS, gdzie przechowywany jest wymagany klucz. Najpierw wyszukiwanie odbywa się w MemCache. Niezależnie od tego, czy są tam dane, czy nie, wyszukiwanie odbywa się także w buforze BlockCache i w razie potrzeby w HFiles. Jeżeli w pliku odnaleziono dane, są one umieszczane w BlockCache i przy kolejnym żądaniu zostaną szybciej zwrócone. Wyszukiwanie w HFile jest stosunkowo szybkie dzięki zastosowaniu filtra Blooma, tj. po wczytaniu niewielkiej ilości danych od razu sprawdza, czy plik ten zawiera wymagany klucz, a jeśli nie, przechodzi do następnego.

Teoria i praktyka wykorzystania HBase
Po otrzymaniu danych z tych trzech źródeł RS generuje odpowiedź. W szczególności może przesłać kilka znalezionych wersji obiektu na raz, jeśli klient zażądał wersjonowania.

4. Buforowanie danych

Bufory MemStore i BlockCache zajmują do 80% alokowanej pamięci RS na stercie (reszta jest zarezerwowana dla zadań usługowych RS). Jeśli typowy tryb użytkowania polega na tym, że procesy zapisują i natychmiast odczytują te same dane, wówczas sensowne jest zmniejszenie BlockCache i zwiększenie MemStore, ponieważ Gdy zapisywane dane nie dostaną się do pamięci podręcznej w celu odczytania, BlockCache będzie używany rzadziej. Bufor BlockCache składa się z dwóch części: LruBlockCache (zawsze na stercie) i BucketCache (zwykle poza stertą lub na dysku SSD). BucketCache należy stosować, gdy jest dużo żądań odczytu i nie mieszczą się one w LruBlockCache, co prowadzi do aktywnej pracy Garbage Collectora. Jednocześnie nie należy spodziewać się radykalnego wzrostu wydajności podczas korzystania z pamięci podręcznej odczytu, ale powrócimy do tego w paragrafie 8

Teoria i praktyka wykorzystania HBase
Istnieje jeden BlockCache dla całego RS i jeden MemStore dla każdej tabeli (po jednym dla każdej rodziny kolumn).

jak opisane teoretycznie podczas zapisu dane nie trafiają do pamięci podręcznej i rzeczywiście takie parametry CACHE_DATA_ON_WRITE dla tabeli i „Cache DATA on Write” dla RS są ustawione na false. Jednak w praktyce, jeśli zapiszemy dane do MemStore, a następnie zrzucimy je na dysk (a więc wyczyścimy), a następnie usuniemy powstały plik, to wykonując żądanie get, pomyślnie odbierzemy dane. Co więcej, nawet jeśli całkowicie wyłączysz BlockCache i wypełnisz tabelę nowymi danymi, a następnie zresetujesz MemStore na dysk, usuniesz je i zażądasz w innej sesji, nadal będą one skądś pobierane. HBase przechowuje więc nie tylko dane, ale także tajemnicze tajemnice.

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

Parametr „Cache DATA on Read” ma wartość false. Jeśli masz jakieś pomysły, zapraszamy do omówienia ich w komentarzach.

5. Wsadowe przetwarzanie danych MultiGet/MultiPut

Przetwarzanie pojedynczych żądań (Get/Put/Delete) jest dość kosztowną operacją, dlatego jeśli to możliwe, warto połączyć je w Listę lub Listę, co pozwala uzyskać znaczny wzrost wydajności. Jest to szczególnie prawdziwe w przypadku operacji zapisu, ale podczas odczytu pojawia się następująca pułapka. Poniższy wykres przedstawia czas odczytania 50 000 rekordów z MemStore. Odczyt został wykonany w jednym wątku, a oś pozioma przedstawia liczbę kluczy w żądaniu. Tutaj widać, że przy wzroście do tysiąca kluczy w jednym żądaniu czas wykonania spada, tj. prędkość wzrasta. Jednak przy domyślnie włączonym trybie MSLAB, po przekroczeniu tego progu zaczyna się radykalny spadek wydajności, a im większa ilość danych w rekordzie, tym dłuższy czas pracy.

Teoria i praktyka wykorzystania HBase

Testy przeprowadzono na maszynie wirtualnej 8 rdzeni w wersji HBase 2.0.0-cdh6.0.0-beta1.

Tryb MSLAB ma na celu ograniczenie fragmentacji sterty, która występuje w wyniku mieszania danych nowej i starej generacji. W ramach obejścia problemu, gdy włączona jest funkcja MSLAB, dane są umieszczane w stosunkowo małych komórkach (porcjach) i przetwarzane w porcjach. W rezultacie, gdy wolumin żądanego pakietu danych przekracza przydzielony rozmiar, wydajność gwałtownie spada. Z drugiej strony wyłączenie tego trybu również nie jest wskazane, gdyż doprowadzi to do przestojów z powodu GC w momentach intensywnego przetwarzania danych. Dobrym rozwiązaniem jest zwiększenie objętości komórki w przypadku aktywnego zapisu poprzez umieszczanie w tym samym czasie co czytanie. Warto zaznaczyć, że problem nie występuje, jeśli po nagraniu uruchomisz polecenie Flush, które resetuje MemStore na dysk, lub jeśli załadujesz za pomocą BulkLoad. Poniższa tabela pokazuje, że zapytania z MemStore o większe (i tę samą ilość) danych powodują spowolnienie. Jednak zwiększając rozmiar porcji, przywracamy normalny czas przetwarzania.

Teoria i praktyka wykorzystania HBase
Oprócz zwiększenia rozmiaru fragmentu pomocne jest dzielenie danych według regionu, tj. podział stołu. Powoduje to, że do każdego regionu dociera mniej żądań i jeśli mieszczą się w komórce, odpowiedź pozostaje dobra.

6. Strategia podziału tabel na regiony (dzielenie)

Ponieważ HBase to magazyn klucz-wartość, a partycjonowanie odbywa się według klucza, niezwykle ważne jest równomierne podzielenie danych między wszystkie regiony. Przykładowo podział takiej tabeli na trzy części spowoduje, że dane zostaną podzielone na trzy regiony:

Teoria i praktyka wykorzystania HBase
Zdarza się, że prowadzi to do gwałtownego spowolnienia, jeśli ładowane później dane wyglądają np. jako długie wartości, większość z nich zaczyna się od tej samej cyfry, np.:

1000001
1000002
...
1100003

Ponieważ klucze są przechowywane jako tablica bajtów, wszystkie zaczną się tak samo i będą należeć do tego samego regionu nr 1, w którym przechowywany jest ten zakres kluczy. Istnieje kilka strategii partycjonowania:

HexStringSplit – Zamienia klucz w zakodowany w formacie szesnastkowym ciąg z zakresu „00000000” => „FFFFFFFF” i dopełnienie po lewej stronie zerami.

UniformSplit – Zamienia klucz w tablicę bajtów z kodowaniem szesnastkowym w zakresie „00” => „FF” i wypełnieniem po prawej stronie zerami.

Ponadto możesz określić dowolny zakres lub zestaw kluczy do podziału i skonfigurować automatyczne dzielenie. Jednak jednym z najprostszych i najskuteczniejszych podejść jest UniformSplit i użycie konkatenacji skrótu, na przykład najbardziej znaczącej pary bajtów z uruchomienia klucza przez funkcję CRC32(rowkey) i samego rowkeya:

skrót + klucz wiersza

Wtedy wszystkie dane zostaną równomiernie rozłożone pomiędzy regionami. Podczas odczytu pierwsze dwa bajty są po prostu odrzucane, a oryginalny klucz pozostaje. RS kontroluje także ilość danych i kluczy w regionie i w przypadku przekroczenia limitów automatycznie dzieli je na części.

7. Tolerancja błędów i lokalizacja danych

Ponieważ za każdy zestaw kluczy odpowiedzialny jest tylko jeden region, rozwiązaniem problemów związanych z awarią RS lub likwidacją jest przechowywanie wszystkich niezbędnych danych w HDFS. Kiedy RS spada, master wykrywa to poprzez brak pulsu w węźle ZooKeeper. Następnie przypisuje obsługiwany region do innego RS, a ponieważ HFiles są przechowywane w rozproszonym systemie plików, nowy właściciel czyta je i kontynuuje udostępnianie danych. Ponieważ jednak część danych mogła znajdować się w MemStore i nie miała czasu dostać się do HFiles, do przywrócenia historii operacji służy WAL, który również jest przechowywany w HDFS. Po zastosowaniu zmian RS jest w stanie odpowiadać na żądania, jednak posunięcie powoduje, że część danych i obsługujących je procesów trafia do innych węzłów, czyli tzw. miejscowość maleje.

Rozwiązaniem problemu jest duża kompresja - ta procedura przenosi pliki do odpowiedzialnych za nie węzłów (gdzie znajdują się ich regiony), w wyniku czego podczas tej procedury gwałtownie wzrasta obciążenie sieci i dysków. Jednak w przyszłości dostęp do danych zostanie zauważalnie przyspieszony. Ponadto major_compaction łączy wszystkie pliki HFiles w jeden plik w regionie, a także czyści dane w zależności od ustawień tabeli. Można na przykład określić liczbę wersji obiektu, które należy zachować, lub okres istnienia, po upływie którego obiekt zostanie fizycznie usunięty.

Procedura ta może mieć bardzo pozytywny wpływ na działanie HBase. Poniższy obrazek pokazuje, jak wydajność spadła w wyniku aktywnego rejestrowania danych. Tutaj możesz zobaczyć, jak 40 wątków zapisywało dane do jednej tabeli i 40 wątków jednocześnie odczytywało dane. Pisanie wątków generuje coraz więcej HFiles, które są czytane przez inne wątki. W rezultacie coraz więcej danych trzeba usuwać z pamięci i w końcu GC zaczyna działać, co praktycznie paraliżuje całą pracę. Rozpoczęcie większego zagęszczania doprowadziło do oczyszczenia powstałego gruzu i przywrócenia produktywności.

Teoria i praktyka wykorzystania HBase
Test przeprowadzono na 3 DataNodes i 4 RS (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki). Wersja HBase 1.2.0-cdh5.14.2

Warto dodać, że główne zagęszczanie zostało uruchomione na „żywej” tabeli, do której aktywnie zapisywano i odczytywano dane. W Internecie pojawiło się oświadczenie, że może to prowadzić do nieprawidłowej reakcji podczas odczytu danych. Aby to sprawdzić, uruchomiono proces, który wygenerował nowe dane i zapisał je w tabeli. Po czym natychmiast przeczytałem i sprawdziłem, czy otrzymana wartość pokrywa się z tym, co zostało zapisane. W trakcie tego procesu główne zagęszczanie przeprowadzono około 200 razy i nie odnotowano ani jednej awarii. Być może problem pojawia się rzadko i tylko przy dużym obciążeniu, dlatego bezpieczniej jest zatrzymać procesy zapisu i odczytu zgodnie z planem i przeprowadzić czyszczenie, aby zapobiec takim poborom GC.

Ponadto większe zagęszczenie nie ma wpływu na stan magazynu MemStore; aby opróżnić go na dysk i skompaktować, należy użyć funkcji opróżniania (connection.getAdmin().flush(TableName.valueOf(tblName))).

8. Ustawienia i wydajność

Jak już wspomniano, HBase pokazuje swój największy sukces tam, gdzie nie musi nic robić, podczas wykonywania BulkLoad. Dotyczy to jednak większości systemów i ludzi. Jednak to narzędzie jest bardziej odpowiednie do przechowywania danych zbiorczo w dużych blokach, natomiast jeśli proces wymaga wielu konkurencyjnych żądań odczytu i zapisu, stosuje się opisane powyżej polecenia Get i Put. Aby określić optymalne parametry, przeprowadzono uruchomienia z różnymi kombinacjami parametrów tabeli i ustawień:

  • 10 wątków zostało uruchomionych jednocześnie 3 razy z rzędu (nazwijmy to blokiem wątków).
  • Czas działania wszystkich wątków w bloku był uśredniany i stanowił końcowy wynik działania bloku.
  • Wszystkie wątki działały z tą samą tabelą.
  • Przed każdym rozpoczęciem bloku gwintu wykonywano duże zagęszczenie.
  • Każdy blok wykonywał tylko jedną z następujących operacji:

-Umieścić
-Dostawać
—Pobierz+Połóż

  • Każdy blok wykonał 50 000 iteracji swojego działania.
  • Rozmiar bloku rekordu wynosi 100 bajtów, 1000 bajtów lub 10000 bajtów (losowo).
  • Uruchomiono bloki z różną liczbą żądanych kluczy (jeden klucz lub 10).
  • Bloki uruchamiano przy różnych ustawieniach tabeli. Parametry zmienione:

— BlockCache = włączony lub wyłączony
— Rozmiar bloku = 65 KB lub 16 KB
— Partycje = 1, 5 lub 30
— MSLAB = włączone lub wyłączone

Blok wygląda zatem następująco:

A. Tryb MSLAB został włączony/wyłączony.
B. Utworzono tabelę, dla której ustawiono następujące parametry: BlockCache = true/none, BlockSize = 65/16 Kb, Partition = 1/5/30.
C. Kompresję ustawiłem na GZ.
D. Uruchomiono jednocześnie 10 wątków, wykonując 1/10 operacji put/get/get+put w tej tabeli z rekordami o wielkości 100/1000/10000 bajtów, wykonując 50 000 zapytań z rzędu (losowe klucze).
mi. Punkt d powtórzono trzykrotnie.
F. Czas pracy wszystkich wątków uśredniono.

Przetestowano wszystkie możliwe kombinacje. Można przewidzieć, że prędkość spadnie wraz ze wzrostem rozmiaru rekordu lub że wyłączenie buforowania spowoduje spowolnienie. Celem było jednak zrozumienie stopnia i istotności wpływu każdego parametru, dlatego zebrane dane wprowadzono na wejście funkcji regresji liniowej, która umożliwia ocenę istotności za pomocą statystyki t. Poniżej znajdują się wyniki bloków wykonujących operacje Put. Pełny zestaw kombinacji 2*2*3*2*3 = 144 opcje + 72 tk. niektóre wykonano dwukrotnie. Zatem łącznie jest 216 przebiegów:

Teoria i praktyka wykorzystania HBase
Testy przeprowadzono na miniklastrze składającym się z 3 DataNode i 4 RS (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki). Wersja HBase 1.2.0-cdh5.14.2.

Największą prędkość wstawiania wynoszącą 3.7 sekundy uzyskano przy wyłączonym trybie MSLAB, na tabeli z jedną partycją, z włączoną funkcją BlockCache, BlockSize = 16, rekordy 100 bajtów, opakowanie po 10 sztuk.
Najniższą prędkość wstawiania wynoszącą 82.8 s uzyskano przy włączonym trybie MSLAB, na tabeli z jedną partycją, z włączoną funkcją BlockCache, BlockSize = 16, rekordy 10000 1 bajtów, po XNUMX każdy.

Przyjrzyjmy się teraz modelowi. Widzimy dobrą jakość modelu opartego na R2, ale jest absolutnie jasne, że ekstrapolacja jest tutaj przeciwwskazana. Rzeczywiste zachowanie systemu przy zmianie parametrów nie będzie liniowe; model ten jest potrzebny nie do przewidywania, ale do zrozumienia, co wydarzyło się w ramach danych parametrów. Na przykład tutaj widzimy na podstawie kryterium Studenta, że ​​parametry BlockSize i BlockCache nie mają znaczenia dla operacji Put (która jest ogólnie dość przewidywalna):

Teoria i praktyka wykorzystania HBase
Jednak fakt, że zwiększenie liczby partycji prowadzi do spadku wydajności, jest nieco nieoczekiwany (widzieliśmy już pozytywny wpływ zwiększenia liczby partycji za pomocą BulkLoad), choć zrozumiały. Po pierwsze, do przetwarzania trzeba generować żądania do 30 regionów zamiast do jednego, a ilość danych nie jest na tyle duża, aby dało to zysk. Po drugie, całkowity czas działania jest określony przez najwolniejszy RS, a ponieważ liczba DataNodes jest mniejsza niż liczba RS, niektóre regiony mają zerową lokalizację. Cóż, spójrzmy na pierwszą piątkę:

Teoria i praktyka wykorzystania HBase
Oceńmy teraz wyniki wykonywania bloków Get:

Teoria i praktyka wykorzystania HBase
Liczba partycji straciła na znaczeniu, co prawdopodobnie można wytłumaczyć faktem, że dane są dobrze buforowane, a pamięć podręczna odczytu jest najważniejszym (statystycznie) parametrem. Naturalnie zwiększenie liczby wiadomości w żądaniu jest również bardzo przydatne dla wydajności. Najwyższe wyniki:

Teoria i praktyka wykorzystania HBase
No cóż, na koniec spójrzmy na model bloku, który najpierw wykonał pobieranie, a następnie umieszczanie:

Teoria i praktyka wykorzystania HBase
Wszystkie parametry są tutaj istotne. Oraz wyniki liderów:

Teoria i praktyka wykorzystania HBase

9. Testowanie obciążenia

Cóż, w końcu wypuścimy mniej więcej przyzwoity ładunek, ale zawsze jest ciekawiej, gdy masz coś do porównania. Na stronie DataStax, kluczowego dewelopera Cassandry, znajduje się Ustalenia NT wielu magazynów NoSQL, w tym HBase w wersji 0.98.6-1. Ładowanie odbywało się poprzez 40 wątków, rozmiar danych 100 bajtów, dyski SSD. Wynik testowania operacji Read-Modify-Write pokazał następujące wyniki.

Teoria i praktyka wykorzystania HBase
O ile rozumiem, odczyt odbywał się w blokach po 100 rekordów i dla 16 węzłów HBase test DataStax wykazał wydajność 10 tysięcy operacji na sekundę.

Całe szczęście, że nasz klaster też ma 16 węzłów, ale mało „szczęście”, że każdy ma 64 rdzenie (wątki), podczas gdy w teście DataStax jest ich tylko 4. Z drugiej strony oni mają dyski SSD, my zaś HDD lub więcej nowa wersja HBase i wykorzystanie procesora podczas obciążenia praktycznie nie wzrosło znacząco (wizualnie o 5-10 procent). Spróbujmy jednak zacząć korzystać z tej konfiguracji. Domyślne ustawienia tabeli, odczyt odbywa się w zakresie kluczy od 0 do 50 milionów losowo (czyli za każdym razem zasadniczo nowy). Tabela zawiera 50 milionów rekordów podzielonych na 64 partycje. Klucze są szyfrowane przy użyciu crc32. Ustawienia tabeli są domyślne, MSLAB jest włączony. Uruchamiając 40 wątków, każdy wątek odczytuje zestaw 100 losowych kluczy i natychmiast zapisuje wygenerowane 100 bajtów z powrotem do tych kluczy.

Teoria i praktyka wykorzystania HBase
Podstawka: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki). Wersja HBase 1.2.0-cdh5.14.2.

Średni wynik jest bliższy 40 tys. operacji na sekundę, czyli znacząco lepszy niż w teście DataStax. Jednak w celach eksperymentalnych możesz nieznacznie zmienić warunki. Jest mało prawdopodobne, że wszystkie prace będą wykonywane wyłącznie na jednym stole, a także tylko na unikalnych kluczach. Załóżmy, że istnieje pewien „gorący” zestaw kluczy, który generuje główne obciążenie. Dlatego spróbujmy stworzyć ładunek z większymi rekordami (10 KB), także w partiach po 100, w 4 różnych tabelach i ograniczając zakres żądanych kluczy do 50 tys. Poniższy wykres pokazuje uruchomienie 40 wątków, każdy wątek czyta zestaw 100 kluczy i natychmiast zapisuje losowe 10 KB na tych kluczach.

Teoria i praktyka wykorzystania HBase
Podstawka: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki). Wersja HBase 1.2.0-cdh5.14.2.

Podczas obciążenia kilkakrotnie uruchomiono duże zagęszczenie, jak pokazano powyżej, bez tej procedury wydajność będzie stopniowo spadać, jednak podczas wykonywania pojawi się również dodatkowe obciążenie. Obniżki wynikają z różnych przyczyn. Czasami wątki kończyły działać i następowała przerwa podczas ich ponownego uruchamiania, czasami aplikacje innych firm powodowały obciążenie klastra.

Czytanie i natychmiastowe pisanie to jeden z najtrudniejszych scenariuszy pracy dla HBase. Jeśli wykonasz tylko małe żądania put, np. 100 bajtów, łącząc je w paczki po 10-50 tysięcy sztuk, możesz uzyskać setki tysięcy operacji na sekundę i podobnie sytuacja wygląda w przypadku żądań tylko do odczytu. Warto zaznaczyć, że wyniki są radykalnie lepsze od tych uzyskanych przez DataStax, przede wszystkim dzięki żądaniom w blokach po 50 tys.

Teoria i praktyka wykorzystania HBase
Podstawka: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40 GHz * 64 wątki). Wersja HBase 1.2.0-cdh5.14.2.

10. Wnioski

System ten jest dość elastycznie konfigurowany, ale wpływ dużej liczby parametrów nadal pozostaje nieznany. Część z nich została przetestowana, ale nie została uwzględniona w powstałym zbiorze testowym. Przykładowo wstępne eksperymenty wykazały niewielkie znaczenie takiego parametru jak DATA_BLOCK_ENCODING, który koduje informację przy użyciu wartości z sąsiednich komórek, co jest zrozumiałe w przypadku danych generowanych losowo. Jeśli używasz dużej liczby zduplikowanych obiektów, zysk może być znaczący. Ogólnie można powiedzieć, że HBase sprawia wrażenie dość poważnej i przemyślanej bazy danych, która potrafi być całkiem produktywna przy wykonywaniu operacji na dużych blokach danych. Zwłaszcza jeśli możliwe jest oddzielenie w czasie procesów czytania i pisania.

Jeśli Twoim zdaniem jest coś, co nie zostało wystarczająco ujawnione, jestem gotowy powiedzieć Ci bardziej szczegółowo. Zapraszamy do podzielenia się swoimi doświadczeniami lub dyskusji, jeśli się z czymś nie zgadzasz.

Źródło: www.habr.com

Dodaj komentarz