{"id":55302,"date":"2020-01-17T00:00:00","date_gmt":"2020-01-16T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/teoriya-i-praktika-ispolzovaniya-hbase"},"modified":"2020-02-18T14:03:24","modified_gmt":"2020-02-18T11:03:24","slug":"teoriya-i-praktika-ispolzovaniya-hbase","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase","title":{"rendered":"Teoria i praktyka wykorzystania HBase","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Dzie\u0144 dobry! Nazywam si\u0119 Danil Lipowoj, nasz zesp\u00f3\u0142 w Sbertechu zacz\u0105\u0142 korzysta\u0107 z HBase jako magazyn danych operacyjnych. W trakcie jego badania zgromadzono do\u015bwiadczenia, kt\u00f3re chcia\u0142em usystematyzowa\u0107 i opisa\u0107 (mamy nadziej\u0119, \u017ce b\u0119dzie to przydatne dla wielu os\u00f3b). Wszystkie poni\u017cej przedstawione eksperymenty przeprowadzono na wersjach HBase 1.2.0-cdh5.14.2 i 2.0.0-cdh6.0.0-beta1. <\/p>\n<ol>\n<li>Og\u00f3lna architektura <\/li>\n<li>Zapisywanie danych w HBASE<\/li>\n<li>Odczytywanie danych z HBASE<\/li>\n<li>Buforowanie danych<\/li>\n<li>Przetwarzanie wsadowe danych MultiGet\/MultiPut<\/li>\n<li>Strategia podzia\u0142u tabel na regiony (sharding)<\/li>\n<li>Odporno\u015b\u0107 na awarie, kompresja i lokalno\u015b\u0107 danych<\/li>\n<li>Ustawienia i wydajno\u015b\u0107<\/li>\n<li>Testowanie obci\u0105\u017cenia<\/li>\n<li>Wnioski<\/li>\n<\/ol>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>1. Og\u00f3lna architektura<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/30800d8a48de4c52ff1650a4f1dec4c8.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nZapasowy Master nas\u0142uchuje heartbeat aktywnego na w\u0119\u017ale ZooKeeper i w przypadku jego znikni\u0119cia przejmuje funkcje mastera. <\/p>\n<h2>2. Zapisywanie danych w HBASE<\/h2>\n<p>\nNajpierw rozwa\u017cymy najprostszy przypadek \u2013 zapis obiektu klucz-warto\u015b\u0107 w pewnej tabeli przy u\u017cyciu put(rowkey). Klient najpierw musi ustali\u0107, gdzie znajduje si\u0119 serwer g\u0142\u00f3wny regionu (Root Region Server \u2014 RRS), kt\u00f3ry przechowuje tabel\u0119 hbase:meta. Informacje t\u0119 uzyskuje od ZooKeeper. Nast\u0119pnie zwraca si\u0119 do RRS i odczytuje tabel\u0119 hbase:meta, z kt\u00f3rej wyci\u0105ga informacj\u0119, kt\u00f3ry RegionServer (RS) odpowiada za przechowywanie danych dla podanego klucza rowkey w interesuj\u0105cej go tabeli. W celu dalszego wykorzystania tabela meta jest buforowana przez klienta, dlatego kolejne zapytania s\u0105 szybsze, bezpo\u015brednio do RS.<\/p>\n<p>Nast\u0119pnie RS, po otrzymaniu zapytania, najpierw zapisuje je w WriteAheadLog (WAL), co jest niezb\u0119dne do odtworzenia w przypadku awarii. Nast\u0119pnie zapisuje dane w MemStore. To bufor w pami\u0119ci, kt\u00f3ry zawiera posortowany zestaw kluczy danego regionu. Tabela mo\u017ce by\u0107 podzielona na regiony (partyacje), z kt\u00f3rych ka\u017cdy zawiera nieprzecinaj\u0105cy si\u0119 zbi\u00f3r kluczy. Pozwala to, umieszczaj\u0105c regiony na r\u00f3\u017cnych serwerach, uzyska\u0107 wy\u017csz\u0105 wydajno\u015b\u0107. Jednak mimo oczywisto\u015bci tego stwierdzenia, p\u00f3\u017aniej zobaczymy, \u017ce to nie dzia\u0142a we wszystkich przypadkach.<\/p>\n<p>Po umieszczeniu wpisu w MemStore klient otrzymuje odpowied\u017a, \u017ce wpis zosta\u0142 pomy\u015blnie zapisany. W rzeczywisto\u015bci jest on przechowywany tylko w buforze i trafi na dysk dopiero po up\u0142ywie pewnego czasu lub po zape\u0142nieniu go nowymi danymi. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/10f4d5d600a20882690f5cc81322bc41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nW trakcie wykonywania operacji \u201eDelete\u201d fizyczne usuni\u0119cie danych nie nast\u0119puje. Zostaj\u0105 one po prostu oznaczone jako usuni\u0119te, a samo zniszczenie ma miejsce w momencie wywo\u0142ania funkcji major compact, o kt\u00f3rej wi\u0119cej napisano w pkt 7.<\/p>\n<p>Pliki w formacie HFile gromadz\u0105 si\u0119 w HDFS, a od czasu do czasu uruchamiany jest proces minor compact, kt\u00f3ry po prostu \u0142\u0105czy ma\u0142e pliki w wi\u0119ksze, nie usuwaj\u0105c niczego. Z biegiem czasu przekszta\u0142ca si\u0119 to w problem, kt\u00f3ry objawia si\u0119 tylko przy odczycie danych (do tego wr\u00f3cimy nieco p\u00f3\u017aniej). <\/p>\n<p>Opr\u00f3cz opisanego powy\u017cej procesu \u0142adowania istnieje znacznie efektywniejsza procedura, w kt\u00f3rej zawarta jest chyba najsilniejsza strona tej bazy danych \u2013 BulkLoad. Polega ona na tym, \u017ce samodzielnie tworzymy HFiles i umieszczamy je na dysku, co pozwala na doskona\u0142\u0105 skalowalno\u015b\u0107 i osi\u0105ganie ca\u0142kiem przyzwoitych pr\u0119dko\u015bci. W istocie ograniczeniem jest tu nie HBase, lecz mo\u017cliwo\u015bci sprz\u0119towe. Poni\u017cej przedstawione s\u0105 wyniki \u0142adowania na klastrze sk\u0142adaj\u0105cym si\u0119 z 16 RegionServers i 16 NodeManager YARN (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki), wersja HBase 1.2.0-cdh5.14.2. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/4e4452b216eda3269a364ea97c49120f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWida\u0107, \u017ce zwi\u0119kszaj\u0105c liczb\u0119 partycji (region\u00f3w) w tabeli oraz liczby executor\u00f3w Spark, otrzymujemy przyrost pr\u0119dko\u015bci \u0142adowania. Pr\u0119dko\u015b\u0107 zale\u017cy r\u00f3wnie\u017c od obj\u0119to\u015bci zapisu. Du\u017ce bloki daj\u0105 przyrost w miarze MB\/s, ma\u0142e w liczbie wstawionych rekord\u00f3w w jednostce czasu, przy innych r\u00f3wnych warunkach. <\/p>\n<p>Mo\u017cna r\u00f3wnie\u017c uruchomi\u0107 \u0142adowanie w dw\u00f3ch tabelach jednocze\u015bnie i uzyska\u0107 podwojone pr\u0119dko\u015bci. Poni\u017cej wida\u0107, \u017ce zapis blok\u00f3w 10 KB od razu do dw\u00f3ch tabel odbywa si\u0119 z pr\u0119dko\u015bci\u0105 oko\u0142o 600 MB\/s w ka\u017cdej (\u0142\u0105cznie 1275 MB\/s), co odpowiada pr\u0119dko\u015bci zapisu do jednej tabeli 623 MB\/s (zob. nr 11 powy\u017cej).<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/9f1b4fc0c80b797111494d400e9ce332.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNatomiast drugi uruchomienie z zapisami 50 KB pokazuje, \u017ce pr\u0119dko\u015b\u0107 \u0142adowania ro\u015bnie ju\u017c nieznacznie, co wskazuje na zbli\u017canie si\u0119 do warto\u015bci granicznych. Nale\u017cy przy tym mie\u0107 na uwadze, \u017ce same mu HBASE praktycznie nie stawia si\u0119 obci\u0105\u017ce\u0144, wszystko co od niego wymagane, to najpierw oddanie danych z hbase:meta, a nast\u0119pnie po umieszczeniu HFiles, zrzucenie danych BlockCache i zapisanie bufora MemStore na dysk, je\u015bli nie jest pusty.<\/p>\n<h2>3. Odczyt danych z HBASE<\/h2>\n<p>\nJe\u015bli zak\u0142adamy, \u017ce wszystkie informacje z hbase:meta s\u0105 ju\u017c dost\u0119pne dla klienta (patrz pkt 2), zapytanie jest kierowane bezpo\u015brednio do tego RS, w kt\u00f3rym przechowywany jest poszukiwany klucz. Najpierw wyszukiwanie odbywa si\u0119 w MemCache. Niezale\u017cnie od tego, czy dane tam istniej\u0105, wyszukiwanie odbywa si\u0119 r\u00f3wnie\u017c w buforze BlockCache i w razie potrzeby w HFiles. Je\u015bli dane zosta\u0142y znalezione w pliku, s\u0105 one umieszczane w BlockCache i przy nast\u0119pnym zapytaniu b\u0119d\u0105 zwracane szybciej. Wyszukiwanie w HFile odbywa si\u0119 stosunkowo szybko dzi\u0119ki zastosowaniu filtru Blooma, tzn. po odczytaniu ma\u0142ej ilo\u015bci danych od razu ustala, czy ten plik zawiera poszukiwany klucz, a je\u015bli nie, przechodzi do nast\u0119pnego.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/a21b1b825a84cfd02507ec334e9452fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPo uzyskaniu danych z tych trzech \u017ar\u00f3de\u0142 RS formu\u0142uje odpowied\u017a. W szczeg\u00f3lno\u015bci mo\u017ce przekaza\u0107 od razu kilka znalezionych wersji obiektu, je\u015bli klient za\u017c\u0105da\u0142 wersjonowania.<\/p>\n<h2>4. Cache danych<\/h2>\n<p>\nBufory MemStore i BlockCache zajmuj\u0105 do 80% przydzielonej pami\u0119ci on-heap RS (pozosta\u0142e przeznaczone s\u0105 na zadania serwisowe RS). Je\u015bli typowy spos\u00f3b u\u017cytkowania polega na tym, \u017ce procesy zapisuj\u0105 i natychmiast odczytuj\u0105 te same dane, warto zmniejszy\u0107 BlockCache i zwi\u0119kszy\u0107 MemStore, poniewa\u017c przy zapisie dane do pami\u0119ci cache na odczyt nie trafiaj\u0105, co powoduje rzadsze wykorzystanie BlockCache. Bufor BlockCache sk\u0142ada si\u0119 z dw\u00f3ch cz\u0119\u015bci: LruBlockCache (zawsze on-heap) i BucketCache (zwykle off-heap lub na SSD). BucketCache warto zastosowa\u0107, gdy zapyta\u0144 o odczyt jest bardzo du\u017co i nie mieszcz\u0105 si\u0119 one w LruBlockCache, co prowadzi do intensywnej pracy Garbage Collector. Przy tym nie nale\u017cy oczekiwa\u0107 radykalnego wzrostu wydajno\u015bci z wykorzystania cache'u do odczytu, jednak do tego jeszcze wr\u00f3cimy w pkt 8.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/17d7791a998dd7da747cb7089dce1f10.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBlockCache jest jeden dla ca\u0142ego RS, a MemStore jest osobny dla ka\u017cdej tabeli (po jednym na ka\u017cdy Column Family).<\/p>\n<p>Jak <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.cloudera.com\/blog\/2012\/06\/hbase-write-path\/\">opisano<\/a><\/noindex> w teorii, przy zapisie dane do pami\u0119ci cache nie trafiaj\u0105 i rzeczywi\u015bcie, takie parametry CACHE_DATA_ON_WRITE dla tabeli oraz \u201eCache DATA on Write\u201d dla RS s\u0105 ustawione na false. Jednak w praktyce, je\u015bli zapiszesz dane w MemStore, a nast\u0119pnie zrzucisz je na dysk (w ten spos\u00f3b je czyszcz\u0105c), a nast\u0119pnie usuniesz powsta\u0142y plik, to wykonuj\u0105c zapytanie get, pomy\u015blnie uzyskasz dane. Co wi\u0119cej, nawet je\u015bli ca\u0142kowicie wy\u0142\u0105czysz BlockCache i wype\u0142nisz tabel\u0119 nowymi danymi, nast\u0119pnie wymusisz zrzut MemStore na dysk, usuniesz je i zapytasz z innej sesji, to i tak zostan\u0105 one sk\u0105d\u015b wydobyte. Tak wi\u0119c HBase przechowuje w sobie nie tylko dane, ale i tajemnicze zagadki.<\/p>\n<pre><code class=\"bash\">hbase(main):001:0&gt; create 'ns:magic', 'cf'\nStworzono tabel\u0119 ns:magic\nZaj\u0119\u0142o 1.1533 sekundy\nhbase(main):002:0&gt; put 'ns:magic', 'key1', 'cf:c', 'spr\u00f3buj_usun\u0105\u0107_mnie'\nZaj\u0119\u0142o 0.2610 sekundy\nhbase(main):003:0&gt; flush 'ns:magic'\nZaj\u0119\u0142o 0.6161 sekundy\nhdfs dfs -mv \/data\/hbase\/data\/ns\/magic\/* \/tmp\/trash\nhbase(main):002:0&gt; get 'ns:magic', 'key1'\n cf:c      znacznik_czasu=1534440690218, warto\u015b\u0107=spr\u00f3buj_usun\u0105\u0107_mnie\n<\/code><\/pre>\n<p>\nParametr \u201eCache DATA on Read\u201d jest ustawiony na false. Je\u015bli masz pomys\u0142y, zapraszam do om\u00f3wienia ich w komentarzach.<\/p>\n<h2>5. Przetwarzanie wsadowe danych MultiGet\/MultiPut<\/h2>\n<p>\nPrzetwarzanie pojedynczych \u017c\u0105da\u0144 (Get\/Put\/Delete) jest do\u015b\u0107 kosztown\u0105 operacj\u0105, dlatego zaleca si\u0119 \u0142\u0105czenie ich w List lub List, co pozwala na znaczn\u0105 popraw\u0119 wydajno\u015bci. Dotyczy to w szczeg\u00f3lno\u015bci operacji zapisu, a przy odczycie pojawia si\u0119 kolejna pu\u0142apka. Na poni\u017cszym wykresie pokazano czas odczytu 50 000 zapis\u00f3w z MemStore. Odczyt by\u0142 realizowany w jednym w\u0105tku, a na osi poziomej pokazano liczb\u0119 kluczy w \u017c\u0105daniu. Wida\u0107, \u017ce wraz z zwi\u0119kszeniem liczby kluczy w jednym \u017c\u0105daniu do tysi\u0105ca czas wykonania maleje, tzn. szybko\u015b\u0107 ro\u015bnie. Jednak\u017ce przy w\u0142\u0105czonym domy\u015blnym trybie MSLAB po tym progu zaczyna si\u0119 radykalny spadek wydajno\u015bci, przy czym im wi\u0119ksza obj\u0119to\u015b\u0107 danych w zapisie, tym d\u0142u\u017cszy czas operacji. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/42d3a77d66770a7fed03f83fecdca470.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTesty przeprowadzono na wirtualnej maszynie, 8 rdzeni, wersja HBase 2.0.0-cdh6.0.0-beta1.<\/p>\n<p>Tryb MSLAB ma na celu zmniejszenie fragmentacji pami\u0119ci heap, kt\u00f3ra powstaje w wyniku mieszania danych m\u0142odszych i starszych pokole\u0144. Jako rozwi\u0105zanie problemu, przy w\u0142\u0105czeniu MSLAB dane s\u0105 umieszczane w stosunkowo ma\u0142ych kom\u00f3rkach (chunk) i przetwarzane partiami. W rezultacie, kiedy obj\u0119to\u015b\u0107 w \u017c\u0105danym pakiecie danych przekracza przydzielony rozmiar, wydajno\u015b\u0107 nagle spada. Z drugiej strony, wy\u0142\u0105czenie tego trybu r\u00f3wnie\u017c nie jest po\u017c\u0105dane, poniewa\u017c prowadzi do zatrzyma\u0144 z powodu GC w momentach intensywnej pracy z danymi. Dobrym rozwi\u0105zaniem jest zwi\u0119kszenie obj\u0119to\u015bci kom\u00f3rki, w przypadku aktywnego zapisu przez put jednocze\u015bnie z odczytem. Warto zauwa\u017cy\u0107, \u017ce problem nie wyst\u0119puje, je\u015bli po zapisaniu wykonasz polecenie flush, kt\u00f3re zrzuca MemStore na dysk, lub je\u015bli nast\u0119puje za\u0142adunek za pomoc\u0105 BulkLoad. W poni\u017cszej tabeli pokazano, \u017ce \u017c\u0105dania z MemStore wi\u0119kszej obj\u0119to\u015bci (i tej samej liczby) prowadz\u0105 do op\u00f3\u017anie\u0144. Jednak zwi\u0119kszaj\u0105c chunksize, przywracamy czas przetwarzania do normy.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/0076215bd171257548f8a4c4d4229ba0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOpr\u00f3cz zwi\u0119kszenia chunksize pomocne jest podzia\u0142anie danych wed\u0142ug region\u00f3w, tj. splitowanie tabel. Prowadzi to do tego, \u017ce na ka\u017cdy region przypada mniejsza liczba zapyta\u0144, a je\u015bli mieszcz\u0105 si\u0119 one w kom\u00f3rce, odpowied\u017a pozostaje dobra.<\/p>\n<h2>6. Strategia podzia\u0142u tabel wed\u0142ug region\u00f3w (splitowanie)<\/h2>\n<p>\nPoniewa\u017c HBase jest przechowalni\u0105 key-value, a partycjonowanie odbywa si\u0119 wed\u0142ug klucza, niezwykle wa\u017cne jest, aby r\u00f3wnomiernie rozdziela\u0107 dane w\u015br\u00f3d wszystkich region\u00f3w. Na przyk\u0142ad, partycjonowanie takiej tabeli na trzy cz\u0119\u015bci prowadzi do tego, \u017ce dane b\u0119d\u0105 podzielone na trzy regiony:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/a811ae81e77b48dbf28ed86dbdc35739.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nCzasami prowadzi to do znacznego spowolnienia, je\u015bli w dalszej kolejno\u015bci wczytywane dane b\u0119d\u0105 mia\u0142y posta\u0107 np. warto\u015bci long, kt\u00f3re w wi\u0119kszo\u015bci zaczynaj\u0105 si\u0119 od tej samej cyfry, na przyk\u0142ad:<\/p>\n<p>1000001<br \/>\n1000002<br \/>\n\u2026<br \/>\n1100003<\/p>\n<p>Poniewa\u017c klucze s\u0105 przechowywane w postaci tablicy bajt\u00f3w, wszystkie one b\u0119d\u0105 zaczyna\u0142y si\u0119 jednakowo i odnosi\u0142y si\u0119 do jednego regionu #1 przechowuj\u0105cego ten zakres kluczy. Istnieje kilka strategii podzia\u0142u:<\/p>\n<p>HexStringSplit \u2013 przekszta\u0142ca klucz w ci\u0105g z szesnastkowym kodowaniem w zakresie \u201e00000000\u201d =&gt; \u201eFFFFFFFF\u201d, a na lewo wype\u0142nia zerami.<\/p>\n<p>UniformSplit \u2013 przekszta\u0142ca klucz w tablic\u0119 bajt\u00f3w z szesnastkowym kodowaniem w zakresie \u201e00\u201d =&gt; \u201eFF\u201d, a na prawo wype\u0142nia zerami.<\/p>\n<p>Ponadto mo\u017cna wskaza\u0107 dowolny zakres lub zestaw kluczy do podzia\u0142u oraz skonfigurowa\u0107 automatyczne splitowanie. Jednak jednym z najprostszych i najskuteczniejszych podej\u015b\u0107 jest UniformSplit i wykorzystanie z\u0142\u0105czenia hash, na przyk\u0142ad wy\u017cszej pary bajt\u00f3w uzyskanej z przepuszczenia klucza przez funkcj\u0119 CRC32(rowkey) oraz samego rowkey:<\/p>\n<p>hash + rowkey<\/p>\n<p>W\u00f3wczas wszystkie dane b\u0119d\u0105 r\u00f3wnomiernie rozprowadzane w\u015br\u00f3d region\u00f3w. Podczas odczytu pierwsze dwa bajty s\u0105 po prostu zrzucane, a pozostaje oryginalny klucz. RS kontroluje r\u00f3wnie\u017c liczb\u0119 danych i kluczy w regionie i w przypadku przekroczenia limit\u00f3w automatycznie dzieli go na cz\u0119\u015bci. <\/p>\n<h2>7. Odporno\u015b\u0107 na awarie i lokalno\u015b\u0107 danych<\/h2>\n<p>\nPoniewa\u017c za ka\u017cdy zestaw kluczy odpowiada tylko jeden region, rozwi\u0105zaniem problem\u00f3w zwi\u0105zanych z awariami RS lub wy\u0142\u0105czeniem z eksploatacji jest przechowywanie wszystkich niezb\u0119dnych danych w HDFS. W przypadku awarii RS, master wykrywa to poprzez brak heartbeat na w\u0119\u017ale ZooKeeper. W\u00f3wczas przypisuje obs\u0142ugiwany region innemu RS, a poniewa\u017c HFiles s\u0105 przechowywane w rozproszonej systemie plik\u00f3w, nowy w\u0142a\u015bciciel odczytuje je i kontynuuje obs\u0142ug\u0119 danych. Jednak\u017ce, poniewa\u017c cz\u0119\u015b\u0107 danych mo\u017ce znajdowa\u0107 si\u0119 w MemStore i nie zosta\u0142a jeszcze zapisana w HFiles, do przywracania historii operacji wykorzystuje si\u0119 WAL, kt\u00f3ry r\u00f3wnie\u017c jest przechowywany w HDFS. Po zatwierdzeniu zmian, RS jest w stanie odpowiada\u0107 na \u017c\u0105dania, jednak przeprowadzka prowadzi do sytuacji, w kt\u00f3rej cz\u0119\u015b\u0107 danych oraz procesy ich obs\u0142ugi znajduj\u0105 si\u0119 na r\u00f3\u017cnych w\u0119z\u0142ach, tj. lokalno\u015b\u0107 ulega zmniejszeniu. <\/p>\n<p>Rozwi\u0105zaniem problemu jest major compaction \u2013 ta procedura przenosi pliki na te w\u0119z\u0142y, kt\u00f3re za nie odpowiadaj\u0105 (tam, gdzie znajduj\u0105 si\u0119 ich regiony), w wyniku czego podczas tej procedury gwa\u0142townie wzrasta obci\u0105\u017cenie sieci i dysk\u00f3w. Jednak w dalszej perspektywie dost\u0119p do danych staje si\u0119 zauwa\u017calnie szybszy. Ponadto, major_compaction \u0142\u0105czy wszystkie HFiles w jeden plik w obr\u0119bie regionu, a tak\u017ce oczyszcza dane w zale\u017cno\u015bci od ustawie\u0144 tabeli. Na przyk\u0142ad, mo\u017cna okre\u015bli\u0107 liczb\u0119 wersji obiektu, kt\u00f3re nale\u017cy zachowa\u0107 lub czas jego \u017cycia, po kt\u00f3rego up\u0142ywie obiekt jest fizycznie usuwany.<\/p>\n<p>Ta procedura mo\u017ce mie\u0107 bardzo pozytywny wp\u0142yw na dzia\u0142anie HBase. Na poni\u017cszym obrazku wida\u0107, jak degradowa\u0142a si\u0119 wydajno\u015b\u0107 w wyniku intensywnego zapisu danych. Mo\u017cna zauwa\u017cy\u0107, jak do jednej tabeli 40 w\u0105tk\u00f3w zapisywa\u0142o i 40 w\u0105tk\u00f3w r\u00f3wnocze\u015bnie odczytywa\u0142o dane. W\u0105tki zapisuj\u0105ce tworz\u0105 coraz wi\u0119cej HFiles, kt\u00f3re s\u0105 odczytywane przez inne w\u0105tki. W wyniku tego coraz wi\u0119cej danych musi zosta\u0107 usuni\u0119tych z pami\u0119ci, a w ko\u0144cu zaczyna dzia\u0142a\u0107 GC, kt\u00f3ry praktycznie parali\u017cuje ca\u0142\u0105 prac\u0119. Uruchomienie major compaction doprowadzi\u0142o do oczyszczenia powsta\u0142ych zator\u00f3w i przywr\u00f3cenia wydajno\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/6c93b2c10c197663785d3de0bb185481.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nTest przeprowadzono na 3 DataNode i 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki). Wersja HBase 1.2.0-cdh5.14.2<\/p>\n<p>Warto zauwa\u017cy\u0107, \u017ce uruchomienie major compaction odby\u0142o si\u0119 na \u201e\u017cywej\u201d tabeli, do kt\u00f3rej aktywnie zapisywano i odczytywano dane. W sieci pojawia\u0142y si\u0119 twierdzenia, \u017ce mo\u017ce to prowadzi\u0107 do niepoprawnych odpowiedzi przy odczycie danych. W celu sprawdzenia uruchomiono proces, kt\u00f3ry generowa\u0142 nowe dane i zapisywa\u0142 je w tabeli. Nast\u0119pnie od razu je odczytywano i por\u00f3wnywano, czy uzyskana warto\u015b\u0107 zgadza si\u0119 z tym, co zapisano. W trakcie pracy tego procesu major compaction uruchamiano oko\u0142o 200 razy i nie zarejestrowano \u017cadnych awarii. Mo\u017cliwe, \u017ce problem pojawia si\u0119 rzadko i tylko podczas wysokiego obci\u0105\u017cenia, dlatego bezpieczniej jest jednak zaplanowa\u0107 zatrzymanie proces\u00f3w zapisu i odczytu oraz wykona\u0107 czyszczenie, aby nie dopuszcza\u0107 do takich spadk\u00f3w GC.<\/p>\n<p>R\u00f3wnie\u017c major compaction nie wp\u0142ywa na stan MemStore, aby zrzuci\u0107 go na dysk i przeprowadzi\u0107 kompaktacj\u0119, nale\u017cy u\u017cy\u0107 flush (connection.getAdmin().flush(TableName.valueOf(tblName))).<\/p>\n<h2>8. Ustawienia i wydajno\u015b\u0107<\/h2>\n<p>\nJak ju\u017c wspomniano, HBase odnosi najwi\u0119kszy sukces tam, gdzie nie wymaga wiele dzia\u0142a\u0144, przy wykonywaniu BulkLoad. To dotyczy jednak wi\u0119kszo\u015bci system\u00f3w i ludzi. Niemniej jednak to narz\u0119dzie nadaje si\u0119 raczej do masowego uk\u0142adania danych du\u017cymi blokami, natomiast je\u015bli proces wymaga wype\u0142nienia wielu konkurencyjnych zapyta\u0144 o odczyt i zapis, u\u017cywane s\u0105 opisane powy\u017cej polecenia Get i Put. Aby okre\u015bli\u0107 optymalne parametry, przeprowadzono uruchomienia przy r\u00f3\u017cnych kombinacjach parametr\u00f3w tabeli i ustawie\u0144:<\/p>\n<ul>\n<li>Uruchomiono 10 w\u0105tk\u00f3w jednocze\u015bnie 3 razy z rz\u0119du (nazwijmy to blokiem w\u0105tk\u00f3w). <\/li>\n<li>Czas pracy wszystkich w\u0105tk\u00f3w w bloku by\u0142 u\u015bredniany i stanowi\u0142 ko\u0144cowy wynik pracy bloku.<\/li>\n<li>Wszystkie w\u0105tki pracowa\u0142y z t\u0105 sam\u0105 tabel\u0105. <\/li>\n<li>Przed ka\u017cdym uruchomieniem bloku w\u0105tk\u00f3w wykonywano major compaction.<\/li>\n<li>Ka\u017cdy blok wykonywa\u0142 tylko jedn\u0105 z nast\u0119puj\u0105cych operacji: <\/li>\n<\/ul>\n<p>\n \u2014 Put<br \/>\n \u2014 Get<br \/>\n \u2014 Get+Put<\/p>\n<ul>\n<li>Ka\u017cdy blok wykonywa\u0142 50 000 powt\u00f3rze\u0144 swojej operacji.<\/li>\n<li>Rozmiar rekordu w bloku wynosi\u0142 100 bajt\u00f3w, 1000 bajt\u00f3w lub 10000 bajt\u00f3w (losowo).<\/li>\n<li>Bloki uruchamiano z r\u00f3\u017cn\u0105 liczb\u0105 \u017c\u0105danych kluczy (lub jeden klucz, lub 10).<\/li>\n<li>Bloki uruchamiano przy r\u00f3\u017cnych ustawieniach tabeli. Zmieniano parametry:<\/li>\n<\/ul>\n<p>\n \u2014 BlockCache = w\u0142\u0105czany lub wy\u0142\u0105czany<br \/>\n \u2014 BlockSize = 65 KB lub 16 KB<br \/>\n \u2014 Partycje = 1, 5 lub 30<br \/>\n \u2014 MSLAB = w\u0142\u0105czony lub wy\u0142\u0105czony<\/p>\n<p>W ten spos\u00f3b blok wygl\u0105da tak:<\/p>\n<p>a. W\u0142\u0105czano\/wy\u0142\u0105czano tryb MSLAB.<br \/>\nb. Tworzenie tabeli, dla kt\u00f3rej ustalono nast\u0119puj\u0105ce parametry: BlockCache = true\/none, BlockSize = 65\/16 Kb, Partycji = 1\/5\/30. <br \/>\nc. Ustalono kompresj\u0119 GZ.<br \/>\nd. Uruchomiono 10 w\u0105tk\u00f3w jednocze\u015bnie wykonuj\u0105cych 1\/10 operacji put\/get\/get+put w tej tabeli z zapisami po 100\/1000\/10000 bajt\u00f3w, wykonuj\u0105c 50 000 zapyta\u0144 z rz\u0119du (klucze losowe).<br \/>\ne. Punkt d powt\u00f3rzono trzy razy.<br \/>\nf. Czas pracy wszystkich w\u0105tk\u00f3w u\u015bredniono. <\/p>\n<p>Sprawdzono wszystkie mo\u017cliwe kombinacje. Przewidywalnie, przy zwi\u0119kszeniu rozmiaru zapisu pr\u0119dko\u015b\u0107 b\u0119dzie mala\u0142a, a wy\u0142\u0105czenie cache'owania spowoduje spowolnienie. Jednak celem by\u0142o zrozumienie stopnia i znaczenia wp\u0142ywu ka\u017cdego parametru, dlatego zebrane dane zosta\u0142y poddane liniowej regresji, co pozwala oceni\u0107 wiarygodno\u015b\u0107 za pomoc\u0105 statystyki t-studenta. Poni\u017cej przedstawione s\u0105 wyniki dzia\u0142ania blok\u00f3w wykonuj\u0105cych operacje Put. Pe\u0142ny zestaw kombinacji 2*2*3*2*3 = 144 warianty + 72, poniewa\u017c niekt\u00f3re zosta\u0142y wykonane dwukrotnie. W sumie 216 uruchomie\u0144:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/7a13c7a9b3ff1859976800f5d45cd51b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nTestowanie przeprowadzono na mini-klastrze sk\u0142adaj\u0105cym si\u0119 z 3 DataNode i 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki). Wersja HBase 1.2.0-cdh5.14.2.<\/p>\n<p>Najwy\u017csza pr\u0119dko\u015b\u0107 wstawiania 3.7 sekundy zosta\u0142a osi\u0105gni\u0119ta przy wy\u0142\u0105czonym trybie MSLAB, na tabeli z jedn\u0105 partycj\u0105, z w\u0142\u0105czonym BlockCache, BlockSize = 16, zapisach po 100 bajt\u00f3w w 10 sztukach w paczce.<br \/>\nNajni\u017csza pr\u0119dko\u015b\u0107 wstawiania 82.8 sekundy zosta\u0142a osi\u0105gni\u0119ta przy w\u0142\u0105czonym trybie MSLAB, na tabeli z jedn\u0105 partycj\u0105, z w\u0142\u0105czonym BlockCache, BlockSize = 16, zapisach po 10000 bajt\u00f3w w 1 sztuce.<\/p>\n<p>Teraz przyjrzyjmy si\u0119 modelowi. Widoczna jest dobra jako\u015b\u0107 modelu wed\u0142ug R2, ale ca\u0142kowicie jasne jest, \u017ce ekstrapolacja w tym przypadku jest niewskazana. Rzeczywiste zachowanie systemu przy zmianie parametr\u00f3w b\u0119dzie nieliniowe, ten model jest potrzebny nie do prognozowania, a do zrozumienia, co si\u0119 wydarzy\u0142o w obr\u0119bie zadanych parametr\u00f3w. Na przyk\u0142ad tutaj widzimy, wed\u0142ug kryterium Studenta, \u017ce dla operacji Put nie maj\u0105 znaczenia parametry BlockSize i BlockCache (co w sumie jest ca\u0142kiem przewidywalne):<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/2fb65d1809d53f2b47f4f8829a9efc65.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nA to, \u017ce zwi\u0119kszenie liczby partycji prowadzi do spadku wydajno\u015bci, jest nieco zaskakuj\u0105ce (ju\u017c widzieli\u015bmy pozytywny wp\u0142yw zwi\u0119kszenia liczby partycji przy BulkLoad), cho\u0107 jest to zrozumia\u0142e. Po pierwsze, aby przetworzy\u0107 dane, trzeba formu\u0142owa\u0107 zapytania do 30 region\u00f3w zamiast jednego, a obj\u0119to\u015b\u0107 danych nie jest na tyle du\u017ca, aby to przynios\u0142o korzy\u015b\u0107. Po drugie, ca\u0142kowity czas pracy determinuje najwolniejszy RS, a poniewa\u017c liczba DataNode jest mniejsza od liczby RS, cz\u0119\u015b\u0107 region\u00f3w ma zerow\u0105 lokalno\u015b\u0107. No i sp\u00f3jrzmy na pierwsz\u0105 pi\u0105tk\u0119 lider\u00f3w:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/8ad7e832879156eaa96e630458405cdc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nTeraz oce\u0144my wyniki wykonania blok\u00f3w Get:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/8a5dd45422c74e8815011d7e9b805ccb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nLiczba partycji straci\u0142a na znaczeniu, co prawdopodobnie t\u0142umaczy si\u0119 tym, \u017ce dane s\u0105 dobrze buforowane, a pami\u0119\u0107 podr\u0119czna do odczytu jest najwa\u017cniejszym (statystycznie) parametrem. Oczywi\u015bcie zwi\u0119kszenie liczby wiadomo\u015bci w zapytaniu jest r\u00f3wnie\u017c bardzo korzystne dla wydajno\u015bci. Najlepsze wyniki:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/9d237f9fdbeaf5412daec2fc2fa24b01.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNo i w ko\u0144cu sp\u00f3jrzmy na model bloku, kt\u00f3ry najpierw realizowa\u0142 get, a potem put:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/75137207a4a69acccad036882794094b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nTutaj wszystkie parametry s\u0105 znacz\u0105ce. A oto wyniki lider\u00f3w:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/c166933d81e86f36958e3af58297f876.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>9. Testy obci\u0105\u017ceniowe<\/h2>\n<p>\nNo i w ko\u0144cu uruchomimy w miar\u0119 rozs\u0105dne obci\u0105\u017cenie, ale zawsze ciekawiej jest, gdy jest z czym por\u00f3wnywa\u0107. Na stronie DataStax \u2013 kluczowego dewelopera Cassandy jest <noindex><a rel=\"nofollow\" href=\"https:\/\/www.datastax.com\/wp-content\/themes\/datastax-2014-08\/files\/NoSQL_Benchmarks_EndPoint.pdf\">wyniki<\/a><\/noindex> NT kilku baz NoSQL, w tym HBase wersji 0.98.6-1. \u0141adowanie odbywa\u0142o si\u0119 40 w\u0105tkami, rozmiar danych wynosi\u0142 100 bajt\u00f3w, dyski SSD. Wynik testowania operacji Read-Modify-Write wykaza\u0142 takie rezultaty.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/521e9dff60f462e6dabebc1234e028be.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n Z tego co zrozumia\u0142em, odczyt realizowany by\u0142 partiami po 100 rekord\u00f3w, a dla 16 nod\u00f3w HBase test DataStax wykaza\u0142 wydajno\u015b\u0107 10 tys. operacji na sekund\u0119. <\/p>\n<p>Dobrze, \u017ce w naszym klastrze r\u00f3wnie\u017c jest 16 nod\u00f3w, ale nie bardzo \"dobrze\", \u017ce na ka\u017cdym s\u0105 64 rdzenie (w\u0105tki), podczas gdy w te\u015bcie DataStax tylko po 4. Z drugiej strony maj\u0105 dyski SSD, a u nas HDD oraz nowsza wersja HBase, a wykorzystanie CPU podczas obci\u0105\u017cenia praktycznie nie wzrasta\u0142o (wizualnie o 5-10 procent). Niemniej spr\u00f3bujemy uruchomi\u0107 si\u0119 na tej konfiguracji. Ustawienia tabel s\u0105 domy\u015blne, odczyty odbywaj\u0105 si\u0119 w zakresie kluczy od 0 do 50 mln losowo (tzn. w zasadzie za ka\u017cdym razem nowe). W tabeli znajduje si\u0119 50 milion\u00f3w rekord\u00f3w, podzielonych na 64 partycje. Klucze s\u0105 haszowane z u\u017cyciem crc32. Ustawienia tabel s\u0105 domy\u015blne, MSLAB jest w\u0142\u0105czony. Uruchomienie 40 w\u0105tk\u00f3w, ka\u017cdy w\u0105tek odczytuje zestaw 100 losowych kluczy i natychmiast zapisuje wygenerowane 100 bajt\u00f3w z powrotem pod tymi kluczami. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/776490f01121cc434135f733311b7722.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n Stojak: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki). Wersja HBase 1.2.0-cdh5.14.2.<\/p>\n<p>\u015aredni wynik bli\u017cej 40 tys. operacji na sekund\u0119, co jest znacznie lepsze ni\u017c w te\u015bcie DataStax. Jednak w celach eksperymentalnych mo\u017cna nieco zmieni\u0107 warunki. Ma\u0142o prawdopodobne jest, aby ca\u0142a praca odbywa\u0142a si\u0119 wy\u0142\u0105cznie na jednej tabeli oraz tylko z unikalnymi kluczy. Za\u0142\u00f3\u017cmy, \u017ce istnieje pewien \u201egor\u0105cy\u201d zestaw kluczy, kt\u00f3ry generuje g\u0142\u00f3wne obci\u0105\u017cenie. Dlatego spr\u00f3bujemy stworzy\u0107 obci\u0105\u017cenie wi\u0119kszymi rekordami (10 KB), r\u00f3wnie\u017c porcjami po 100, w 4 r\u00f3\u017cnych tabelach i ograniczaj\u0105c zakres \u017c\u0105danych kluczy do 50 tys. Na poni\u017cszym wykresie przedstawiono uruchomienie 40 w\u0105tk\u00f3w, ka\u017cdy w\u0105tek odczytuje zestaw 100 kluczy i natychmiast zapisuje losowe 10 KB pod tymi kluczami z powrotem. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/30d29f1b98663e3c07cb2be20e93876a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nStojak: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki). Wersja HBase 1.2.0-cdh5.14.2.<\/p>\n<p>W trakcie obci\u0105\u017cenia kilka razy uruchamiano major compaction, jak pokazano powy\u017cej, bez tej procedury wydajno\u015b\u0107 stopniowo by spada\u0142a, jednak w trakcie wykonania pojawia si\u0119 r\u00f3wnie\u017c dodatkowe obci\u0105\u017cenie. Spadki spowodowane s\u0105 r\u00f3\u017cnymi przyczynami. Czasami w\u0105tki ko\u0144czy\u0142y prac\u0119 i podczas ich ponownego uruchamiania pojawia\u0142a si\u0119 przerwa, czasami zewn\u0119trzne aplikacje generowa\u0142y obci\u0105\u017cenie na klastrze.<\/p>\n<p>Czytanie i jednoczesne zapisywanie to jeden z najtrudniejszych scenariuszy pracy dla HBase. Je\u015bli wykonujemy tylko zapytania put o ma\u0142ej wielko\u015bci, na przyk\u0142ad po 100 bajt\u00f3w, \u0142\u0105cz\u0105c je w pakiety po 10-50 tys. sztuk, mo\u017cna uzyska\u0107 setki tysi\u0119cy operacji na sekund\u0119, a podobnie sytuacja wygl\u0105da w przypadku zapyta\u0144 tylko do odczytu. Warto zauwa\u017cy\u0107, \u017ce wyniki s\u0105 radykalnie lepsze ni\u017c te uzyskane przez DataStax, w du\u017cej mierze dzi\u0119ki zapytaniom blokowym po 50 tys.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria i praktyka wykorzystania HBase\" src=\"\/wp-content\/uploads\/2020\/01\/412bda50a55093224169f048ea2f863a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nStojak: 16 DataNode i 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 w\u0105tki). Wersja HBase 1.2.0-cdh5.14.2.<\/p>\n<h2>10. Wnioski<\/h2>\n<p>\nSystem ten jest wystarczaj\u0105co elastyczny, jednak wp\u0142yw du\u017cej liczby parametr\u00f3w wci\u0105\u017c pozostaje nieznany. Cz\u0119\u015b\u0107 z nich zosta\u0142a przetestowana, ale nie wesz\u0142a do ostatecznego zbioru test\u00f3w. Na przyk\u0142ad wst\u0119pne eksperymenty wykaza\u0142y niewielkie znaczenie takiego parametru jak DATA_BLOCK_ENCODING, kt\u00f3ry koduje informacje, korzystaj\u0105c z warto\u015bci z s\u0105siednich kom\u00f3rek, co jest ca\u0142kowicie zrozumia\u0142e dla danych generowanych losowo. W przypadku u\u017cycia du\u017cej liczby powtarzaj\u0105cych si\u0119 obiekt\u00f3w zysk mo\u017ce by\u0107 znacz\u0105cy. Og\u00f3lnie mo\u017cna powiedzie\u0107, \u017ce HBase sprawia wra\u017cenie do\u015b\u0107 powa\u017cnej i przemy\u015blanej bazy danych, kt\u00f3ra przy operacjach z du\u017cymi blokami danych mo\u017ce by\u0107 wystarczaj\u0105co wydajna. Szczeg\u00f3lnie je\u015bli istnieje mo\u017cliwo\u015b\u0107 roz\u0142o\u017cenia w czasie proces\u00f3w odczytu i zapisu.<\/p>\n<p>Je\u015bli co\u015b wed\u0142ug Ciebie nie zosta\u0142o wystarczaj\u0105co om\u00f3wione, ch\u0119tnie opowiem wi\u0119cej. Zach\u0119camy do dzielenia si\u0119 swoimi do\u015bwiadczeniami lub dyskusji, je\u015bli z czym\u015b si\u0119 nie zgadzasz.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/sberbank\/blog\/420425\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0430\u043d\u0438\u043b \u041b\u0438\u043f\u043e\u0432\u043e\u0439, \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432 \u0421\u0431\u0435\u0440\u0442\u0435\u0445\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HBase \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u0445\u043e\u0434\u0435 \u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u043a\u043e\u043f\u0438\u043b\u0441\u044f \u043e\u043f\u044b\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u043f\u0438\u0441\u0430\u0442\u044c (\u043d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e). \u0412\u0441\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b\u0438\u0441\u044c \u0441 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 HBase 1.2.0-cdh5.14.2 \u0438 2.0.0-cdh6.0.0-beta1. \u041e\u0431\u0449\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0417\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 HBASE \u0427\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 HBASE [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-55302","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0430\u043d\u0438\u043b \u041b\u0438\u043f\u043e\u0432\u043e\u0439, \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432 \u0421\u0431\u0435\u0440\u0442\u0435\u0445\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HBase \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f HBase | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0430\u043d\u0438\u043b \u041b\u0438\u043f\u043e\u0432\u043e\u0439, \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432 \u0421\u0431\u0435\u0440\u0442\u0435\u0445\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HBase \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-01-16T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:03:24+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Teoria i praktyka wykorzystania HBase | ProHoster","description":"Dzie\u0144 dobry! Nazywam si\u0119 Danil Lipowy, nasz zesp\u00f3\u0142 w Sbertechu zacz\u0105\u0142 u\u017cywa\u0107 HBase jako magazynu danych operacyjnych.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f HBase | ProHoster","og:description":"\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0430\u043d\u0438\u043b \u041b\u0438\u043f\u043e\u0432\u043e\u0439, \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432 \u0421\u0431\u0435\u0440\u0442\u0435\u0445\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HBase \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-01-16T21:00:00+00:00","article:modified_time":"2020-02-18T11:03:24+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"55302","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:46:28","updated":"2022-09-28 08:11:41","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/55302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=55302"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/55302\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=55302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=55302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=55302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}