Diferenças entre o HBase e o Bigtable

Uma maneira de acessar o Bigtable é usar uma versão personalizada do cliente Apache HBase para Java. Em geral, o cliente personalizado expõe a mesma API de uma instalação padrão do HBase. Nesta página, descrevemos as diferenças entre o cliente HBase do Cloud Bigtable para Java e uma instalação padrão do HBase. Muitas dessas diferenças estão relacionadas a tarefas de gerenciamento processadas automaticamente pelo Bigtable.

Grupos de colunas

Ao criar um grupo de colunas, não é possível configurar o tamanho do bloco ou o método de compactação, seja com o shell do HBase ou a API HBase. O Bigtable gerencia o tamanho e a compactação do bloco para você.

Além disso, quando usado para receber informações de uma tabela, o shell do HBase sempre informará que nenhum grupo de colunas usa a compactação. Na realidade, o Bigtable usa métodos de compactação exclusivos para todos os seus dados.

O Bigtable exige que os nomes dos grupos de colunas sigam a expressão regular [_a-zA-Z0-9][-_.a-zA-Z0-9]*. Se você estiver importando dados para o Bigtable do HBase, talvez seja necessário primeiro alterar os nomes dos grupos para seguir esse padrão.

Linhas e células

  • Não é possível definir uma ACL para uma linha individual.
  • Não é possível definir a visibilidade de células individuais.
  • Não há compatibilidade com tags. Não é possível usar a classe org.apache.hadoop.hbase.Tag para adicionar metadados a células individuais.

Mutações e exclusões

  • As operações Append no Bigtable são totalmente atômicas para leitores e gravadores. Os leitores nunca poderão ler uma operação Append parcialmente aplicada.
  • É possível excluir uma determinada versão de uma coluna específica com base no carimbo de data/hora dela, mas não excluir todos os valores com um carimbo de data/hora específico em uma determinada linha ou grupo de colunas. Os seguintes métodos na classe org.apache.hadoop.hbase.client.Delete não são compatíveis:
    • new Delete(byte[] row, long timestamp)
    • addColumn(byte[] family, byte[] qualifier)
    • addFamily(byte[] family, long timestamp)
    • addFamilyVersion(byte[] family, long timestamp)
  • No HBase, as exclusões ocultam puts, mas o Bigtable não oculta puts após a exclusão quando as solicitações de put são enviadas após as solicitações de exclusão. Isso significa que, no Bigtable, uma solicitação de gravação enviada a uma célula não é afetada por uma solicitação de exclusão enviada anteriormente para a mesma célula.

Recebimentos e verificações

Coprocessadores

Coprocessadores não são compatíveis. Não é possível criar classes que implementam a interface org.apache.hadoop.hbase.coprocessor.

Filtros

A tabela a seguir mostra os filtros compatíveis. Todos esses filtros estão no pacote org.apache.hadoop.hbase.filter.

Compatível Compatível, com limitações Sem suporte
  1. Compatível somente com um único grupo de colunas.
  2. Não é possível chamar setLenAsVal(true).
  3. Compatível apenas com o comparador BinaryComparator. Se outro operador que não seja EQUAL for utilizado, apenas um único grupo de colunas será compatível.
  4. Oferece suporte apenas aos seguintes comparadores:
    • BinaryComparator
    • RegexStringComparator sem sinalizações (as sinalizações são ignoradas) e o operador EQUAL
  5. Se um PageFilter estiver em um FilterList, o PageFilter só funcionará de maneira semelhante ao HBase quando o FilterList estiver definido como MUST_PASS_ALL, que é o comportamento padrão. Se FilterList estiver definido como MUST_PASS_ONE, o Bigtable vai tratar PageFilter como um MUST_PASS_ALL e só vai retornar um número de linhas correspondentes ao pageSize do PageFilter.
  6. Na maioria dos casos, PrefixFilter verifica se há linhas no PrefixFilter. No entanto, se PrefixFilter fizer parte de um FilterList e tiver o operador MUST_PASS_ONE, o Bigtable não poderá determinar o intervalo implícito e realizará uma verificação não filtrada da linha inicial para a linha de parada. Nesse caso, use PrefixFilter com BigtableExtendedScan ou uma combinação de filtros para otimizar o desempenho.
  7. Depende do filtro de condição do Bigtable, que pode ser lento. Compatível, mas não recomendado.
ColumnPrefixFilter
FamilyFilter
FilterList
FuzzyRowFilter
MultipleColumnPrefixFilter
MultiRowRangeFilter
PrefixFilter 6
RandomRowFilter
TimestampsFilter
ColumnCountGetFilter 1
ColumnPaginationFilter 1
ColumnRangeFilter 1
FirstKeyOnlyFilter 1
KeyOnlyFilter 2
PageFilter 5
QualifierFilter 3
RowFilter 1, 4
SingleColumnValueExcludeFilter 1, 4, 7
SingleColumnValueFilter 4, 7
ValueFilter 4
DependentColumnFilter
FirstKeyValueMatchingQualifiersFilter
InclusiveStopFilter
ParseFilter
SkipFilter
WhileMatchFilter

Além disso, as seguintes diferenças afetam os filtros do Bigtable:

  • Em filtros que usam o comparador de expressões regulares (org.apache.hadoop.hbase.filter.RegexStringComparator), as expressões regulares usam a sintaxe RE2, não a sintaxe Java.
  • Filtros personalizados não são compatíveis. Não é possível criar classes que herdam de org.apache.hadoop.hbase.filter.Filter.
  • Há um limite de tamanho de 20 KB em expressões de filtro. Como solução alternativa para reduzir o tamanho de uma expressão de filtro, use uma coluna complementar que armazene o valor de hash dos critérios de filtro.

Timestamps

O Bigtable armazena carimbos de data/hora em microssegundos, enquanto o HBase armazena carimbos de data/hora em milissegundos. Essa distinção tem implicações quando você usa a biblioteca de cliente do HBase para o Bigtable e tem dados com carimbos de data/hora invertidos.

A biblioteca de cliente converte entre microssegundos e milissegundos, mas como o maior carimbo de data/hora do HBase que o Bigtable pode armazenar é Long.MAX_VALUE/1000, qualquer valor maior que esse será convertido em Long.MAX_VALUE/1000. Como resultado, valores grandes de carimbo de data/hora invertidos podem não ser convertidos corretamente.

Administração

Nesta seção, descrevemos métodos na interface org.apache.hadoop.hbase.client.Admin que não estão disponíveis no Bigtable ou que se comportam de maneira diferente no Bigtable e no HBase. Essas listas não são completas e podem não refletir os métodos da API HBase adicionados mais recentemente.

A maioria desses métodos é desnecessária no Bigtable, já que as tarefas de gerenciamento são tratadas automaticamente. Alguns métodos não estão disponíveis porque se referem a recursos com os quais o Bigtable não é compatível.

Tarefas gerais de manutenção

O Bigtable realiza a maioria das tarefas de manutenção automaticamente. Como resultado, os seguintes métodos não estão disponíveis:

  • abort(String why, Throwable e)
  • balancer()
  • enableCatalogJanitor(boolean enable)
  • getMasterInfoPort()
  • getOperationTimeout()
  • isCatalogJanitorEnabled()
  • rollWALWriter(ServerName serverName)
  • runCatalogScan()
  • setBalancerRunning(boolean on, boolean synchronous)
  • shutdown()
  • stopMaster()
  • updateConfiguration()
  • updateConfiguration(ServerName serverName)

Grupos de localidades

O Bigtable não permite especificar grupos de localidades para grupos de colunas. Como resultado, não é possível chamar métodos HBase que retornam um grupo de localidades.

Namespaces

O Bigtable não usa namespaces. Use os prefixos de chave de linha para simular namespaces. Os seguintes métodos não estão disponíveis:

  • createNamespace(NamespaceDescriptor descriptor)
  • deleteNamespace(String name)
  • getNamespaceDescriptor(String name)
  • listNamespaceDescriptors()
  • listTableDescriptorsByNamespace(String name)
  • listTableNamesByNamespace(String name)
  • modifyNamespace(NamespaceDescriptor descriptor)

Gerenciamento de regiões

O Bigtable usa blocos, que são semelhantes a regiões. O Bigtable gerencia os blocos automaticamente. Como resultado, os seguintes métodos não estão disponíveis:

  • assign(byte[] regionName)
  • closeRegion(byte[] regionname, String serverName)
  • closeRegion(ServerName sn, HRegionInfo hri)
  • closeRegion(String regionname, String serverName)
  • closeRegionWithEncodedRegionName(String encodedRegionName, String serverName)
  • compactRegion(byte[] regionName)
  • compactRegion(byte[] regionName, byte[] columnFamily)
  • compactRegionServer(ServerName sn, boolean major)
  • flushRegion(byte[] regionName)
  • getAlterStatus(byte[] tableName)
  • getAlterStatus(TableName tableName)
  • getCompactionStateForRegion(byte[] regionName)
  • getOnlineRegions(ServerName sn)
  • majorCompactRegion(byte[] regionName)
  • majorCompactRegion(byte[] regionName, byte[] columnFamily)
  • mergeRegions(byte[] encodedNameOfRegionA, byte[] encodedNameOfRegionB, boolean forcible)
  • move(byte[] encodedRegionName, byte[] destServerName)
  • offline(byte[] regionName)
  • splitRegion(byte[] regionName)
  • splitRegion(byte[] regionName, byte[] splitPoint)
  • stopRegionServer(String hostnamePort)
  • unassign(byte[] regionName, boolean force)

Snapshots

Os seguintes métodos não estão disponíveis.

  • deleteSnapshots(Pattern pattern)
  • deleteSnapshots(String regex)
  • isSnapshotFinished(HBaseProtos.SnapshotDescription snapshot)
  • restoreSnapshot(byte[] snapshotName)
  • restoreSnapshot(String snapshotName)
  • restoreSnapshot(byte[] snapshotName, boolean takeFailSafeSnapshot)
  • restoreSnapshot(String snapshotName, boolean takeFailSafeSnapshot)
  • snapshot(HBaseProtos.SnapshotDescription snapshot)

Gerenciamento de tabelas

Tarefas como a compactação de tabelas são tratadas automaticamente. Como resultado, os seguintes métodos não estão disponíveis:

  • compact(TableName tableName)
  • compact(TableName tableName, byte[] columnFamily)
  • flush(TableName tableName)
  • getCompactionState(TableName tableName)
  • majorCompact(TableName tableName)
  • majorCompact(TableName tableName, byte[] columnFamily)
  • modifyTable(TableName tableName, HTableDescriptor htd)
  • split(TableName tableName)
  • split(TableName tableName, byte[] splitPoint)

Coprocessadores

O Bigtable não é compatível com coprocessadores. Como resultado, os seguintes métodos não estão disponíveis:

  • coprocessorService()
  • coprocessorService(ServerName serverName)
  • getMasterCoprocessors()

Procedimentos distribuídos

O Bigtable não é compatível com procedimentos distribuídos. Como resultado, os seguintes métodos não estão disponíveis:

  • execProcedure(String signature, String instance, Map<String, String> props)
  • execProcedureWithRet(String signature, String instance, Map<String, String> props)
  • isProcedureFinished(String signature, String instance, Map<String, String> props)