HBase
 sql >> Baza danych >  >> NoSQL >> HBase

Dzielenie i łączenie regionów Apache HBase

Ten wpis na blogu został opublikowany na Hortonworks.com przed fuzją z Cloudera. Niektóre linki, zasoby lub odniesienia mogą nie być już dokładne.

W tym poście zagłębimy się w jeden z głównych obszarów HBase. W szczególności przyjrzymy się, jak Apache HBase rozkłada obciążenie na regiony i zarządza podziałem regionów. HBase przechowuje wiersze danych w tabelach. Tabele są podzielone na fragmenty wierszy zwane „regionami”. Regiony te są rozproszone w klastrze, hostowane i udostępniane procesom klienta przez proces RegionServer. Region to ciągły zakres w przestrzeni klucza, co oznacza, że ​​wszystkie wiersze w tabeli sortujące między kluczem początkowym i końcowym regionu są przechowywane w tym samym regionie. Regiony nie nakładają się, tj. klucz jednorzędowy należy do dokładnie jednego regionu w dowolnym momencie. Region jest obsługiwany tylko przez jeden serwer regionu w dowolnym momencie, dzięki czemu HBase gwarantuje silną spójność w ramach jednego wiersza #. Razem z -ROOT- i .META. regiony, regiony tabeli skutecznie tworzą 3-poziomowe B-drzewo w celu zlokalizowania wiersza w tabeli.

Region z kolei składa się z wielu „Sklepów”, które odpowiadają rodzinom kolumn. Sklep zawiera jeden memstore i zero lub więcej plików sklepu. Dane dla każdej rodziny kolumn są przechowywane i dostępne oddzielnie.

Tabela zazwyczaj składa się z wielu regionów, które z kolei są hostowane przez wiele serwerów regionalnych. W związku z tym regiony są fizycznym mechanizmem używanym do dystrybucji obciążenia związanego z zapisem i zapytaniami na serwerach regionu. Gdy tabela jest tworzona po raz pierwszy, HBase domyślnie przydzieli tylko jeden region dla tabeli. Oznacza to, że początkowo wszystkie żądania będą kierowane do jednego serwera regionu, niezależnie od liczby serwerów regionu. Jest to główny powód, dla którego początkowe fazy ładowania danych do pustej tabeli nie mogą wykorzystać całej pojemności klastra.

Podział wstępny

Powodem, dla którego HBase tworzy tylko jeden region dla tabeli, jest to, że nie może wiedzieć, jak utworzyć punkty podziału w przestrzeni kluczy wiersza. Podejmowanie takich decyzji opiera się w dużej mierze na dystrybucji kluczy w Twoich danych. Zamiast zgadywać i zostawiać cię z konsekwencjami, HBase zapewnia narzędzia do zarządzania tym od klienta. W procesie zwanym wstępnym podziałem można utworzyć tabelę z wieloma regionami, dostarczając punkty podziału w momencie tworzenia tabeli. Ponieważ wstępne dzielenie zapewnia bardziej równomierne rozłożenie początkowego obciążenia w klastrze, należy zawsze rozważyć jego użycie, jeśli wcześniej znasz dystrybucję klucza. Jednak wstępne dzielenie wiąże się również z ryzykiem utworzenia regionów, które nie rozkładają naprawdę równomiernie obciążenia z powodu przekrzywienia danych lub obecności bardzo gorących lub dużych wierszy. Jeśli początkowy zestaw punktów podziału regionu zostanie źle wybrany, możesz skończyć z niejednorodnym rozkładem obciążenia, co z kolei ograniczy wydajność Twojego klastra.

Nie ma krótkiej odpowiedzi na temat optymalnej liczby regionów dla danego obciążenia, ale możesz zacząć od mniejszej wielokrotności liczby serwerów regionu jako liczby podziałów, a następnie pozwolić automatycznemu podziałowi zająć się resztą.

Jednym z problemów związanych ze wstępnym podziałem jest obliczanie punktów podziału dla tabeli. Możesz użyć narzędzia RegionSplitter. RegionSplitter tworzy punkty podziału przy użyciu wtykowego SplitAlgorithm. HexStringSplit i UniformSplit to dwa predefiniowane algorytmy. Pierwszego można użyć, jeśli klucze wierszy mają przedrostek dla ciągów szesnastkowych (np. jeśli używasz skrótów jako przedrostków). Ten ostatni dzieli przestrzeń na klucze równomiernie, zakładając, że są to losowe tablice bajtów. Możesz także zaimplementować swój niestandardowy SplitAlgorithm i użyć go z narzędzia RegionSplitter.

$ hbase org.apache.hadoop.hbase.util.RegionSplitter test_table HexStringSplit -c 10 -f f1

gdzie -c 10 określa żądaną liczbę regionów jako 10, a -f określa rodziny kolumn, które chcesz umieścić w tabeli, oddzielone „:”. Narzędzie utworzy tabelę o nazwie „test_table” z 10 regionami:

13/01/18 18:49:32 DEBUG hbase.HRegionInfo: Current INFO from scan results = {NAME => 'test_table,,1358563771069.acc1ad1b7962564fc3a43e5907e8db33.', STARTKEY => '', ENDKEY => '19999999', ENCODED => acc1ad1b7962564fc3a43e5907e8db33,}
13/01/18 18:49:32 DEBUG hbase.HRegionInfo: Current INFO from scan results = {NAME => 'test_table,19999999,1358563771096.37ec12df6bd0078f5573565af415c91b.', STARTKEY => '19999999', ENDKEY => '33333332', ENCODED => 37ec12df6bd0078f5573565af415c91b,}
...

Jeśli masz pod ręką punkty podziału, możesz również użyć powłoki HBase, aby utworzyć tabelę z żądanymi punktami podziału.

hbase(main):015:0> create 'test_table', 'f1', SPLITS=> ['a', 'b', 'c']

lub

$ echo -e  "anbnc" >/tmp/splits
hbase(main):015:0> create 'test_table', 'f1', SPLITSFILE=>'/tmp/splits'

Aby uzyskać optymalny rozkład obciążenia, należy pomyśleć o modelu danych i dystrybucji kluczy w celu wybrania prawidłowego algorytmu podziału lub punktów podziału. Bez względu na wybraną metodę tworzenia tabeli ze wstępnie określoną liczbą regionów, możesz teraz rozpocząć ładowanie danych do tabeli i zobaczyć, że obciążenie jest rozłożone w całym klastrze. Możesz pozwolić, aby automatyczny podział przejął kontrolę po rozpoczęciu pozyskiwania danych i stale monitorować całkowitą liczbę regionów w tabeli.

Automatyczne dzielenie

Niezależnie od tego, czy używany jest podział wstępny, czy nie, gdy region osiągnie określony limit, zostanie automatycznie podzielony na dwa regiony. Jeśli korzystasz z HBase 0.94 (dostarczanego z HDP-1.2), możesz skonfigurować, kiedy HBase zdecyduje się podzielić region i jak oblicza punkty podziału za pomocą podłączanego interfejsu API RegionSplitPolicy. Istnieje kilka wstępnie zdefiniowanych zasad podziału regionów:ConstantSizeRegionSplitPolicy, IncreasingToUpperBoundRegionSplitPolicy i KeyPrefixRegionSplitPolicy.

Pierwsza z nich to domyślna i jedyna dzielona polityka dla wersji HBase przed 0.94. Dzieli regiony, gdy łączny rozmiar danych dla jednego ze sklepów (odpowiadający rodzinie kolumn) w regionie jest większy niż skonfigurowany „hbase.hregion.max.filesize”, który ma domyślną wartość 10 GB. Ta zasada podziału jest idealna w przypadkach, w których zakończyłeś już podział i chcesz uzyskać mniejszą liczbę regionów na serwer regionu.

Domyślna zasada podziału dla HBase 0.94 i łącza trunkingowego to IncreasingToUpperBoundRegionSplitPolicy, która zapewnia bardziej agresywny podział na podstawie liczby regionów hostowanych na tym samym serwerze regionu. Zasada podziału wykorzystuje maksymalny rozmiar pliku sklepu w oparciu o wartość Min (R^2 * „hbase.hregion.memstore.flush.size”, „hbase.hregion.max.filesize”), gdzie R jest liczbą regionów tego samego tabela hostowana na tym samym serwerze regionu. Na przykład przy domyślnym rozmiarze opróżniania pamięci pamięci wynoszącym 128 MB i domyślnym maksymalnym rozmiarze magazynu wynoszącym 10 GB, pierwszy region na serwerze regionu zostanie podzielony zaraz po pierwszym opróżnieniu na 128 MB. Wraz ze wzrostem liczby regionów hostowanych na serwerze regionu, będzie on wykorzystywał coraz większe rozmiary podziału:512 MB, 1152 MB, 2 GB, 3,2 GB, 4,6 GB, 6,2 GB itd. Po osiągnięciu 9 regionów rozmiar podziału przekroczy skonfigurowany „hbase”. .hregion.max.filesize”, po czym od tego momentu będzie używany rozmiar podziału 10 GB. W przypadku obu tych algorytmów, niezależnie od tego, kiedy nastąpi podział, używanym punktem podziału jest klucz wiersza, który odpowiada punktowi środkowemu w „indeksie bloku” największego pliku magazynu w największym sklepie.

KeyPrefixRegionSplitPolicy to ciekawy dodatek do arsenału HBase. Możesz skonfigurować długość prefiksu dla kluczy wierszy w celu ich grupowania, a ta zasada podziału zapewnia, że ​​regiony nie są dzielone w środku grupy wierszy o tym samym prefiksie. Jeśli ustawiłeś prefiksy dla swoich kluczy, możesz użyć tej zasady podziału, aby upewnić się, że wiersze z tym samym prefiksem klucza wiersza zawsze trafiają do tego samego regionu. Ta grupa rekordów jest czasami określana jako „Grupy jednostek” lub „Grupy wierszy”. Jest to kluczowa cecha, gdy rozważamy użycie funkcji „lokalnych transakcji” (alternatywny link) w projekcie aplikacji.

Domyślną zasadę podziału można skonfigurować, ustawiając konfigurację „hbase.regionserver.region.split.policy” lub konfigurując deskryptor tabeli. Dla odważnych dusz możesz również zaimplementować własną niestandardową politykę podziału i podłączyć ją w czasie tworzenia tabeli lub modyfikując istniejącą tabelę:

HTableDescriptor tableDesc = new HTableDescriptor("example-table");
tableDesc.setValue(HTableDescriptor.SPLIT_POLICY, AwesomeSplitPolicy.class.getName());
//add columns etc
admin.createTable(tableDesc);

Jeśli przeprowadzasz wstępne dzielenie i chcesz ręcznie zarządzać podziałami regionów, możesz również wyłączyć podziały regionów, ustawiając „hbase.hregion.max.filesize” na wysoką liczbę i ustawiając zasady podziału na ConstantSizeRegionSplitPolicy. Należy jednak użyć wartości zabezpieczającej wynoszącej 100 GB, aby regiony nie przekroczyły możliwości serwera regionalnego. Możesz rozważyć wyłączenie automatycznego dzielenia i polegać na początkowym zestawie regionów z wstępnego podziału, na przykład, jeśli używasz jednolitych skrótów dla swoich prefiksów kluczy i możesz upewnić się, że ładowanie do odczytu/zapisu dla każdego regionu, a także jego rozmiar jest jednakowa we wszystkich regionach w tabeli.

Wymuszone podziały

HBase umożliwia również klientom wymuszenie podziału tabeli online po stronie klienta. Na przykład powłoka HBase może być użyta do podzielenia wszystkich regionów tabeli lub podzielenia regionu, opcjonalnie przez podanie punktu podziału.

hbase(main):024:0> split 'b07d0034cbe72cb040ae9cf66300a10c', 'b'
0 row(s) in 0.1620 seconds

Dzięki starannemu monitorowaniu rozkładu obciążenia HBase, jeśli zauważysz, że niektóre regiony otrzymują nierówne obciążenia, możesz rozważyć ręczne podzielenie tych regionów w celu wyrównania obciążenia i poprawy przepustowości. Innym powodem, dla którego warto dokonywać podziałów ręcznych, jest fakt, że początkowe podziały dla regionu okazały się nieoptymalne, a podziały automatyczne zostały wyłączone. Może się tak zdarzyć na przykład, jeśli dystrybucja danych zmienia się w czasie.

Jak wdrażane są podziały regionów

Ponieważ żądania zapisu są obsługiwane przez serwer regionu, gromadzą się one w systemie pamięci masowej o nazwie „memstore”. Po zapełnieniu memstore jego zawartość jest zapisywana na dysku jako dodatkowe pliki magazynu. To wydarzenie nazywa się „spłukiwaniem memstore”. W miarę gromadzenia się plików w sklepie, RegionServer „kompaktuje” je w połączone, większe pliki. Po zakończeniu każdego opróżniania lub kompaktowania żądanie podziału regionu jest umieszczane w kolejce, jeśli RegionSplitPolicy zdecyduje, że region powinien zostać podzielony na dwie części. Ponieważ wszystkie pliki danych w HBase są niezmienne, gdy nastąpi podział, nowo utworzone regiony podrzędne nie będą ponownie zapisywały wszystkich danych w nowych plikach. Zamiast tego utworzą małe pliki przypominające dowiązania symboliczne, zwane plikami referencyjnymi, które wskazują górną lub dolną część nadrzędnego pliku magazynu zgodnie z punktem podziału. Plik referencyjny będzie używany tak jak zwykły plik danych, ale tylko połowa rekordów. Region można podzielić tylko wtedy, gdy nie ma już odniesień do niezmiennych plików danych regionu nadrzędnego. Te pliki referencyjne są stopniowo czyszczone przez kompaktowanie, dzięki czemu region przestaje odwoływać się do plików nadrzędnych i może być dalej dzielony.

Chociaż podział regionu jest decyzją lokalną podejmowaną na serwerze RegionServer, sam proces podziału musi być koordynowany z wieloma podmiotami. RegionServer powiadamia Master przed i po podziale, aktualizuje .META. tabeli, aby klienci mogli odkrywać nowe regiony podrzędne, oraz zmieniać strukturę katalogów i pliki danych w HDFS. Split to proces wielozadaniowy. Aby umożliwić wycofywanie zmian w przypadku błędu, RegionServer prowadzi dziennik w pamięci o stanie wykonania. Kroki podejmowane przez RegionServer w celu wykonania podziału są przedstawione na rysunku 1. Każdy krok jest oznaczony swoim numerem. Akcje z serwerów regionalnych lub głównych są wyświetlane na czerwono, a akcje klientów są wyświetlane na zielono.

1. RegionServer decyduje lokalnie o podziale regionu i przygotowuje podział. W pierwszym kroku tworzy strefę w zookeeper w /hbase/region-in-transition/region-name w stanie SPLITTING.
2. Mistrz dowiaduje się o tym zwęźle, ponieważ ma on obserwatora nadrzędnego regionu w okresie przejściowym.
3. RegionServer tworzy podkatalog o nazwie „.splits” w katalogu regionu nadrzędnego w HDFS.
4. RegionServer zamyka region nadrzędny, wymusza opróżnianie pamięci podręcznej i oznacza region jako offline w lokalnych strukturach danych. W tym momencie żądania klientów przychodzące do regionu nadrzędnego będą zgłaszać NotServingRegionException. Klient ponowi próbę z pewnym opóźnieniem.
5. RegionServer tworzy katalogi regionów w katalogu .splits, dla regionów podrzędnych A i B oraz tworzy niezbędne struktury danych. Następnie dzieli pliki magazynu, w tym sensie, że tworzy dwa pliki referencyjne na plik magazynu w regionie nadrzędnym. Te pliki referencyjne będą wskazywać pliki regionów nadrzędnych.
6. RegionServer tworzy rzeczywisty katalog regionu w HDFS i przenosi pliki referencyjne dla każdej córki.
7. RegionServer wysyła żądanie Put do .META. i ustawia rodzica jako offline w .META. tabeli i dodaje informacje o regionach potomnych. W tym momencie nie będzie pojedynczych wpisów w .META. dla córek. Klienci zobaczą, że region nadrzędny jest podzielony, jeśli zeskanują .META., ale nie będą wiedzieć o córkach, dopóki nie pojawią się w .META.. Również, jeśli to Put to .META. się powiedzie, rodzic zostanie skutecznie podzielony. Jeśli RegionServer ulegnie awarii, zanim ten RPC się powiedzie, główny i następny serwer regionu otwierający region wyczyści brudny stan dotyczący podziału regionu. Po .META. aktualizacja, jednak podział regionów zostanie przesunięty do przodu przez Mistrza.
8. RegionServer otwiera równolegle córki, aby akceptować zapisy.
9. RegionServer dodaje córki A i B do .META. wraz z informacją, że goszczą regiony. Po tym momencie klienci mogą odkrywać nowe regiony i wysyłać żądania do nowego regionu. Klienci buforują plik .META. wpisy lokalnie, ale gdy wysyłają żądania do serwera regionu lub .META., ich pamięci podręczne zostaną unieważnione, a oni dowiedzą się o nowych regionach z .META..
10. RegionServer aktualizuje znode /hbase/region-in-transition/region-name w zookeeper do stanu SPLIT, aby master mógł się o tym dowiedzieć. Balancer może dowolnie ponownie przypisać regiony potomne do innych serwerów regionu, jeśli tak zdecyduje.
11. Po podziale meta i HDFS nadal będą zawierać odniesienia do regionu nadrzędnego. Te odniesienia zostaną usunięte, gdy kompaktowanie w regionach potomnych ponownie zapisze pliki danych. Zadania wyrzucania elementów bezużytecznych w systemie głównym okresowo sprawdzają, czy regiony podrzędne nadal odwołują się do plików nadrzędnych. Jeśli nie, region nadrzędny zostanie usunięty.

Scalanie regionów

W przeciwieństwie do dzielenia regionów, HBase w tym momencie nie zapewnia użytecznych narzędzi do scalania regionów. Chociaż istnieją narzędzia HMerge i Merge, nie nadają się one do ogólnego użytku. Obecnie nie ma obsługi tabel online ani funkcji automatycznego scalania. Jednak w przypadku problemów, takich jak OnlineMerge, automatyczne scalanie regionów zainicjowane przez Master, blokady odczytu/zapisu oparte na ZK dla operacji na tabelach, pracujemy nad stabilizacją podziałów regionów i umożliwieniem lepszej obsługi scalania regionów. Bądź na bieżąco!

Wniosek

Jak widać, pod maską HBase wykonuje wiele czynności porządkowych w celu zarządzania podziałami regionów i automatycznego dzielenia na fragmenty przez regiony. Jednak HBase zapewnia również niezbędne narzędzia związane z zarządzaniem regionem, dzięki czemu można zarządzać procesem podziału. Możesz również precyzyjnie kontrolować, kiedy i jak przebiegają podziały regionów za pomocą RegionSplitPolicy.

Liczba regionów w tabeli i sposób podziału tych regionów są kluczowymi czynnikami w zrozumieniu i dostrojeniu obciążenia klastra HBase. Jeśli możesz oszacować dystrybucję kluczy, powinieneś utworzyć tabelę z podziałem wstępnym, aby uzyskać optymalną wydajność ładowania początkowego. Możesz zacząć od mniejszej wielokrotności liczby serwerów regionu jako punktu początkowego dla początkowej liczby regionów i pozwolić przejąć automatycznemu podziałowi. Jeśli nie możesz poprawnie oszacować początkowych punktów podziału, lepiej po prostu utworzyć tabelę z jednym regionem i rozpocząć wstępne ładowanie z automatycznym podziałem i użyć IncreasingToUpperBoundRegionSplitPolicy. Należy jednak pamiętać, że całkowita liczba regionów ustabilizuje się w czasie, a bieżący zestaw punktów podziału regionów zostanie określony na podstawie danych otrzymanych do tej pory przez tabelę. Możesz chcieć monitorować rozkład obciążenia w regionach przez cały czas, a jeśli rozkład obciążenia zmienia się w czasie, użyj ręcznego podziału lub ustaw bardziej agresywne rozmiary podziału regionów. Na koniec możesz wypróbować nadchodzącą funkcję scalania online i dodać swój przypadek użycia.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wprowadzenie do federacji i architektury HDFS

  2. Jak HBase w CDP może wykorzystać S3 firmy Amazon?

  3. HBase i Hive – razem lepiej

  4. Koncepcje rozwoju aplikacji operacyjnej bazy danych Cloudera

  5. MapReduce tasowanie i sortowanie w Hadoop