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 do HBase para o Bigtable, talvez seja necessário mudar os nomes das famílias 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 quais filtros são compatíveis. Todos esses filtros estão no pacote org.apache.hadoop.hbase.filter.

Suporte Compatível, com limitações Não compatível
  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. É compatível apenas com os 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 o FilterList estiver definido como MUST_PASS_ONE, o Bigtable vai tratar o PageFilter como um MUST_PASS_ALL e retornar apenas o 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)