{"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\/pt\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase","title":{"rendered":"Teoria e pr\u00e1tica do uso do HBase","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Bom dia! Meu nome \u00e9 Danil Lipovoy, nossa equipe na Sbertech come\u00e7ou a usar HBase como um reposit\u00f3rio de dados operacionais. Durante seu estudo, acumulamos experi\u00eancia que gostar\u00edamos de sistematizar e descrever (esperamos que seja \u00fatil para muitos). Todos os experimentos realizados abaixo foram feitos com as vers\u00f5es HBase 1.2.0-cdh5.14.2 e 2.0.0-cdh6.0.0-beta1. <\/p>\n<ol>\n<li>Arquitetura Geral <\/li>\n<li>Grava\u00e7\u00e3o de Dados em HBASE<\/li>\n<li>Leitura de Dados de HBASE<\/li>\n<li>Cache de Dados<\/li>\n<li>Processamento de Dados em Lote MultiGet\/MultiPut<\/li>\n<li>Estrat\u00e9gia de Divis\u00e3o de Tabelas em Regi\u00f5es (Split)<\/li>\n<li>Alta Disponibilidade, Compacta\u00e7\u00e3o e Localidade de Dados<\/li>\n<li>Configura\u00e7\u00f5es e Desempenho<\/li>\n<li>Testes de carga<\/li>\n<li>Como resultado, obtemos um servi\u00e7o de \"monitoramento como servi\u00e7o\", automatizado na linha de produ\u00e7\u00e3o de integra\u00e7\u00e3o cont\u00ednua. O desenvolvedor ou testador precisa apenas definir a lista de m\u00e9tricas em um arquivo JSON, e tudo o mais acontece automaticamente. Obtemos um controle de qualidade transparente dos lan\u00e7amentos: todas as notifica\u00e7\u00f5es sobre desempenho, consumo de recursos ou regress\u00f5es arquitet\u00f4nicas.<\/li>\n<\/ol>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>1. Arquitetura Geral<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/30800d8a48de4c52ff1650a4f1dec4c8.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO Master de backup escuta o heartbeat do ativo no n\u00f3 do ZooKeeper e, em caso de desaparecimento, assume as fun\u00e7\u00f5es de Master. <\/p>\n<h2>2. Grava\u00e7\u00e3o de Dados em HBASE<\/h2>\n<p>\nPrimeiro, consideramos o caso mais simples \u2013 a grava\u00e7\u00e3o de um objeto chave-valor em uma tabela usando put(rowkey). O cliente precisa primeiro descobrir onde est\u00e1 o servidor da regi\u00e3o raiz (Root Region Server - RRS), que armazena a tabela hbase:meta. Essa informa\u00e7\u00e3o \u00e9 obtida do ZooKeeper. Em seguida, ele se conecta ao RRS e l\u00ea a tabela hbase:meta, da qual extrai informa\u00e7\u00f5es sobre qual RegionServer (RS) \u00e9 respons\u00e1vel por armazenar os dados para a chave rowkey na tabela de interesse. Para uso futuro, a meta-tabela \u00e9 armazenada em cache pelo cliente, e, portanto, as chamadas subsequentes s\u00e3o mais r\u00e1pidas, indo diretamente para o RS.<\/p>\n<p>Ap\u00f3s o RRS receber a solicita\u00e7\u00e3o, ele primeiramente a escreve no WriteAheadLog (WAL), o que \u00e9 necess\u00e1rio para recupera\u00e7\u00e3o em caso de falha. Em seguida, os dados s\u00e3o salvos no MemStore. Este \u00e9 um buffer na mem\u00f3ria que cont\u00e9m um conjunto classificado de chaves desta regi\u00e3o. A tabela pode ser dividida em regi\u00f5es (parti\u00e7\u00f5es), cada uma contendo um conjunto exclusivo de chaves. Isso permite que, ao distribuir as regi\u00f5es em diferentes servidores, se obtenha um desempenho mais alto. No entanto, apesar da obviedade dessa afirma\u00e7\u00e3o, veremos a seguir que isso n\u00e3o se aplica a todos os casos.<\/p>\n<p>Ap\u00f3s a grava\u00e7\u00e3o no MemStore, o cliente recebe uma resposta informando que a grava\u00e7\u00e3o foi conclu\u00edda com sucesso. No entanto, na realidade, ela \u00e9 armazenada apenas no buffer e ser\u00e1 gravada no disco apenas ap\u00f3s um determinado intervalo de tempo ou quando for preenchida com novos dados. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/10f4d5d600a20882690f5cc81322bc41.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAo executar a opera\u00e7\u00e3o 'Delete', n\u00e3o ocorre a exclus\u00e3o f\u00edsica dos dados. Eles simplesmente s\u00e3o marcados como exclu\u00eddos, e a exclus\u00e3o real acontece no momento da chamada da fun\u00e7\u00e3o major compact, sobre a qual h\u00e1 mais informa\u00e7\u00f5es no item 7.<\/p>\n<p>Os arquivos no formato HFile se acumulam no HDFS e, de tempos em tempos, \u00e9 iniciado um processo de minor compact, que apenas junta pequenos arquivos em arquivos maiores, sem excluir nada. Com o tempo, isso se torna um problema que se manifesta apenas ao ler os dados (voltaremos a isso mais adiante). <\/p>\n<p>Al\u00e9m do processo de carregamento descrito acima, existe um procedimento muito mais eficiente, que \u00e9 talvez o ponto mais forte deste banco de dados \u2013 o BulkLoad. Isso envolve a cria\u00e7\u00e3o manual de HFiles e seu armazenamento em disco, o que permite uma escalabilidade excelente e velocidades bastante altas. Na verdade, a limita\u00e7\u00e3o aqui n\u00e3o \u00e9 o HBase, mas as capacidades do hardware. Abaixo est\u00e3o os resultados do carregamento em um cluster composto por 16 RegionServers e 16 NodeManagers YARN (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads), vers\u00e3o HBase 1.2.0-cdh5.14.2. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/4e4452b216eda3269a364ea97c49120f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAqui, \u00e9 vis\u00edvel que aumentando o n\u00famero de parti\u00e7\u00f5es (regi\u00f5es) na tabela, bem como os executores Spark, obtemos um aumento na velocidade de carregamento. A velocidade tamb\u00e9m depende do volume de grava\u00e7\u00e3o. Blocos grandes proporcionam um aumento em termos de MB\/segundo, enquanto blocos pequenos aumentam a quantidade de registros inseridos por unidade de tempo, mantendo todas as outras vari\u00e1veis constantes. <\/p>\n<p>Tamb\u00e9m \u00e9 poss\u00edvel iniciar o carregamento em duas tabelas simultaneamente e obter o dobro da velocidade. Abaixo, \u00e9 mostrado que a grava\u00e7\u00e3o de blocos de 10 KB em duas tabelas vai a uma velocidade de cerca de 600 MB\/segundo cada (totalizando 1275 MB\/segundo), que corresponde \u00e0 velocidade de grava\u00e7\u00e3o em uma tabela de 623 MB\/segundo (ver n\u00ba 11 acima).<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/9f1b4fc0c80b797111494d400e9ce332.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPor outro lado, a segunda execu\u00e7\u00e3o com grava\u00e7\u00f5es de 50 KB mostra que a velocidade de carregamento cresce de forma insignificante, o que indica uma aproxima\u00e7\u00e3o aos limites m\u00e1ximos. \u00c9 importante considerar que a carga no pr\u00f3prio HBASE \u00e9 praticamente inexistente; tudo o que \u00e9 necess\u00e1rio dele \u00e9, primeiro, fornecer os dados do hbase:meta e, depois, ao adicionar os HFiles, liberar os dados do BlockCache e salvar o buffer MemStore no disco, caso n\u00e3o esteja vazio.<\/p>\n<h2>3. Leitura de dados do HBASE<\/h2>\n<p>\nSe considerarmos que todas as informa\u00e7\u00f5es de hbase:meta j\u00e1 est\u00e3o com o cliente (ver item 2), a consulta vai diretamente para o RS que armazena a chave necess\u00e1ria. Primeiro, a busca \u00e9 realizada no MemCache. Independentemente de haver ou n\u00e3o dados l\u00e1, a busca tamb\u00e9m \u00e9 feita no buffer BlockCache e, se necess\u00e1rio, nos HFiles. Se os dados forem encontrados no arquivo, eles s\u00e3o armazenados no BlockCache e, na pr\u00f3xima solicita\u00e7\u00e3o, ser\u00e3o retornados mais rapidamente. A busca no HFile acontece relativamente r\u00e1pido devido ao uso do filtro de Bloom, ou seja, ao ler um pequeno volume de dados, ele imediatamente determina se esse arquivo cont\u00e9m a chave necess\u00e1ria e, se n\u00e3o, passa para o pr\u00f3ximo.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/a21b1b825a84cfd02507ec334e9452fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nRecebendo dados dessas tr\u00eas fontes, o RS forma a resposta. Em particular, ele pode transmitir v\u00e1rias vers\u00f5es encontradas de um objeto se o cliente solicitar versionamento.<\/p>\n<h2>4. Cache de dados<\/h2>\n<p>\nOs buffers MemStore e BlockCache ocupam at\u00e9 80% da mem\u00f3ria heap alocada do RS (o restante \u00e9 reservado para tarefas de servi\u00e7o do RS). Se o modo t\u00edpico de uso for tal que os processos escrevam e leiam esses mesmos dados imediatamente, faz sentido diminuir o BlockCache e aumentar o MemStore, pois ao gravar, os dados no cache de leitura n\u00e3o s\u00e3o acessados, o que far\u00e1 com que o uso do BlockCache ocorra com menos frequ\u00eancia. O buffer BlockCache consiste em duas partes: LruBlockCache (sempre on-heap) e BucketCache (geralmente off-heap ou em SSD). O BucketCache deve ser utilizado quando h\u00e1 muitas solicita\u00e7\u00f5es de leitura que n\u00e3o cabem no LruBlockCache, o que leva a um trabalho ativo do Garbage Collector. Contudo, n\u00e3o se deve esperar um aumento dr\u00e1stico de desempenho da utiliza\u00e7\u00e3o do cache de leitura, mas voltaremos a isso no item 8.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/17d7791a998dd7da747cb7089dce1f10.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO BlockCache \u00e9 \u00fanico para todo o RS, enquanto o MemStore \u00e9 espec\u00edfico para cada tabela (um por cada Column Family).<\/p>\n<p>Como <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.cloudera.com\/blog\/2012\/06\/hbase-write-path\/\">est\u00e1 descrito<\/a><\/noindex> Na teoria, ao gravar, os dados n\u00e3o v\u00e3o para o cache e, de fato, esses par\u00e2metros CACHE_DATA_ON_WRITE para a tabela e \"Cache DATA on Write\" para o RS est\u00e3o configurados como false. No entanto, na pr\u00e1tica, se gravarmos dados no MemStore, depois o descarregarmos no disco (limpando assim), e em seguida deletarmos o arquivo resultante, ao executar uma solicita\u00e7\u00e3o get, conseguiremos obter os dados com sucesso. Al\u00e9m disso, mesmo se desativarmos completamente o BlockCache e preenchermos a tabela com novos dados, depois conseguirmos descarregar o MemStore no disco, delet\u00e1-los e solicit\u00e1-los de outra sess\u00e3o, eles ainda ser\u00e3o recuperados de algum lugar. Portanto, o HBase armazena n\u00e3o apenas dados, mas tamb\u00e9m mist\u00e9rios enigm\u00e1ticos.<\/p>\n<pre><code class=\"bash\">hbase(main):001:0&gt; criar 'ns:magic', 'cf'\nTabela ns:magic criada\nDemorou 1.1533 segundos\nhbase(main):002:0&gt; colocar 'ns:magic', 'key1', 'cf:c', 'tente_me_deletar'\nDemorou 0.2610 segundos\nhbase(main):003:0&gt; esvaziar 'ns:magic'\nDemorou 0.6161 segundos\nhdfs dfs -mv \/data\/hbase\/data\/ns\/magic\/* \/tmp\/trash\nhbase(main):002:0&gt; obter 'ns:magic', 'key1'\n cf:c      timestamp=1534440690218, valor=tente_me_deletar\n<\/code><\/pre>\n<p>\nO par\u00e2metro \"Cache DATA on Read\" est\u00e1 definido como falso. Se tiver alguma ideia, fique \u00e0 vontade para discutir nos coment\u00e1rios.<\/p>\n<h2>5. Processamento em Lote de Dados MultiGet\/MultiPut<\/h2>\n<p>\nO processamento de solicita\u00e7\u00f5es individuais (Get\/Put\/Delete) \u00e9 uma opera\u00e7\u00e3o bastante cara, portanto, deve-se tentar agrup\u00e1-las em List ou List, o que pode resultar em um aumento significativo de desempenho. Isso \u00e9 especialmente verdadeiro para opera\u00e7\u00f5es de grava\u00e7\u00e3o, mas h\u00e1 uma armadilha ao ler. No gr\u00e1fico abaixo est\u00e1 o tempo para ler 50.000 registros do MemStore. A leitura foi realizada em um \u00fanico thread e no eixo horizontal est\u00e1 o n\u00famero de chaves na solicita\u00e7\u00e3o. Pode-se ver que ao aumentar para mil chaves em uma \u00fanica solicita\u00e7\u00e3o, o tempo de execu\u00e7\u00e3o diminui, ou seja, a velocidade aumenta. No entanto, com o modo MSLAB ativado por padr\u00e3o, ap\u00f3s esse limite, h\u00e1 uma queda dr\u00e1stica no desempenho, e quanto maior o volume de dados no registro, maior o tempo de execu\u00e7\u00e3o. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/42d3a77d66770a7fed03f83fecdca470.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOs testes foram realizados em uma m\u00e1quina virtual, 8 n\u00facleos, vers\u00e3o HBase 2.0.0-cdh6.0.0-beta1.<\/p>\n<p>O modo MSLAB foi projetado para reduzir a fragmenta\u00e7\u00e3o do heap, que ocorre devido \u00e0 mistura de dados de gera\u00e7\u00f5es novas e antigas. Para resolver esse problema, ao ativar o MSLAB, os dados s\u00e3o colocados em c\u00e9lulas (chunk) relativamente pequenas e processados em lotes. Como resultado, quando o volume no pacote de dados solicitado excede o tamanho alocado, o desempenho cai drasticamente. Por outro lado, desativar esse modo tamb\u00e9m n\u00e3o \u00e9 desej\u00e1vel, pois levar\u00e1 a pausas devido ao GC em momentos de intenso trabalho com dados. Uma boa sa\u00edda \u00e9 aumentar o tamanho da c\u00e9lula, especialmente ao gravar atrav\u00e9s de put ao mesmo tempo que se l\u00ea. Vale ressaltar que o problema n\u00e3o ocorre se, ap\u00f3s a grava\u00e7\u00e3o, a comando flush que descarrega o MemStore no disco for executada ou se a carga for realizada usando BulkLoad. Na tabela abaixo, mostra-se que solicita\u00e7\u00f5es de dados maiores do MemStore (e com a mesma quantidade) levam a uma desacelera\u00e7\u00e3o. No entanto, aumentando o chunksize, podemos retornar o tempo de processamento ao normal.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/0076215bd171257548f8a4c4d4229ba0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAl\u00e9m de aumentar o chunksize, a fragmenta\u00e7\u00e3o dos dados por regi\u00f5es, ou seja, o partitioning das tabelas, ajuda. Isso resulta em um menor n\u00famero de solicita\u00e7\u00f5es para cada regi\u00e3o, e se elas forem armazenadas em uma c\u00e9lula, a resposta permanece boa.<\/p>\n<h2>6. Estrat\u00e9gia de partitioning de tabelas por regi\u00f5es<\/h2>\n<p>\nComo o HBase \u00e9 um reposit\u00f3rio de chave-valor e o particionamento \u00e9 feito pela chave, \u00e9 crucial distribuir os dados uniformemente entre todas as regi\u00f5es. Por exemplo, particionar uma tabela em tr\u00eas partes resultar\u00e1 em tr\u00eas regi\u00f5es:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/a811ae81e77b48dbf28ed86dbdc35739.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n\u00c0s vezes, isso leva a uma desacelera\u00e7\u00e3o dr\u00e1stica, se os dados carregados posteriormente forem, por exemplo, valores longos que na sua maioria come\u00e7am com o mesmo d\u00edgito, como por exemplo:<\/p>\n<p>1000001<br \/>\n1000002<br \/>\n\u2026<br \/>\n1100003<\/p>\n<p>Como as chaves s\u00e3o armazenadas como um array de bytes, todas elas come\u00e7ar\u00e3o de forma semelhante e pertencer\u00e3o \u00e0 regi\u00e3o #1 que armazena esse intervalo de chaves. Existem v\u00e1rias estrat\u00e9gias de particionamento:<\/p>\n<p>HexStringSplit \u2013 Converte a chave em uma string com codifica\u00e7\u00e3o hexadecimal no intervalo de \"00000000\" =&gt; \"FFFFFFFF\" e preenche \u00e0 esquerda com zeros.<\/p>\n<p>UniformSplit \u2013 Converte a chave em um array de bytes com codifica\u00e7\u00e3o hexadecimal no intervalo de \"00\" =&gt; \"FF\" e preenche \u00e0 direita com zeros.<\/p>\n<p>Al\u00e9m disso, \u00e9 poss\u00edvel especificar qualquer intervalo ou conjunto de chaves para particionamento e configurar o auto-partitioning. No entanto, uma das abordagens mais simples e eficazes \u00e9 o UniformSplit e o uso de concatena\u00e7\u00e3o do hash, por exemplo, o par mais significativo de bytes ao passar a chave pela fun\u00e7\u00e3o CRC32(rowkey) e a pr\u00f3pria chave:<\/p>\n<p>hash + rowkey<\/p>\n<p>Assim, todos os dados ser\u00e3o distribu\u00eddos uniformemente entre as regi\u00f5es. Ao ler, os primeiros dois bytes s\u00e3o simplesmente descartados e a chave original permanece. Al\u00e9m disso, o RS controla a quantidade de dados e chaves na regi\u00e3o e, ao ultrapassar os limites, divide automaticamente em partes. <\/p>\n<h2>7. Toler\u00e2ncia a falhas e localidade dos dados<\/h2>\n<p>\nComo cada conjunto de chaves \u00e9 responsabilidade de apenas uma regi\u00e3o, a solu\u00e7\u00e3o para problemas relacionados a falhas do RS ou desativa\u00e7\u00e3o \u00e9 armazenar todos os dados necess\u00e1rios no HDFS. Quando um RS falha, o mestre detecta isso pela aus\u00eancia de heartbeat no n\u00f3 do ZooKeeper. Em seguida, ele atribui a regi\u00e3o problem\u00e1tica a outro RS, e como os HFiles s\u00e3o armazenados em um sistema de arquivos distribu\u00eddo, o novo propriet\u00e1rio os l\u00ea e continua a servir os dados. No entanto, como parte dos dados pode estar no MemStore e n\u00e3o ter sido gravada nos HFiles, para a recupera\u00e7\u00e3o do hist\u00f3rico de opera\u00e7\u00f5es utiliza-se o WAL, que tamb\u00e9m \u00e9 armazenado no HDFS. Ap\u00f3s a aplica\u00e7\u00e3o das altera\u00e7\u00f5es, o RS pode responder a solicita\u00e7\u00f5es, no entanto, a realoca\u00e7\u00e3o resulta em que parte dos dados e os processos que os atendem estejam em diferentes n\u00f3s, ou seja, a localidade diminui. <\/p>\n<p>A solu\u00e7\u00e3o para o problema \u00e9 a major compaction \u2013 este procedimento move arquivos para os n\u00f3s que s\u00e3o respons\u00e1veis por eles (onde suas regi\u00f5es est\u00e3o localizadas), resultando em um aumento repentino na carga sobre a rede e os discos durante esse procedimento. No entanto, o acesso aos dados torna-se significativamente mais r\u00e1pido posteriormente. Al\u00e9m disso, a major_compaction realiza a fus\u00e3o de todos os HFiles em um \u00fanico arquivo dentro da regi\u00e3o, al\u00e9m de limpar dados de acordo com as configura\u00e7\u00f5es da tabela. Por exemplo, \u00e9 poss\u00edvel definir o n\u00famero de vers\u00f5es do objeto a serem mantidas ou o tempo de vida, ap\u00f3s o qual o objeto \u00e9 exclu\u00eddo fisicamente.<\/p>\n<p>Este procedimento pode ter um impacto muito positivo na opera\u00e7\u00e3o do HBase. Na imagem abaixo, \u00e9 poss\u00edvel ver como o desempenho degradou devido \u00e0 grava\u00e7\u00e3o ativa de dados. Aqui, 40 threads estavam gravando em uma tabela e 40 threads estavam lendo dados simultaneamente. As threads de grava\u00e7\u00e3o formam cada vez mais HFiles, que s\u00e3o consumidos por outras threads. Como resultado, mais dados precisam ser removidos da mem\u00f3ria e, eventualmente, o GC come\u00e7a a operar, o que praticamente paralisa todo o trabalho. A execu\u00e7\u00e3o da major compaction levou \u00e0 limpeza dos ac\u00famulos formados e \u00e0 recupera\u00e7\u00e3o do desempenho.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/6c93b2c10c197663785d3de0bb185481.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO teste foi realizado em 3 DataNodes e 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads). Vers\u00e3o HBase 1.2.0-cdh5.14.2<\/p>\n<p>Vale ressaltar que a execu\u00e7\u00e3o da compacta\u00e7\u00e3o major foi realizada em uma tabela \"viva\", onde dados estavam sendo ativamente escritos e lidos. Nas redes, havia afirma\u00e7\u00f5es de que isso poderia levar a respostas incorretas ao ler dados. Para verificar, foi iniciado um processo que gerava novos dados e os escrevia na tabela. Em seguida, imediatamente lia e verificava se o valor obtido coincidia com o que havia sido gravado. Durante a execu\u00e7\u00e3o desse processo, a compacta\u00e7\u00e3o major foi iniciada cerca de 200 vezes sem que nenhum erro fosse registrado. Pode ser que o problema ocorra raramente e apenas durante alta carga, portanto, \u00e9 mais seguro realmente parar os processos de leitura e escrita de forma planejada e realizar a limpeza, evitando tais quedas no GC.<\/p>\n<p>Al\u00e9m disso, a compacta\u00e7\u00e3o major n\u00e3o afeta o estado do MemStore, para liber\u00e1-lo no disco e compact\u00e1-lo \u00e9 necess\u00e1rio usar flush (connection.getAdmin().flush(TableName.valueOf(tblName))).<\/p>\n<h2>8. Configura\u00e7\u00f5es e desempenho<\/h2>\n<p>\nComo j\u00e1 mencionado, o HBase tem o maior sucesso onde n\u00e3o precisa fazer nada durante a execu\u00e7\u00e3o do BulkLoad. No entanto, isso \u00e9 aplic\u00e1vel \u00e0 maioria dos sistemas e pessoas. Entretanto, essa ferramenta \u00e9 mais adequada para o carregamento em massa de dados em grandes blocos, enquanto que, se o processo exige a realiza\u00e7\u00e3o de m\u00faltiplas requisi\u00e7\u00f5es concorrentes de leitura e grava\u00e7\u00e3o, s\u00e3o utilizadas os comandos Get e Put descritos acima. Para determinar os par\u00e2metros ideais, foram realizados testes com diferentes combina\u00e7\u00f5es de par\u00e2metros de tabelas e configura\u00e7\u00f5es:<\/p>\n<ul>\n<li>10 threads foram executados simultaneamente 3 vezes consecutivas (vamos chamar isso de bloco de threads). <\/li>\n<li>O tempo de opera\u00e7\u00e3o de todos os threads no bloco foi calculado como uma m\u00e9dia e representava o resultado final do desempenho do bloco.<\/li>\n<li>Todos os threads trabalhavam com a mesma tabela. <\/li>\n<li>Antes de cada execu\u00e7\u00e3o do bloco de threads, uma compacta\u00e7\u00e3o major era realizada.<\/li>\n<li>Cada bloco executou apenas uma das seguintes opera\u00e7\u00f5es: <\/li>\n<\/ul>\n<p>\n \u2014 Put<br \/>\n \u2014 Get<br \/>\n \u2014 Get+Put<\/p>\n<ul>\n<li>Cada bloco realizou 50.000 repeti\u00e7\u00f5es de sua opera\u00e7\u00e3o.<\/li>\n<li>O tamanho da grava\u00e7\u00e3o no bloco era de 100 bytes, 1000 bytes ou 10.000 bytes (aleat\u00f3rio).<\/li>\n<li>Os blocos foram executados com diferentes n\u00fameros de chaves solicitadas (ou uma chave ou 10).<\/li>\n<li>Os blocos foram executados sob diferentes configura\u00e7\u00f5es de tabela. As seguintes vari\u00e1veis foram alteradas:<\/li>\n<\/ul>\n<p>\n \u2014 BlockCache = ativado ou desativado<br \/>\n \u2014 BlockSize = 65 KB ou 16 KB<br \/>\n \u2014 Parti\u00e7\u00f5es = 1, 5 ou 30<br \/>\n \u2014 MSLAB = ativado ou desativado<\/p>\n<p>Assim, o bloco \u00e9 configurado da seguinte forma:<\/p>\n<p>a. O modo MSLAB foi ativado\/desativado.<br \/>\nb. Uma tabela foi criada, para a qual os seguintes par\u00e2metros foram definidos: BlockCache = true\/none, BlockSize = 65\/16 Kb, Parti\u00e7\u00f5es = 1\/5\/30. <br \/>\nc. A compress\u00e3o GZ foi ativada.<br \/>\nd. 10 threads foram iniciadas simultaneamente realizando 1\/10 opera\u00e7\u00f5es put\/get\/get+put nesta tabela com registros de 100\/1000\/10000 bytes, executando 50.000 solicita\u00e7\u00f5es consecutivas (as chaves eram aleat\u00f3rias).<br \/>\ne. O item d foi repetido tr\u00eas vezes.<br \/>\nf. O tempo de execu\u00e7\u00e3o de todas as threads foi calculado como uma m\u00e9dia. <\/p>\n<p>Todas as combina\u00e7\u00f5es poss\u00edveis foram testadas. \u00c9 previs\u00edvel que, ao aumentar o tamanho do registro, a velocidade caia ou que a desativa\u00e7\u00e3o do cache cause lentid\u00e3o. No entanto, o objetivo era entender a magnitude e a import\u00e2ncia do impacto de cada par\u00e2metro, por isso os dados coletados foram fornecidos como entrada para uma fun\u00e7\u00e3o de regress\u00e3o linear, que permite avaliar a confiabilidade usando a estat\u00edstica t. Abaixo est\u00e3o os resultados das opera\u00e7\u00f5es Put. O conjunto completo de combina\u00e7\u00f5es \u00e9 2*2*3*2*3 = 144 variantes + 72, pois algumas foram executadas duas vezes. Portanto, no total, foram 216 execu\u00e7\u00f5es:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/7a13c7a9b3ff1859976800f5d45cd51b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOs testes foram realizados em um mini-cluster composto por 3 DataNodes e 4 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads). Vers\u00e3o do HBase 1.2.0-cdh5.14.2.<\/p>\n<p>A maior velocidade de inser\u00e7\u00e3o de 3,7 segundos foi obtida com o modo MSLAB desligado, em uma tabela com uma parti\u00e7\u00e3o, com o BlockCache ativado, BlockSize = 16, registros de 100 bytes em pacotes de 10.<br \/>\nA menor velocidade de inser\u00e7\u00e3o de 82,8 segundos foi obtida com o modo MSLAB ativado, em uma tabela com uma parti\u00e7\u00e3o, com o BlockCache ativado, BlockSize = 16, registros de 10000 bytes um \u00fanico.<\/p>\n<p>Agora vamos olhar para o modelo. Observamos uma boa qualidade do modelo em R2, mas \u00e9 bastante claro que a extrapola\u00e7\u00e3o aqui \u00e9 desaconselh\u00e1vel. O comportamento real do sistema com a mudan\u00e7a dos par\u00e2metros ser\u00e1 n\u00e3o linear; este modelo n\u00e3o \u00e9 para previs\u00f5es, mas para entender o que aconteceu dentro dos par\u00e2metros definidos. Por exemplo, aqui vemos pelo crit\u00e9rio de Student que, para a opera\u00e7\u00e3o Put, os par\u00e2metros BlockSize e BlockCache n\u00e3o t\u00eam relev\u00e2ncia (o que \u00e9, no geral, bastante previs\u00edvel):<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/2fb65d1809d53f2b47f4f8829a9efc65.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAumentar o n\u00famero de parti\u00e7\u00f5es levando a uma diminui\u00e7\u00e3o no desempenho \u00e9 um tanto inesperado (j\u00e1 vimos o impacto positivo do aumento do n\u00famero de parti\u00e7\u00f5es durante o BulkLoad), embora explic\u00e1vel. Primeiro, para processar \u00e9 necess\u00e1rio gerar consultas para 30 regi\u00f5es em vez de uma, e o volume de dados n\u00e3o \u00e9 suficiente para que isso traga vantagens. Em segundo lugar, o tempo total de execu\u00e7\u00e3o \u00e9 determinado pelo RS mais lento, e como o n\u00famero de DataNodes \u00e9 menor que o n\u00famero de RS, algumas regi\u00f5es t\u00eam localidade zero. Agora, vamos olhar para os cinco l\u00edderes:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/8ad7e832879156eaa96e630458405cdc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAgora vamos avaliar os resultados da execu\u00e7\u00e3o dos blocos Get:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/8a5dd45422c74e8815011d7e9b805ccb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO n\u00famero de parti\u00e7\u00f5es perdeu relev\u00e2ncia, o que provavelmente se explica pelo fato de os dados serem bem armazenados em cache e o cache para leitura ser o par\u00e2metro mais significativo (estatisticamente). Naturalmente, o aumento no n\u00famero de mensagens na consulta tamb\u00e9m \u00e9 bastante ben\u00e9fico para o desempenho. Os melhores resultados:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/9d237f9fdbeaf5412daec2fc2fa24b01.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nE finalmente, vamos analisar o modelo de bloco que primeiro executou o get e depois o put:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/75137207a4a69acccad036882794094b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAqui todos os par\u00e2metros s\u00e3o significativos. E os resultados dos l\u00edderes:<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/c166933d81e86f36958e3af58297f876.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>9. Teste de carga<\/h2>\n<p>\nE finalmente, vamos rodar uma carga mais ou menos decente, mas \u00e9 sempre mais interessante quando h\u00e1 algo para comparar. No site da DataStax - o principal desenvolvedor do Cassandra, h\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.datastax.com\/wp-content\/themes\/datastax-2014-08\/files\/NoSQL_Benchmarks_EndPoint.pdf\">resultados<\/a><\/noindex> Um benchmark de v\u00e1rias solu\u00e7\u00f5es NoSQL, incluindo HBase vers\u00e3o 0.98.6-1. O carregamento foi feito com 40 threads, tamanho dos dados 100 bytes, discos SSD. O resultado do teste de opera\u00e7\u00f5es Read-Modify-Write mostrou os seguintes resultados.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/521e9dff60f462e6dabebc1234e028be.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n Pelo que entendi, a leitura foi realizada em blocos de 100 registros e para 16 n\u00f3s HBase, o teste da DataStax mostrou um desempenho de 10 mil opera\u00e7\u00f5es por segundo. <\/p>\n<p>\u00c9 bom que em nosso cluster tamb\u00e9m haja 16 n\u00f3s, mas n\u00e3o \u00e9 t\u00e3o \"bom\" que cada um tenha 64 n\u00facleos (threads), enquanto no teste da DataStax s\u00e3o apenas 4. Por outro lado, eles t\u00eam discos SSD, enquanto n\u00f3s temos HDD e uma vers\u00e3o mais nova do HBase, e a utiliza\u00e7\u00e3o da CPU durante a carga praticamente n\u00e3o aumentou significativamente (visualmente entre 5 a 10 por cento). No entanto, vamos tentar iniciar nesta configura\u00e7\u00e3o. As configura\u00e7\u00f5es das tabelas est\u00e3o no padr\u00e3o, a leitura \u00e9 realizada no intervalo de chaves de 0 a 50 milh\u00f5es, aleatoriamente (ou seja, basicamente a cada vez \u00e9 uma nova). A tabela tem 50 milh\u00f5es de registros, divididos em 64 parti\u00e7\u00f5es. As chaves s\u00e3o hashadas por crc32. As configura\u00e7\u00f5es das tabelas s\u00e3o padr\u00e3o, MSLAB est\u00e1 ativado. Iniciando 40 threads, cada thread l\u00ea um conjunto de 100 chaves aleat\u00f3rias e imediatamente escreve 100 bytes gerados por essas chaves de volta. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/776490f01121cc434135f733311b7722.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n Stand: 16 DataNodes e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads). Vers\u00e3o do HBase 1.2.0-cdh5.14.2.<\/p>\n<p>O resultado m\u00e9dio est\u00e1 mais pr\u00f3ximo de 40 mil opera\u00e7\u00f5es por segundo, o que \u00e9 significativamente melhor do que no teste da DataStax. No entanto, para fins experimentais, podemos alterar um pouco as condi\u00e7\u00f5es. \u00c9 bastante improv\u00e1vel que todo o trabalho seja realizado exclusivamente em uma \u00fanica tabela, assim como apenas com chaves \u00fanicas. Suponhamos que h\u00e1 um conjunto \"quente\" de chaves que gera a maior carga. Portanto, tentaremos criar uma carga com registros maiores (10 KB), tamb\u00e9m em lotes de 100, em 4 tabelas diferentes, limitando o intervalo de chaves solicitadas a 50 mil. O gr\u00e1fico abaixo mostra a execu\u00e7\u00e3o de 40 threads, cada thread l\u00ea um conjunto de 100 chaves e imediatamente escreve aleatoriamente 10 KB de volta por essas chaves. <\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/30d29f1b98663e3c07cb2be20e93876a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nStand: 16 DataNodes e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads). Vers\u00e3o do HBase 1.2.0-cdh5.14.2.<\/p>\n<p>Durante a carga, v\u00e1rias vezes foi executada a major compaction, como foi mostrado acima, sem este procedimento a performance gradualmente ir\u00e1 degradar, por\u00e9m durante a execu\u00e7\u00e3o tamb\u00e9m ocorre carga adicional. As quedas de desempenho s\u00e3o causadas por diferentes raz\u00f5es. \u00c0s vezes, as threads terminavam o trabalho e enquanto eram reiniciadas ocorria uma pausa, \u00e0s vezes aplicativos externos criavam carga no cluster.<\/p>\n<p>A leitura e escrita simult\u00e2nea \u00e9 um dos cen\u00e1rios de opera\u00e7\u00e3o mais exigentes para o HBase. Se voc\u00ea realizar apenas requisi\u00e7\u00f5es put de pequeno tamanho, como 100 bytes, agrupando-as em pacotes de 10-50 mil, \u00e9 poss\u00edvel alcan\u00e7ar centenas de milhares de opera\u00e7\u00f5es por segundo, e o mesmo se aplica a requisi\u00e7\u00f5es de leitura. Vale ressaltar que os resultados s\u00e3o radicalmente melhores do que os obtidos pela DataStax, principalmente devido \u00e0s requisi\u00e7\u00f5es em blocos de 50 mil.<\/p>\n<p><img decoding=\"async\" alt=\"Teoria e pr\u00e1tica do uso do HBase\" src=\"\/wp-content\/uploads\/2020\/01\/412bda50a55093224169f048ea2f863a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nStand: 16 DataNodes e 16 RS (CPU Xeon E5-2680 v4 @ 2.40GHz * 64 threads). Vers\u00e3o do HBase 1.2.0-cdh5.14.2.<\/p>\n<h2>10. Conclus\u00f5es<\/h2>\n<p>\nEste sistema \u00e9 bastante flex\u00edvel, mas o impacto de muitos par\u00e2metros ainda \u00e9 desconhecido. Parte deles foi testada, mas n\u00e3o foi inclu\u00edda no conjunto de testes resultante. Por exemplo, experimentos preliminares mostraram a baixa relev\u00e2ncia de um par\u00e2metro como DATA_BLOCK_ENCODING, que codifica informa\u00e7\u00f5es utilizando valores de c\u00e9lulas vizinhas, o que faz sentido para dados gerados aleatoriamente. No caso de um grande n\u00famero de objetos repetidos, o ganho pode ser significativo. De modo geral, pode-se afirmar que o HBase parece ser um banco de dados s\u00e9rio e bem pensado, que pode ser bastante eficiente em opera\u00e7\u00f5es com grandes blocos de dados, especialmente se houver a possibilidade de distribuir no tempo os processos de leitura e escrita.<\/p>\n<p>Se algo n\u00e3o estiver suficientemente abordado, estou \u00e0 disposi\u00e7\u00e3o para explicar mais detalhadamente. Sinta-se \u00e0 vontade para compartilhar sua experi\u00eancia ou discutir se voc\u00ea discorda de algo.<br \/>\n<br \/>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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 e pr\u00e1tica do uso do HBase | ProHoster","description":"Bom dia! Meu nome \u00e9 Danil Lipovoy, e nossa equipe na Sbertech come\u00e7ou a usar o HBase como um reposit\u00f3rio de dados operacionais.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/teoriya-i-praktika-ispolzovaniya-hbase","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/55302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=55302"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/55302\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=55302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=55302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=55302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}