Tento blogový příspěvek byl publikován na Hortonworks.com před sloučením s Cloudera. Některé odkazy, zdroje nebo reference již nemusí být přesné.
Tento blogový příspěvek se původně objevil zde a je zde celý reprodukován.
HBase je distribuovaná databáze postavená na základních konceptech uspořádaného protokolu zápisu a stromu sloučení se strukturou protokolu. Jako u každé databáze je pro HBase zásadním zájmem optimalizované I/O. Je-li to možné, prioritou je neprovádět vůbec žádné I/O. To znamená, že využití paměti a struktury mezipaměti jsou nanejvýš důležité. Za tímto účelem HBase udržuje dvě struktury mezipaměti:„paměťové úložiště“ a „blokovací mezipaměť“. Úložiště paměti implementované jako MemStore
, shromažďuje úpravy dat tak, jak jsou přijímány, a ukládá je do vyrovnávací paměti (1). Bloková mezipaměť, implementace BlockCache
rozhraní, uchovává datové bloky po přečtení v paměti.
MemStore
je důležité pro přístup k posledním úpravám. Bez MemStore
, přístup k těmto datům, jak byla zapsána do protokolu zápisu, by vyžadoval čtení a deserializaci položek zpět z tohoto souboru, alespoň O(n)
úkon. Místo toho MemStore
udržuje strukturu skiplistu, která má znak O(log n)
náklady na přístup a nevyžaduje žádný vstup/výstup na disku. MemStore
obsahuje však jen malý kousek dat uložených v HBase.
Servisní čtení z BlockCache
je primární mechanismus, jehož prostřednictvím je HBase schopna obsluhovat náhodná čtení s milisekundovou latencí. Když je datový blok načten z HDFS, uloží se do mezipaměti BlockCache
. Následná čtení sousedních dat – dat ze stejného bloku – netrpí I/O penalizací opětovného získání těchto dat z disku (2). Je to BlockCache
to bude zbývající zaměření tohoto příspěvku.
Blokuje do mezipaměti
Než pochopíte BlockCache
pomáhá pochopit, co přesně je „blok“ HBase. V kontextu HBase je blok jedinou jednotkou I/O. Při zápisu dat do HFfile je blok nejmenší jednotkou zapsaných dat. Podobně, jeden blok je nejmenší množství dat, které může HBase přečíst zpět ze souboru HFile. Dávejte pozor, abyste si nepletli blok HBase s blokem HDFS nebo s bloky základního souborového systému – všechny se liší (3).
Bloky HBase se dodávají ve 4 variantách: DATA
, META
, INDEX
a BLOOM
.
DATA
bloky ukládají uživatelská data. Když se zobrazí BLOCKSIZE
je specifikován pro rodinu sloupců, je to nápověda pro tento typ bloku. Pozor, je to jen náznak. Při proplachování MemStore
, HBase udělá vše pro to, aby dodržela tento pokyn. Po každé Cell
je zapsán, zapisovatel zkontroluje, zda je zapsaná částka>=cílová BLOCKSIZE
. Pokud ano, zavře aktuální blok a spustí další (4).
INDEX
a BLOOM
bloky slouží stejnému cíli; oba se používají ke zrychlení cesty čtení. INDEX
bloky poskytují index přes Cell
jsou obsaženy v DATA
bloky. BLOOM
bloky obsahují filtr květů přes stejná data. Index umožňuje čtenáři rychle zjistit, kde se nachází Cell
by měly být uloženy. Filtr sdělí čtenáři, když je Cell
v datech rozhodně chybí.
Nakonec META
bloky ukládají informace o samotném HFfile a další různé informace – metadata, jak byste mohli očekávat. Podrobnější přehled formátů HFile a rolí různých typů bloků je uveden v Apache HBase I/O – HFile.
HBase BlockCache a její implementace
Existuje jedna BlockCache
instance na serveru oblasti, což znamená, že všechna data ze všech oblastí hostovaných tímto serverem sdílejí stejný fond mezipaměti (5). BlockCache
je vytvořena při spuštění regionálního serveru a je zachována po celou dobu životnosti procesu. HBase tradičně poskytoval pouze jednu BlockCache
implementace: LruBlockCache
. Vydání 0.92 představilo první alternativu v HBASE-4027: SlabCache
. HBase 0.96 představil další možnost prostřednictvím HBASE-7404, nazvanou BucketCache
.
Klíčový rozdíl mezi osvědčenou LruBlockCache
a těmito alternativami je způsob, jakým spravují paměť. Konkrétně LruBlockCache
je datová struktura, která je umístěna výhradně na haldě JVM, zatímco ostatní dvě jsou schopny využívat paměť mimo haldu JVM. To je důležitý rozdíl, protože paměť haldy JVM spravuje JVM Garbage Collector, zatímco ostatní nikoli. V případě SlabCache
a BucketCache
, cílem je snížit tlak GC, kterému čelí proces regionálního serveru, snížením počtu objektů uchovávaných na hromadě.
LruBlockCache
Toto je výchozí implementace. Datové bloky jsou pomocí této implementace ukládány do mezipaměti v haldě JVM. Je rozdělena do tří oblastí:s jedním přístupem, s více přístupem a v paměti. Oblasti mají velikost 25 %, 50 %, 25 % z celkového počtu BlockCache
velikost, respektive (6). Blok, který byl původně načten z HDFS, je vyplněn v oblasti s jedním přístupem. Po sobě jdoucí přístupy posouvají tento blok do oblasti s více přístupy. Oblast v paměti je vyhrazena pro bloky načtené z rodin sloupců označených jako IN_MEMORY
. Bez ohledu na oblast jsou staré bloky vystěhovány, aby se uvolnilo místo pro nové bloky pomocí nejméně nedávno použitého algoritmu, tedy „Lru“ v „LruBlockCache“.
SlabCache
Tato implementace přiděluje oblasti paměti mimo haldu JVM pomocí DirectByteBuffer
s. Tyto oblasti poskytují tělo této BlockCache
. Přesná oblast, do které bude konkrétní blok umístěn, závisí na velikosti bloku. Ve výchozím nastavení jsou přiděleny dvě oblasti, které spotřebují 80 % a 20 % celkové nakonfigurované velikosti mezipaměti mimo haldu. První se používá k ukládání bloků, které mají přibližně cílovou velikost bloku (7). Ten obsahuje bloky, které jsou přibližně 2x větší než velikost cílového bloku. Blok se umístí do nejmenší oblasti, kam se vejde. Pokud mezipaměť narazí na blok větší, než se vejde do kterékoli oblasti, tento blok nebude uložen do mezipaměti. Jako LruBlockCache
, blokové vystěhování je řízeno pomocí algoritmu LRU.
BucketCache
Tuto implementaci lze nakonfigurovat tak, aby fungovala v jednom ze tří různých režimů: heap
, offheap
a file
. Bez ohledu na provozní režim BucketCache
spravuje oblasti paměti zvané „buckety“ pro ukládání bloků uložených v mezipaměti. Každý segment je vytvořen s cílovou velikostí bloku. heap
implementace vytvoří tyto buckety na hromadě JVM; offheap
implementace používá DirectByteByffers
ke správě bucketů mimo haldu JVM; file
mode očekává cestu k souboru na souborovém systému, kde jsou vytvořeny buckety. file
režim je určen pro použití se záložním úložištěm s nízkou latencí – souborovým systémem v paměti nebo možná souborem uloženým na úložišti SSD (8). Bez ohledu na režim BucketCache
vytvoří 14 kbelíků různých velikostí. Používá frekvenci blokovaného přístupu k informování o využití, stejně jako LruBlockCache
a má stejné rozdělení s jedním přístupem, více přístupy a v paměti 25 %, 50 %, 25 %. Stejně jako výchozí mezipaměť je vyřazení bloků spravováno pomocí algoritmu LRU.
Víceúrovňové ukládání do mezipaměti
Oba SlabCache
a BucketCache
jsou navrženy pro použití jako součást víceúrovňové strategie ukládání do mezipaměti. Tedy určitou část celkového BlockCache
velikost je přidělena LruBlockCache
instance. Tato instance funguje jako mezipaměť první úrovně, „L1“, zatímco druhá instance mezipaměti je považována za mezipaměť druhé úrovně, „L2“. Interakce mezi LruBlockCache
a SlabCache
se liší od způsobu LruBlockCache
a BucketCache
interagovat.
SlabCache
strategii s názvem DoubleBlockCache
, je vždy ukládat bloky do mezipaměti L1 i L2. Dvě úrovně mezipaměti fungují nezávisle:obě jsou kontrolovány při načítání bloku a každá vyřazuje bloky bez ohledu na druhou. BucketCache
strategii s názvem CombinedBlockCache
, používá mezipaměť L1 výhradně pro bloky Bloom a Index. Datové bloky jsou odesílány přímo do mezipaměti L2. V případě vyklizení bloku L1 je tento blok namísto úplného vyřazení degradován do mezipaměti L2.
Který vybrat?
Existují dva důvody, proč zvážit povolení jedné z alternativních BlockCache
implementací. První je jednoduše množství paměti RAM, kterou můžete věnovat regionálnímu serveru. Komunitní moudrost uznává, že horní hranice haldy JVM, pokud jde o server regionu, je někde mezi 14 GB a 31 GB (9). Přesný limit obvykle závisí na kombinaci hardwarového profilu, konfigurace clusteru, tvaru datových tabulek a vzorů přístupu aplikací. Když se GC pozastaví a RegionTooBusyException
, poznáte, že jste vstoupili do nebezpečné zóny začnou zahlcovat vaše protokoly.
Další čas, kdy je vhodné zvážit alternativní mezipaměť, je, když latence odezvy skutečně záležitosti. Udržování hromady kolem 8–12 GB umožňuje, aby kolektor CMS běžel velmi hladce (10), což má měřitelný dopad na 99. percentil doby odezvy. Vzhledem k tomuto omezení je jedinou možností prozkoumat alternativní sběrač odpadu nebo vyzkoušet jednu z těchto implementací mimo hromadu.
Tato druhá možnost je přesně to, co jsem udělal. V příštím příspěvku se podělím o některé nevědecké, ale informativní výsledky experimentů, kde porovnám doby odezvy pro různé BlockCache
implementací.
Jako vždy zůstaňte naladěni a pokračujte s HBase!
1: MemStore
shromažďuje úpravy dat tak, jak jsou přijímány, a ukládá je do paměti. To slouží dvěma účelům:zvyšuje celkové množství dat zapsaných na disk v jedné operaci a uchovává tyto nedávné změny v paměti pro následný přístup ve formě čtení s nízkou latencí. První z nich je důležitý, protože udržuje bloky zápisu HBase zhruba v synchronizaci s velikostmi bloků HDFS, čímž se přizpůsobují přístupové vzory HBase se základním úložištěm HDFS. To druhé je samovysvětlující a usnadňuje požadavky na čtení nedávno zapsaných dat. Stojí za zmínku, že tato struktura se nepodílí na trvanlivosti dat. Úpravy se také zapisují do uspořádaného protokolu zápisu, HLog
, která zahrnuje operaci připojení HDFS v konfigurovatelném intervalu, obvykle okamžitě.
2:Opětovné načtení dat z místního souborového systému je nejlepším scénářem. HDFS je koneckonců distribuovaný souborový systém, takže nejhorší případ vyžaduje čtení tohoto bloku přes síť. HBase dělá maximum pro udržení datové lokality. Tyto dva články poskytují podrobný pohled na to, co znamená datová lokalita pro HBase a jak je spravována.
3:Systém souborů, HDFS a bloky HBase jsou různé, ale souvisí. Moderní I/O subsystém je mnoho vrstev abstrakce na vrcholu abstrakce. Jádrem této abstrakce je koncept jediné jednotky dat, označované jako „blok“. Všechny tři tyto vrstvy úložiště tedy definují svůj vlastní blok, každý o své vlastní velikosti. Obecně platí, že větší velikost bloku znamená zvýšenou propustnost sekvenčního přístupu. Menší velikost bloku umožňuje rychlejší náhodný přístup.
4:Umístění BLOCKSIZE
kontrola po zapsání dat má dva důsledky. Jedna Cell
je nejmenší jednotka dat zapsaná do DATA
blok. Znamená to také Cell
nemůže zahrnovat více bloků.
5:Toto se liší od MemStore
, pro který existuje samostatná instance pro každý region hostovaný serverem regionu.
6:Až donedávna byly tyto paměťové oddíly definovány staticky; neexistoval způsob, jak přepsat rozdělení 25/50/25. Daný segment, například oblast s více přístupy, by se mohl zvětšit nad 50% přidělené části, pokud by ostatní oblasti nebyly dostatečně využívány. Zvýšené využití v ostatních oblastech vytlačí vstupy z oblasti s více přístupem, dokud nebude dosaženo rovnováhy 25/50/25. Operátor nemohl změnit tyto výchozí velikosti. HBASE-10263, dodávaný v HBase 0.98.0, zavádí konfigurační parametry pro tyto velikosti. Flexibilní chování je zachováno.
7:Cílem „přibližně“ je umožnit určitý prostor pro pohyb ve velikostech bloků. Velikost bloku HBase je hrubý cíl nebo nápověda, nikoli přísně vynucené omezení. Přesná velikost jakéhokoli konkrétního datového bloku bude záviset na velikosti cílového bloku a velikosti Cell
hodnoty v něm obsažené. Nápověda k velikosti bloku je určena jako výchozí velikost bloku 64 kb.
8:Použití BucketCache
v file
režim s perzistentním záložním úložištěm má další výhodu:perzistenci. Při spuštění vyhledá existující data v mezipaměti a ověří jejich platnost.
9:Pokud tomu rozumím, existují dvě složky, které doporučují horní hranici tohoto rozsahu. Prvním je omezení adresovatelnosti objektů JVM. JVM je schopen odkazovat na objekt na haldě s 32bitovou relativní adresou namísto plné 64bitové nativní adresy. Tato optimalizace je možná pouze v případě, že celková velikost haldy je menší než 32 GB. Další podrobnosti najdete v části Komprimované Jejda. Druhým je schopnost garbage collectoru držet krok s množstvím objektů v systému. Z toho, co mohu říci, tři zdroje odchodu objektů jsou MemStore
, BlockCache
a síťové operace. První je zmírněn MemSlab
funkce, ve výchozím nastavení povolena. Druhý je ovlivněn velikostí vaší datové sady vs. velikostí mezipaměti. Třetímu nelze pomoci, pokud HBase využívá síťový zásobník, který se spoléhá na kopírování dat.
10:Stejně jako u 8 je to za předpokladu „moderního hardwaru“. Interakce zde jsou poměrně složité a značně přesahují rozsah jediného blogového příspěvku.