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

HBase BlockCache 101

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.

Ten post na blogu pierwotnie pojawił się tutaj i jest tutaj w całości odtworzony.

HBase to rozproszona baza danych zbudowana wokół podstawowych koncepcji uporządkowanego dziennika zapisu i drzewa scalającego o strukturze dziennika. Podobnie jak w przypadku każdej bazy danych, zoptymalizowane operacje we/wy mają kluczowe znaczenie dla HBase. Jeśli to możliwe, priorytetem jest w ogóle nie wykonywać żadnych operacji we/wy. Oznacza to, że wykorzystanie pamięci i struktury pamięci podręcznej mają ogromne znaczenie. W tym celu HBase utrzymuje dwie struktury pamięci podręcznej:„magazyn pamięci” i „pamięć podręczna bloku”. Magazyn pamięci zaimplementowany jako MemStore , gromadzi edycje danych w miarę ich odbierania, buforując je w pamięci (1). Pamięć podręczna bloków, implementacja BlockCache interfejs, utrzymuje bloki danych rezydujące w pamięci po ich odczytaniu.

MemStore jest ważne, aby uzyskać dostęp do ostatnich zmian. Bez MemStore , dostęp do tych danych w takiej postaci, w jakiej zostały zapisane w dzienniku zapisu, wymagałby odczytania i zdeserializowania wpisów z tego pliku, co najmniej O(n) operacja. Zamiast tego MemStore utrzymuje strukturę listy pomijania, która korzysta z O(log n) koszt dostępu i nie wymaga dysku I/O. MemStore zawiera jednak tylko niewielką część danych przechowywanych w HBase.

Obsługa odczytów z BlockCache jest podstawowym mechanizmem, dzięki któremu HBase jest w stanie obsłużyć losowe odczyty z milisekundowym opóźnieniem. Gdy blok danych jest odczytywany z HDFS, jest buforowany w BlockCache . Kolejne odczyty sąsiednich danych – danych z tego samego bloku – nie podlegają karze we/wy w postaci ponownego pobrania tych danych z dysku (2). Jest to BlockCache na tym skupimy się w tym poście.

Bloki do pamięci podręcznej

Zanim zrozumiesz BlockCache , pomaga zrozumieć, czym dokładnie jest „blok” HBase. W kontekście HBase blok jest pojedynczą jednostką we/wy. Podczas zapisywania danych do HFile blok jest najmniejszą jednostką zapisanych danych. Podobnie, pojedynczy blok to najmniejsza ilość danych, jaką HBase może odczytać z powrotem z HFile. Uważaj, aby nie pomylić bloku HBase z blokiem HDFS lub blokami podstawowego systemu plików – wszystkie są różne (3).

Bloki HBase są dostępne w 4 odmianach: DATAMETAINDEXBLOOM .

DATA bloki przechowują dane użytkownika. Gdy BLOCKSIZE jest określony dla rodziny kolumn, jest to wskazówka dla tego rodzaju bloku. Pamiętaj, to tylko wskazówka. Podczas opróżniania MemStore , HBase dołoży wszelkich starań, aby przestrzegać tej wytycznej. Po każdej Cell zostanie zapisany, autor sprawdza, czy zapisana kwota jest>=celem BLOCKSIZE . Jeśli tak, zamknie bieżący blok i rozpocznie następny (4).

INDEXBLOOM klocki służą temu samemu celowi; oba są używane do przyspieszenia ścieżki odczytu. INDEX bloki zapewniają indeks nad Cell s zawarte w DATA Bloki. BLOOM bloki zawierają filtr rozkwitu na tych samych danych. Indeks pozwala czytelnikowi szybko dowiedzieć się, gdzie znajduje się Cell powinny być przechowywane. Filtr informuje czytelnika, kiedy Cell jest zdecydowanie nieobecny w danych.

Na koniec META bloki przechowują informacje o samym HFile i inne różne informacje – metadane, jak można się spodziewać. Bardziej kompleksowy przegląd formatów HFile i ról różnych typów bloków znajduje się w Apache HBase I/O – HFile.

HBase BlockCache i jego implementacje

Istnieje jeden BlockCache wystąpienie na serwerze regionu, co oznacza, że ​​wszystkie dane ze wszystkich regionów obsługiwanych przez ten serwer współdzielą tę samą pulę pamięci podręcznej (5). BlockCache jest tworzony podczas uruchamiania serwera regionu i jest zachowywany przez cały okres istnienia procesu. Tradycyjnie HBase udostępniał tylko jeden BlockCache implementacja: LruBlockCache . W wersji 0.92 wprowadzono pierwszą alternatywę w HBASE-4027:SlabCache . HBase 0.96 wprowadził inną opcję za pośrednictwem HBASE-7404, o nazwie BucketCache .

Kluczowa różnica między wypróbowanym i prawdziwym LruBlockCache a te alternatywy to sposób, w jaki zarządzają pamięcią. W szczególności LruBlockCache jest strukturą danych, która znajduje się w całości na stercie JVM, podczas gdy pozostałe dwie są w stanie korzystać z pamięci spoza sterty JVM. Jest to ważne rozróżnienie, ponieważ pamięć sterty JVM jest zarządzana przez moduł JVM Garbage Collector, a pozostałymi nie. W przypadku SlabCacheBucketCache , pomysł polega na zmniejszeniu presji GC doświadczanej przez proces serwera regionu poprzez zmniejszenie liczby obiektów przechowywanych na stercie.

LruBlockCache

To jest implementacja domyślna. Bloki danych są buforowane na stercie JVM przy użyciu tej implementacji. Jest podzielony na trzy obszary:jednodostępowy, wielodostępowy i w pamięci. Obszary mają rozmiar 25%, 50%, 25% całości BlockCache rozmiar odpowiednio (6). Blok początkowo odczytany z HDFS jest umieszczany w obszarze jednodostępowym. Kolejne dostępy promują ten blok w obszarze wielodostępu. Obszar w pamięci jest zarezerwowany dla bloków wczytanych z rodzin kolumn oznaczonych jako IN_MEMORY . Niezależnie od obszaru, stare bloki są eksmitowane, aby zrobić miejsce na nowe bloki przy użyciu algorytmu najrzadziej używanego, stąd „Lru” w „LruBlockCache”.

Pamięć podręczna płyty

Ta implementacja przydziela obszary pamięci poza stertą JVM za pomocą DirectByteBuffer s. Te obszary stanowią treść tego BlockCache . Dokładny obszar, w którym zostanie umieszczony konkretny blok, zależy od rozmiaru bloku. Domyślnie przydzielane są dwa obszary, które zużywają odpowiednio 80% i 20% całkowitego skonfigurowanego rozmiaru pamięci podręcznej poza stertą. Pierwsza służy do buforowania bloków, które mają w przybliżeniu rozmiar bloku docelowego (7). Ten ostatni zawiera bloki, które są około 2 razy większe od docelowego rozmiaru bloku. Blok jest umieszczany w najmniejszym obszarze, w którym może się zmieścić. Jeśli pamięć podręczna napotka blok większy niż może zmieścić się w którymkolwiek obszarze, blok ten nie zostanie zapisany w pamięci podręcznej. Jak LruBlockCache , eksmisja blokowa jest zarządzana za pomocą algorytmu LRU.

Pamięć podręczna

Ta implementacja może być skonfigurowana do działania w jednym z trzech różnych trybów: heapoffheapfile . Niezależnie od trybu pracy, BucketCache zarządza obszarami pamięci zwanymi „zasobnikami” do przechowywania buforowanych bloków. Każdy kubeł jest tworzony z docelowym rozmiarem bloku. heap implementacja tworzy te wiadra na stercie JVM; offheap implementacja korzysta z DirectByteByffers do zarządzania zasobnikami poza stertą JVM; file mode oczekuje ścieżki do pliku w systemie plików, w którym tworzone są zasobniki. file tryb jest przeznaczony do użytku z magazynem kopii zapasowych o niskim opóźnieniu — systemem plików w pamięci lub być może plikiem znajdującym się na dysku SSD (8). Niezależnie od trybu, BucketCache tworzy 14 wiader o różnych rozmiarach. Wykorzystuje częstotliwość dostępu blokowego do informowania o wykorzystaniu, podobnie jak LruBlockCache , i ma taki sam podział jednodostępowy, wielodostępowy i w pamięci wynoszący 25%, 50%, 25%. Podobnie jak domyślna pamięć podręczna, eksmisja bloków jest zarządzana za pomocą algorytmu LRU.

Buforowanie wielopoziomowe

Zarówno SlabCacheBucketCache są przeznaczone do użycia w ramach wielopoziomowej strategii buforowania. W związku z tym pewna część całkowitego BlockCache rozmiar jest przydzielony do LruBlockCache instancja. Ta instancja działa jako pamięć podręczna pierwszego poziomu, „L1,”, podczas gdy druga instancja pamięci podręcznej jest traktowana jako pamięć podręczna drugiego poziomu, „L2”. Jednak interakcja między LruBlockCacheSlabCache różni się od tego, w jaki sposób LruBlockCacheBucketCache interakcji.

SlabCache strategia o nazwie DoubleBlockCache , ma zawsze buforować bloki w obu pamięciach podręcznych L1 i L2. Dwa poziomy pamięci podręcznej działają niezależnie:oba są sprawdzane podczas pobierania bloku i każdy eksmituje bloki bez względu na drugi. BucketCache strategia o nazwie CombinedBlockCache , używa pamięci podręcznej L1 wyłącznie dla bloków Bloom i Index. Bloki danych są wysyłane bezpośrednio do pamięci podręcznej L2. W przypadku usunięcia bloku L1, zamiast całkowitego odrzucenia, blok ten jest degradowany do pamięci podręcznej L2.

Który wybrać?

Istnieją dwa powody, dla których warto rozważyć włączenie jednej z alternatyw BlockCache wdrożenia. Pierwsza to po prostu ilość pamięci RAM, którą możesz przeznaczyć na serwer regionu. Mądrość społeczności uznaje, że górna granica sterty JVM, jeśli chodzi o serwer regionu, wynosi od 14 GB do 31 GB (9). Dokładny limit zwykle zależy od kombinacji profilu sprzętowego, konfiguracji klastra, kształtu tabel danych i wzorców dostępu do aplikacji. Będziesz wiedział, że znalazłeś się w niebezpiecznej strefie, gdy GC zatrzyma się i RegionTooBusyException zaczną zalewać Twoje logi.

Innym momentem, w którym należy rozważyć alternatywną pamięć podręczną, jest opóźnienie odpowiedzi naprawdę sprawy. Utrzymanie sterty w okolicach 8-12 GB pozwala kolektorowi CMS działać bardzo płynnie (10), co ma wymierny wpływ na 99. percentyl czasu odpowiedzi. Biorąc pod uwagę to ograniczenie, jedynym wyborem jest zbadanie alternatywnego odśmiecacza pamięci lub skorzystanie z jednej z tych implementacji ze sterty na przejażdżkę.

Ta druga opcja jest dokładnie tym, co zrobiłem. W następnym poście przedstawię kilka nienaukowych, ale pouczających wyników eksperymentów, w których porównuję czasy odpowiedzi dla różnych BlockCache implementacje.

Jak zawsze, bądź na bieżąco i kontynuuj z HBase!

1: MemStore gromadzi edycje danych w miarę ich odbierania, buforując je w pamięci. Służy to dwóm celom:zwiększa całkowitą ilość danych zapisanych na dysku podczas jednej operacji i zachowuje te ostatnie zmiany w pamięci do późniejszego dostępu w postaci odczytów o niskim opóźnieniu. To pierwsze jest ważne, ponieważ utrzymuje fragmenty zapisu HBase z grubsza zsynchronizowane z rozmiarami bloków HDFS, dopasowując wzorce dostępu HBase do podstawowej pamięci masowej HDFS. To ostatnie nie wymaga wyjaśnień, ułatwiając odczytywanie ostatnio zapisanych danych. Warto zaznaczyć, że struktura ta nie wpływa na trwałość danych. Zmiany są również zapisywane w uporządkowanym dzienniku zapisu, HLog , który obejmuje operację dołączania HDFS w konfigurowalnych odstępach czasu, zwykle natychmiast.

2:Najlepszym scenariuszem jest ponowne wczytanie danych z lokalnego systemu plików. HDFS to w końcu rozproszony system plików, więc najgorszy przypadek wymaga odczytania tego bloku przez sieć. HBase dokłada wszelkich starań, aby zachować lokalność danych. Te dwa artykuły zapewniają dogłębne spojrzenie na to, co oznacza lokalizacja danych dla HBase i jak jest zarządzana.

3:Bloki systemu plików, HDFS i HBase są różne, ale powiązane. Nowoczesny podsystem we/wy składa się z wielu warstw abstrakcji nałożonych na abstrakcję. Rdzeniem tej abstrakcji jest koncepcja pojedynczej jednostki danych, określanej jako „blok”. W związku z tym wszystkie trzy z tych warstw pamięci definiują swój własny blok, każdy o własnym rozmiarze. Ogólnie rzecz biorąc, większy rozmiar bloku oznacza zwiększoną przepustowość dostępu sekwencyjnego. Mniejszy rozmiar bloku ułatwia szybszy dostęp losowy.

4:Umieszczenie BLOCKSIZE sprawdzenie po zapisaniu danych ma dwie konsekwencje. Pojedyncza Cell to najmniejsza jednostka danych zapisywana w DATA blok. Oznacza to również Cell nie może obejmować wielu bloków.

5:to coś innego niż MemStore , dla którego istnieje osobna instancja dla każdego regionu hostowanego przez serwer regionu.

6:Do niedawna te partycje pamięci były zdefiniowane statycznie; nie było możliwości obejścia podziału 25/50/25. Dany segment, na przykład obszar wielodostępowy, może urosnąć do poziomu przekraczającego 50% przydziału, o ile inne obszary będą niewykorzystane. Zwiększone wykorzystanie w pozostałych obszarach spowoduje eksmisję wejść z obszaru wielodostępowego do czasu osiągnięcia salda 25/50/25. Operator nie mógł zmienić tych domyślnych rozmiarów. HBASE-10263, dostarczany w HBase 0.98.0, wprowadza parametry konfiguracyjne dla tych rozmiarów. Elastyczne zachowanie zostaje zachowane.

7:„W przybliżeniu” biznes polega na umożliwieniu trochę swobody w rozmiarach bloków. Rozmiar bloku HBase jest przybliżonym celem lub wskazówką, a nie ściśle wymuszonym ograniczeniem. Dokładny rozmiar konkretnego bloku danych będzie zależał od rozmiaru bloku docelowego i rozmiaru Cell zawartych w nich wartości. Wskazówka dotycząca rozmiaru bloku jest określona jako domyślny rozmiar bloku 64kb.

8:Korzystanie z BucketCachefile tryb z trwałym magazynem zapasowym ma jeszcze jedną zaletę:trwałość. Podczas uruchamiania wyszuka istniejące dane w pamięci podręcznej i zweryfikuje ich poprawność.

9:Jak rozumiem, istnieją dwa elementy, które zalecają górną granicę tego zakresu. Pierwszym z nich jest ograniczenie adresowalności obiektów JVM. JVM może odwoływać się do obiektu na stercie za pomocą 32-bitowego adresu względnego zamiast pełnego 64-bitowego adresu natywnego. Ta optymalizacja jest możliwa tylko wtedy, gdy całkowity rozmiar sterty jest mniejszy niż 32 GB. Zobacz Skompresowane ups, aby uzyskać więcej informacji. Drugi to zdolność garbage collectora do nadążania za ilością obiektów odchodzących w systemie. Z tego, co mogę powiedzieć, trzy źródła rezygnacji obiektów to MemStoreBlockCache i operacje sieciowe. Pierwszy jest łagodzony przez MemSlab funkcja, domyślnie włączona. Na drugi wpływ ma rozmiar zestawu danych w porównaniu z rozmiarem pamięci podręcznej. Trzeciego nie można pomóc, o ile HBase korzysta ze stosu sieciowego, który opiera się na kopiowaniu danych.

10:Podobnie jak w przypadku 8, zakłada się „nowoczesny sprzęt”. Interakcje tutaj są dość złożone i znacznie wykraczają poza zakres pojedynczego wpisu na blogu.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak wdrożyć modele ML do produkcji

  2. Budowanie skalowalnego procesu przy użyciu NiFi, Kafka i HBase na CDP

  3. Ograniczenia Hadoop, sposoby rozwiązania wad Hadoop

  4. Hadoop — samouczki Apache Hadoop dla początkujących

  5. 6 najlepszych technik optymalizacji pracy MapReduce