HBase 与 Bigtable 之间的差异

访问 Bigtable 的一种方法是使用自定义版本的 Java 版 Apache HBase 客户端。通常,自定义客户端与标准安装的 HBase 客户端会展示相同的 API。本页面介绍 Java 版 Cloud Bigtable HBase 客户端与标准 HBase 安装之间的差异,其中许多差异与 Bigtable 自动处理的管理任务有关。

Java 版 Cloud Bigtable HBase 客户端适用于从 HBase 迁移到 Bigtable 且希望继续使用 HBase API 的客户。在所有其他情况下,Java 开发者应改用Java 版 Cloud Bigtable 客户端,该客户端会调用 Bigtable API。

列族

在创建列族时,无法使用 HBase shell 或 HBase API 配置块大小或压缩方法。Bigtable 会为您管理块大小和压缩。

另外,如果您使用 HBase shell 获取表的相关信息,HBase shell 始终会报告每个列族均不使用压缩。实际上,Bigtable 会为您的所有数据使用专有压缩方法。

系统会忽略以下列族设置,因为 Bigtable 会为您管理底层存储:

  • BLOCKCACHE
  • BLOCKSIZE
  • BLOOMFILTER
  • CACHE_BLOOMS_ON_WRITE
  • CACHE_DATA_IN_L1
  • CACHE_DATA_ON_WRITE
  • CACHE_INDEX_ON_WRITE
  • COMPRESS_TAGS
  • COMPRESSION
  • COMPRESSION_COMPACT
  • DATA_BLOCK_ENCODING
  • EVICT_BLOCKS_ON_CLOSE
  • IN_MEMORY
  • KEEP_DELETED_CELLS
  • PREFETCH_BLOCKS_ON_OPEN
  • REPLICATION_SCOPE

设置 VERSIONS、MIN_VERSIONS 和 TTL 会转换为 Bigtable 垃圾回收政策。

Bigtable 要求列族名称遵循正则表达式 [_a-zA-Z0-9][-_.a-zA-Z0-9]*。如果您要从 HBase 将数据导入 Bigtable,则可能需要先更改系列名称以遵循此模式。

行和单元格

  • 您无法为单个行定义 ACL。借助 Bigtable 授权视图,您可以授予对表数据子集的访问权限,但这些视图不会通过 HBase API 公开。
  • 您无法设置单个单元的公开范围。
  • 不支持标记。您无法使用 org.apache.hadoop.hbase.Tag 类向单个单元格添加元数据。您添加到单元格的所有标记都会在单元格写入之前被丢弃。

更改和删除

  • 对于读取者和写入者而言,Bigtable 中的 Append 操作都是完全原子化的。读取者将永远无法读取部分应用的 Append 操作。
  • Increment 操作是原子操作,但不支持在 Increment 上设置时间范围。
  • 您传递给 Table#mutateRow() 的 RowMutations 对象可以包含 Put 和 Delete 操作,也可以包含 Append 和 Increment 操作,但不能同时包含这两组操作。batch()、checkAndMutate() 或 BufferedMutator 不支持包含 Append 或 Increment 操作的 RowMutations 对象。
  • 支持根据时间戳删除特定列的特定版本。不过,不支持以下类型的删除操作:

    • 仅删除列的最新版本
    • 删除一行中具有特定时间戳的所有值
    • 删除列族中特定时间戳或之前的所有值

    因此,org.apache.hadoop.hbase.client.Delete 类中的以下方法不受支持: + new Delete(byte[] row, long timestamp) + addColumn(byte[] family, byte[] qualifier) + addFamily(byte[] family, long timestamp) + addFamilyVersion(byte[] family, long timestamp)

  • 在 HBase 中,删除遮盖放置,但在删除请求之后发送放置请求时,Bigtable 不会遮盖放置。这意味着在 Bigtable 中,发送到单元格的写入请求不会受之前发送到同一单元格的删除请求的影响。

获取和扫描

协处理器

不支持协处理器。您无法创建实现 org.apache.hadoop.hbase.coprocessor 接口的类。

过滤条件

下表列出了软件包 org.apache.hadoop.hbase.filter 中支持的过滤条件。该软件包中的所有其他过滤条件均不受支持,并且会抛出 UnsupportedOperationException。

支持 受支持(存在限制)
  1. 在大多数情况下,PrefixFilter 会扫描 PrefixFilter 中的行。但是,如果 PrefixFilter 是 FilterList 的一部分并且包含 MUST_PASS_ONE 运算符,则 Bigtable 无法确定隐式范围,而是执行从开始行到停止行的未过滤扫描。在这种情况下,请将 PrefixFilter 与 BigtableExtendedScan 搭配使用,或组合使用多个过滤条件,以优化性能。
  2. 仅当您使用列限定符作为列偏移量时,才需要单个列族。
  3. 仅支持单个列族。
  4. 仅支持 EQUAL 运算符,以及 BinaryComparator 比较器或 RegexStringComparator 比较器。
  5. 不支持使用 new KeyOnlyFilter(true) 构建过滤条件。
  6. 不能是使用 MUST_PASS_ONE 运算符的 FilterList 的一部分。
  7. PageFilter 必须是顶级过滤条件,或使用 MUST_PASS_ALL 运算符(默认行为)的顶级 FilterList 中的最后一个过滤条件。 不支持在 FilterList 中使用 MUST_PASS_ONE 运算符的 PageFilter。
  8. 仅支持 BinaryComparator 比较运算符,或 RegexStringComparator 比较运算符与 EQUAL 运算符。如果使用 EQUAL 以外的任何运算符,则仅支持单个列族。
  9. 仅支持以下比较器:
    • BinaryComparator
    • RegexStringComparator,无标志(忽略标志)和 EQUAL 运算
  10. 依赖 Bigtable 条件过滤条件,速度可能很慢。支持,但不推荐。
  11. 每次扫描仅支持一个 WhileMatchFilter。
ColumnCountGetFilter
ColumnPrefixFilter
FilterList
FirstKeyOnlyFilter
FuzzyRowFilter
MultipleColumnPrefixFilter
PrefixFilter 1
RandomRowFilter
TimestampsFilter
ColumnPaginationFilter 2
ColumnRangeFilter 3
FamilyFilter 4
KeyOnlyFilter 5
MultiRowRangeFilter 6
PageFilter 7
QualifierFilter 8
RowFilter 4
SingleColumnValueExcludeFilter 3、9、10
SingleColumnValueFilter 9、10
ValueFilter 9
WhileMatchFilter 6、11

另外,以下差异会影响 Bigtable 过滤条件:

  • 仅支持比较运算符 BinaryComparator 和 RegexStringComparator。不支持所有其他比较器,并且会抛出 UnsupportedOperationException。
  • 在使用正则表达式比较器 (org.apache.hadoop.hbase.filter.RegexStringComparator) 的过滤器中,正则表达式采用 RE2 语法而非 Java 语法。
  • 不支持自定义过滤器。您无法创建从 org.apache.hadoop.hbase.filter.Filter 继承的类。如需使用没有 HBase 等效项的 Bigtable 过滤条件,请将其封装在 com.google.cloud.bigtable.hbase.filter.BigtableFilter 中。
  • 过滤表达式的大小上限为 20 KB,且过滤表达式的嵌套深度不能超过 20 层。作为减小过滤表达式大小的解决方法,请使用存储过滤条件哈希值的辅助列。

时间戳

Bigtable 存储以微秒为单位的时间戳,而 HBase 存储以毫秒为单位的时间戳。如果您使用适用于 Bigtable 的 HBase 客户端库,并且您的数据具有反向时间戳,则此区别会产生影响。

客户端库会在微秒和毫秒之间转换,但由于 Bigtable 可以存储的最大 HBase 时间戳为 Long.MAX_VALUE/1000,因此任何大于该值的值都会转换为 Long.MAX_VALUE/1000。因此,较大的反向时间戳值可能无法正确转换。

管理

本部分介绍 Bigtable HBase Java 客户端如何实现 org.apache.hadoop.hbase.client.Admin 接口。由于 Bigtable 会自动处理大多数集群和存储管理任务,因此许多 HBase 管理方法都不适用。本部分中未列为受支持或无效的任何 Admin 方法均不受支持,并且会抛出 UnsupportedOperationException。

表管理

支持以下用于管理表和列族的 Admin 方法:

  • addColumnFamily(TableName tableName, ColumnFamilyDescriptor columnFamily) 和 addColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamily)(HBase 1.x:addColumn(TableName tableName, HColumnDescriptor column))
  • createTable(TableDescriptor desc)、createTable(TableDescriptor desc, byte[][] splitKeys)、createTable(TableDescriptor desc, byte[] startKey, byte[] endKey, int numRegions)、createTableAsync(TableDescriptor desc)和 createTableAsync(TableDescriptor desc, byte[][] splitKeys)
  • deleteColumnFamily(TableName tableName, byte[] columnName) 和 deleteColumnFamilyAsync(TableName tableName, byte[] columnName)(HBase 1.x:deleteColumn(TableName tableName, byte[] columnName))
  • deleteTable(TableName tableName)、deleteTableAsync(TableName tableName)、deleteTables(Pattern pattern)和 deleteTables(String regex)
  • disableTable(TableName tableName)、disableTableAsync(TableName tableName)、disableTables(Pattern pattern)和disableTables(String regex)
  • enableTable(TableName tableName)、enableTableAsync(TableName tableName)、enableTables(Pattern pattern)和 enableTables(String regex)
  • getAlterStatus(TableName tableName)和getAlterStatus(byte[] tableName)之间
  • getDescriptor(TableName tableName)、getTableDescriptor(TableName tableName)、getTableDescriptors(List<String> names)和 getTableDescriptorsByTableName(List<TableName> tableNames)
  • isTableAvailable(TableName tableName)和isTableAvailable(TableName tableName, byte[][] splitKeys)之间
  • isTableDisabled(TableName tableName)和isTableEnabled(TableName tableName)之间
  • listTableDescriptors()、listTableDescriptors(List<TableName> tableNames)、listTableDescriptors(Pattern pattern) 和 listTableDescriptors(Pattern pattern, boolean includeSysTables)(HBase 1.x:listTables()、listTables(Pattern pattern)、listTables(Pattern pattern, boolean includeSysTables)、listTables(String regex) 和 listTables(String regex, boolean includeSysTables))
  • listTableNames()、listTableNames(Pattern pattern)、listTableNames(Pattern pattern, boolean includeSysTables)、listTableNames(String regex)和listTableNames(String regex, boolean includeSysTables)
  • modifyColumnFamily(TableName tableName, ColumnFamilyDescriptor columnFamily) 和 modifyColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamily)(HBase 1.x:modifyColumn(TableName tableName, HColumnDescriptor column))
  • modifyTable(TableDescriptor td)、modifyTable(TableName tableName, TableDescriptor td)、modifyTableAsync(TableDescriptor td)和 modifyTableAsync(TableName tableName, TableDescriptor td)
  • tableExists(TableName tableName)
  • truncateTable(TableName tableName, boolean preserveSplits) 和 truncateTableAsync(TableName tableName, boolean preserveSplits)

以下受支持的表管理方法在 Bigtable 上的行为有所不同,或者会忽略某些参数:

  • 无法停用 Bigtable 表。disableTable()、disableTableAsync()、disableTables()、enableTable()、enableTableAsync() 和 enableTables() 仅在客户端内存(isTableDisabled() 和 isTableEnabled() 读取)中更改表的状态。
  • modifyTable() 和 modifyTableAsync() 仅对列族应用更改。表级属性会被忽略。
  • truncateTable() 和 truncateTableAsync() 会删除表中的所有数据。系统会忽略 preserveSplits 参数。
  • 接受 includeSysTables 参数的 listTableDescriptors()、listTables() 和 listTableNames() 重载会忽略 includeSysTables,因为 Bigtable 没有系统表。
  • isTableAvailable(TableName tableName, byte[][] splitKeys) 仅检查表是否存在,并忽略 splitKeys 参数。
  • getAlterStatus() 始终返回 (0, 0),因为 Bigtable 中的架构修改是同步的。

系统会自动处理表压缩和拆分等任务。因此,以下方法没有任何效果:

  • compact(TableName tableName)
  • compact(TableName tableName, byte[] columnFamily)
  • majorCompact(TableName tableName)
  • majorCompact(TableName tableName, byte[] columnFamily)
  • split(TableName tableName)
  • split(TableName tableName, byte[] splitPoint)

快照

HBase 快照方法可创建和管理 Bigtable 备份。由于备份存储在特定集群中,因此如果您的实例有多个集群,则必须将配置属性 google.bigtable.snapshot.cluster.id 设置为要使用的集群。您使用 snapshot() 创建的备份会在配置属性 google.bigtable.snapshot.default.ttl.secs 中的秒数(默认为 24 小时)后过期。cloneSnapshot() 会从备份恢复到新表。

Admin 中支持以下快照方法:

  • cloneSnapshot(byte[] snapshotName, TableName tableName)
  • cloneSnapshot(String snapshotName, TableName tableName)
  • deleteSnapshot(byte[] snapshotName)
  • deleteSnapshot(String snapshotName)
  • snapshot(byte[] snapshotName, TableName tableName)
  • snapshot(String snapshotName, TableName tableName)

此外,AsyncAdmin 还支持 listSnapshots()、listSnapshots(Pattern pattern) 和 snapshot(SnapshotDescription snapshot)。所有其他快照方法(包括 restoreSnapshot()、deleteSnapshots()、deleteTableSnapshots()、listTableSnapshots() 和 cloneSnapshot(String snapshotName, TableName tableName, boolean restoreAcl))均不受支持,并且会抛出 UnsupportedOperationException。

区域管理

Bigtable 使用片,这与区域类似。支持以下检索区域信息的方法,但与标准 HBase 存在差异:

  • getRegions(TableName tableName) 和 getTableRegions(TableName tableName) 以及接口 org.apache.hadoop.hbase.client.RegionLocator 中的方法会根据表中行键的样本返回近似边界。返回的区域中的服务器名称不是真实的服务器。
  • getRegionMetrics(ServerName serverName, TableName tableName) 会忽略 serverName 参数,并根据表中行键的样本返回近似区域大小指标。

由于 Bigtable 会自动管理您的片,因此以下方法没有任何效果:

  • assign(byte[] regionName)
  • compactRegion(byte[] regionName)
  • compactRegion(byte[] regionName, byte[] columnFamily)
  • flushRegion(byte[] regionName)
  • majorCompactRegion(byte[] regionName)
  • majorCompactRegion(byte[] regionName, byte[] columnFamily)
  • splitRegion(byte[] regionName)
  • splitRegion(byte[] regionName, byte[] splitPoint)

在 HBase 1.x 中,compactRegionServer(ServerName sn, boolean major)、mergeRegions(byte[] encodedNameOfRegionA, byte[] encodedNameOfRegionB, boolean forcible)、move(byte[] encodedRegionName, byte[] destServerName) 和 unassign(byte[] regionName, boolean force) 也没有任何效果。不支持其 HBase 2.x 等效项,并会抛出 UnsupportedOperationException。

集群状态和连接

Bigtable 会自动处理集群维护任务,因此 Admin 中的维护方法会抛出 UnsupportedOperationException。仅支持以下连接和状态方法:

  • close() 不会产生任何影响。
  • getClusterMetrics()、getClusterMetrics(EnumSet<Option> options) 和 getClusterStatus() 会返回带有空服务器列表的占位值,并且 getClusterMetrics(EnumSet<Option> options) 会忽略 options 参数。
  • getConfiguration() 会返回客户端 Configuration 对象。
  • getConnection() 会返回客户端 Connection 对象。

命名空间

Bigtable 不使用命名空间。您可以使用行键前缀来模拟命名空间。

默认情况下,所有命名空间方法都会抛出 UnsupportedOperationException。但是,如果您将配置属性 google.bigtable.namespace.warnings 设置为 true,则以下方法会记录警告且不会产生任何影响(返回 null 或空结果),而不是抛出异常:

  • createNamespace(NamespaceDescriptor descriptor)
  • deleteNamespace(String name)
  • deleteNamespaceAsync(String name)
  • getNamespaceDescriptor(String name)
  • listNamespaceDescriptors()
  • listTableDescriptorsByNamespace(byte[] name)
  • listTableDescriptorsByNamespace(String name)
  • listTableNamesByNamespace(String name)
  • modifyNamespace(NamespaceDescriptor descriptor)

即使 google.bigtable.namespace.warnings 设置为 true,listNamespaces() 也会抛出 UnsupportedOperationException。

其他管理功能

Bigtable 不支持以下类别中的 Admin 方法,调用这些方法会抛出 UnsupportedOperationException:

  • 位置组:Bigtable 不允许您为列族指定位置组。
  • 协处理器和分布式过程:Bigtable 不支持协处理器或分布式过程。
  • 配额:如需了解 Bigtable 配额,请参阅配额和限制。
  • 复制:Bigtable 会自动在实例中的集群之间复制数据。如需了解详情,请参阅复制概览。如需从 HBase 复制到 Bigtable,请参阅从 HBase 复制到 Bigtable。
  • 访问权限控制:Bigtable 使用 IAM 进行访问权限控制。
  • RegionServer 组:Bigtable 会自动管理服务器,不会公开 RegionServer 组。