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 会为您管理底层存储:
BLOCKCACHEBLOCKSIZEBLOOMFILTERCACHE_BLOOMS_ON_WRITECACHE_DATA_IN_L1CACHE_DATA_ON_WRITECACHE_INDEX_ON_WRITECOMPRESS_TAGSCOMPRESSIONCOMPRESSION_COMPACTDATA_BLOCK_ENCODINGEVICT_BLOCKS_ON_CLOSEIN_MEMORYKEEP_DELETED_CELLSPREFETCH_BLOCKS_ON_OPENREPLICATION_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 中,发送到单元格的写入请求不会受之前发送到同一单元格的删除请求的影响。
获取和扫描
- 借助反向扫描,您可以反向读取一系列行。如需了解详情,请参阅反向扫描。
- 与 HBase 不同,当您发送读取请求时,Bigtable 不会自动滤除在即将到来的垃圾回收周期中标记为待删除的过期数据。为避免读取过期数据,请在读取请求中使用过滤条件。如需了解详情,请参阅垃圾回收概览。
- 不支持限制每列族每行的值数量。您无法调用
org.apache.hadoop.hbase.client.Scan#setMaxResultsPerColumnFamily(int limit)方法。 - 不支持部分结果。返回的行始终是完整的。对
org.apache.hadoop.hbase.client.Scan#setBatch(int batch)和org.apache.hadoop.hbase.client.Scan#setAllowPartialResults(boolean allowPartialResults)方法的调用会被忽略。 - 在同步
Table#getScanner(Scan)调用中,org.apache.hadoop.hbase.client.Scan#setCaching(int caching)控制客户端一次提取的行数。AsyncTable#getScanner()会忽略setCaching()。对org.apache.hadoop.hbase.client.Scan#setMaxResultSize(long maxResultSize)方法的调用始终会被忽略。
协处理器
不支持协处理器。您无法创建实现 org.apache.hadoop.hbase.coprocessor 接口的类。
过滤条件
下表列出了软件包 org.apache.hadoop.hbase.filter 中支持的过滤条件。该软件包中的所有其他过滤条件均不受支持,并且会抛出 UnsupportedOperationException。
| 支持 | 受支持(存在限制) |
|---|---|
|
|
ColumnCountGetFilterColumnPrefixFilterFilterListFirstKeyOnlyFilterFuzzyRowFilterMultipleColumnPrefixFilterPrefixFilter 1RandomRowFilterTimestampsFilter
|
ColumnPaginationFilter 2ColumnRangeFilter 3FamilyFilter 4KeyOnlyFilter 5MultiRowRangeFilter 6PageFilter 7QualifierFilter 8RowFilter 4SingleColumnValueExcludeFilter 3、9、10SingleColumnValueFilter 9、10ValueFilter 9WhileMatchFilter 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 组。