将数据从 Apache HBase 迁移到 Azure Cosmos DB for NoSQL 帐户
适用范围: NoSQL
Azure Cosmos DB 是可缩放的多区域分布式完全托管型数据库。 它能够确保数据访问延迟较低。 若要详细了解 Azure Cosmos DB,请参阅概述一文。 本文指导如何将数据从 HBase 迁移到 Azure Cosmos DB for NoSQL 帐户。
Azure Cosmos DB 与 HBase 之间的差异
在迁移之前,必须了解 Azure Cosmos DB 与 HBase 之间的差异。
资源模型
Azure Cosmos DB 具有以下资源模型:
HBase 具有以下资源模型:
资源映射
下表显示了 Apache HBase、Apache Phoenix 和 Azure Cosmos DB 之间的概念映射。
HBase | Phoenix | Azure Cosmos DB |
---|---|---|
群集 | 群集 | 帐户 |
命名空间 | 架构(如果启用) | 数据库 |
表 | 表 | 容器/集合 |
列系列 | 列系列 | 空值 |
行 | 行 | 项/文档 |
版本(时间戳) | 版本(时间戳) | 空值 |
空值 | 主键 | 分区键 |
空值 | 索引 | 索引 |
空值 | 辅助索引 | 辅助索引 |
空值 | 视图 | 空值 |
空值 | 序列 | 空值 |
数据结构比较和差异
Azure Cosmos DB 与 HBase 的数据结构之间的主要差异如下所示:
RowKey
在 HBase 中,数据通过 RowKey 进行存储,并按表创建期间指定的 RowKey 范围水平分区为各个区域。
另一端的 Azure Cosmos DB 基于指定分区键的哈希值将数据分布到分区中。
列系列
在 HBase 中,列按列系列 (CF) 进行分组。
Azure Cosmos DB (API for NoSQL) 将数据存储为 JSON 文档。 因此,与 JSON 数据结构关联的所有属性都适用。
Timestamp
HBase 使用时间戳为给定单元的多个实例确定版本。 可以使用时间戳查询单元的不同版本。
Azure Cosmos DB 具备更改源功能,该功能会按发生顺序跟踪对容器进行的更改的持久记录。 然后,它会按照所更改文档的修改顺序输出这些文档的排序列表。
数据格式
HBase 数据格式由 RowKey、列系列:列名、时间戳和值组成。 下面是 HBase 表行的示例:
ROW COLUMN+CELL 1000 column=Office:Address, timestamp=1611408732448, value=1111 San Gabriel Dr. 1000 column=Office:Phone, timestamp=1611408732418, value=1-425-000-0002 1000 column=Personal:Name, timestamp=1611408732340, value=John Dole 1000 column=Personal:Phone, timestamp=1611408732385, value=1-425-000-0001
在 Azure Cosmos DB for NoSQL 中,JSON 对象表示数据格式。 分区键驻留在文档的字段中,并设置哪个字段是集合的分区键。 Azure Cosmos DB 没有用于列系列或版本的时间戳概念。 如前面强调的那样,它具有更改源支持,通过该支持可以跟踪/记录对容器执行的更改。 下面是文档的示例。
{ "RowId": "1000", "OfficeAddress": "1111 San Gabriel Dr.", "OfficePhone": "1-425-000-0002", "PersonalName": "John Dole", "PersonalPhone": "1-425-000-0001", }
提示
HBase 将数据存储在字节数组中,因此,如果要将包含双字节字符的数据迁移到 Azure Cosmos DB,则数据必须进行 UTF-8 编码。
一致性模型
HBase 提供严格一致的读取和写入。
Azure Cosmos DB 提供五个妥善定义的一致性级别。 每个级别在可用性与性能方面各有利弊。 支持的一致性级别如下(从最强到最弱):
- 强
- 有限过期性
- 会话
- 一致前缀
- 最终
调整大小
HBase
对于 HBase 的企业规模部署,Master、区域服务器和 ZooKeeper 推动了大量的调整大小操作。 与任何分布式应用程序一样,HBase 设计为可横向扩展。HBase 性能主要取决于 HBase 区域服务器的大小。 调整大小主要取决于两个关键要求 � 必须存储在 HBase 上的数据集的吞吐量和大小。
Azure Cosmos DB
Azure Cosmos DB 是一种来自 Azure 的 PaaS 产品/服务,底层基础结构部署详细信息是从最终用户抽象而来。 对 Azure Cosmos DB 容器进行预配后,Azure 平台会自动预配底层基础结构(计算、存储、内存、网络堆栈),以支持给定工作负载的性能要求。 所有数据库操作的成本将由 Azure Cosmos DB 规范化,并以“请求单位”(缩写为 RU)表示。
若要估计工作负载消耗的 RU 数量,请考虑以下因素:
有一个可用的容量计算器,用于协助进行针对 US 大小调整的练习。
还可以在 Azure Cosmos DB 中使用自动缩放预配吞吐量,立即自动缩放数据库或容器吞吐量(RU/秒)。 吞吐量会根据使用情况进行缩放,而不会影响工作负载可用性、延迟、吞吐量或性能。
数据分布
HBase HBase 根据 RowKey 对数据进行排序。 数据随后会分区到区域中并存储在区域服务器中。 自动分区会根据分区策略水平划分区域。 这由分配给 HBase 参数 hbase.hregion.max.filesize
的值(默认值为 10 GB)进行控制。 HBase 中具有给定 RowKey 的行始终属于一个区域。 此外,每个列系列的数据会在磁盘上分隔。 这样便可以在读取时进行筛选并对 HFile 隔离 I/O。
Azure Cosmos DB Azure Cosmos DB 使用分区缩放数据库中的单个容器。 分区会将容器中的项划分到称为“逻辑分区”的特定子集中。 逻辑分区是根据与容器中每个项关联的“分区键”值形成的。 逻辑分区中的所有项具有相同的分区键值。 每个逻辑分区最多可以保存 20 GB 数据。
每个物理分区都包含一个数据副本和一个 Azure Cosmos DB 数据库引擎实例。 此结构使数据持久且高度可用,并在本地物理分区之间平均划分吞吐量。 物理分区自动进行创建和配置,并且无法控制其大小、位置或它们所包含的逻辑分区。 逻辑分区不会在物理分区之间进行拆分。
与 HBase RowKey 一样,分区键设计对于 Azure Cosmos DB 十分重要。 HBase 的行键的工作方式是对数据进行排序并存储连续数据,而 Azure Cosmos DB 的分区键是一种不同的机制,因为它会对数据进行哈希分布。 假设使用 HBase 的应用程序针对 HBase 的数据访问模式进行了优化,则对分区键使用相同的 RowKey 不会产生良好的性能结果。 考虑到这是 HBase 上的排序数据,Azure Cosmos DB 组合索引可能十分有用。 如果要在多个字段中使用 ORDER BY 子句,则它是必需的。 还可以通过定义组合索引来改善许多相等性和范围查询的性能。
可用性
HBase HBase 由 Master、区域服务器和 ZooKeeper 组成。 通过使每个组件冗余,可以实现单个群集的高可用性。 配置异地冗余时,可以在不同物理数据中心间部署 HBase 群集,并使用复制使多个群集保持同步。
Azure Cosmos DB Azure Cosmos DB 不需要任何配置,例如群集组件冗余。 它可为高可用性、一致性和延迟提供综合性 SLA。 有关详细信息,请参阅 Azure Cosmos DB 的 SLA。
数据可靠性
HBase HBase 基于 Hadoop 分布式文件系统 (HDFS) 进行构建,HDFS 上存储的数据会复制三次。
Azure Cosmos DB Azure Cosmos DB 主要通过两种方式提供高可用性。 第一种方式是 Azure Cosmos DB 在 Azure Cosmos DB 帐户中配置的区域之间复制数据。 第二种方式是 Azure Cosmos DB 在区域内保留数据的四个副本。
迁移之前的注意事项
系统依赖项
规划的此方面侧重于了解要迁移到 Azure Cosmos DB 的 HBase 实例的上游和下游依赖项。
下游依赖项的示例可能是从 HBase 读取数据的应用程序。 这些应用程序必须重构才能从 Azure Cosmos DB 进行读取。 在迁移过程中必须考虑以下几点:
用于评估依赖项的问题 - 当前 HBase 系统是否为独立组件? 或者,它是否调用了另一个系统上的进程,或它是否由另一个系统上的进程进行调用,或它是否使用目录服务进行访问? 是否有其他重要进程在 HBase 群集中工作? 需要阐明这些系统依赖项,以确定迁移的影响。
本地 HBase 部署的 RPO 和 RTO。
脱机与联机迁移
若要成功进行数据迁移,必须了解使用数据库的业务的特征并决定如何执行该操作。 如果可以完全关闭系统,执行数据迁移,然后在目标位置重新启动系统,请选择脱机迁移。 此外,如果数据库始终繁忙,并且你不能承受较长中断时间,请考虑联机迁移。
注意
本文档仅涵盖脱机迁移。
执行脱机数据迁移时,这取决于当前运行的 HBase 版本和可用的工具。 请参阅数据迁移部分以了解更多详细信息。
性能注意事项
规划的此方面是了解 HBase 的性能目标,然后将它们转换为 Azure Cosmos DB 语义。 例如,若要在 HBase 上达到“X”IOPS,Azure Cosmos DB 中需要多少个请求单位(RU/秒)。 HBase 与 Azure Cosmos DB 之间存在差异,此练习侧重于介绍如何将 HBase 中的性能目标转换到 Azure Cosmos DB。 这会推动缩放练习。
提出的问题:
- HBase 部署是读取密集型还是写入密集型?
- 读取与写入之间的拆分是什么?
- 目标 IOPS 表示为多少百分位?
- 使用哪些/如何使用应用程序将数据加载到 HBase?
- 使用哪些/如何使用应用程序从 HBase 读取数据?
执行请求排序数据的查询时,HBase 会快速返回结果,因为数据是按 RowKey 进行排序。 但是,Azure Cosmos DB 没有这样一种概念。 若要优化性能,可以根据需要使用组合索引。
部署注意事项
可以使用 Azure 门户或 Azure CLI 部署 Azure Cosmos DB for NoSQL。 由于迁移目标是 Azure Cosmos DB for NoSQL,因此在部署时,请选择 API 的“NoSQL”作为参数。 此外,根据可用性要求设置异地冗余、多区域写入和可用性区域。
网络注意事项
Azure Cosmos DB 有三种主要网络选项。 第一种是使用公共 IP 地址并使用 IP 防火墙控制访问的配置(默认)。 第二种是使用公共 IP 地址,并且只允许从特定虚拟网络的特定子网进行访问的配置(服务终结点)。 第三种是使用专用 IP 地址加入专用网络的配置(专用终结点)。
有关三种网络选项的详细信息,请参阅以下文档:
评估现有数据
数据发现
从现有 HBase 群集提前收集信息,以确定要迁移的数据。 这些信息可帮助确定如何迁移、决定要迁移的表、了解这些表中的结构以及决定如何生成数据模型。 例如,收集如下所示的详细信息:
- HBase 版本
- 迁移目标表
- 列系列信息
- 表状态
以下命令演示如何使用 hbase shell 脚本收集以上详细信息,并将其存储在操作系统的本地文件系统中。
获取 HBase 版本
hbase version -n > hbase-version.txt
输出:
cat hbase-version.txt
HBase 2.1.8.4.1.2.5
获取表的列表
可以获取 HBase 中存储的表的列表。 如果创建了非默认命名空间,则它会以“命名空间: 表”格式输出。
echo "list" | hbase shell -n > table-list.txt
HBase 2.1.8.4.1.2.5
输出:
echo "list" | hbase shell -n > table-list.txt
cat table-list.txt
TABLE
COMPANY
Contacts
ns1:t1
3 row(s)
Took 0.4261 seconds
COMPANY
Contacts
ns1:t1
确定要迁移的表
通过指定要迁移的表名,获取表中列系列的详细信息。
echo "describe '({Namespace}:){Table name}'" | hbase shell -n > {Table name} -schema.txt
输出:
cat {Table name} -schema.txt
Table {Table name} is ENABLED
{Table name}
COLUMN FAMILIES DESCRIPTION
{NAME => 'cf1', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
{NAME => 'cf2', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
2 row(s)
Took 0.5775 seconds
获取表中的列系列及其设置
echo "status 'detailed'" | hbase shell -n > hbase-status.txt
输出:
{HBase version}
0 regionsInTransition
active master: {Server:Port number}
2 backup masters
{Server:Port number}
{Server:Port number}
master coprocessors: []
# live servers
{Server:Port number}
requestsPerSecond=0.0, numberOfOnlineRegions=44, usedHeapMB=1420, maxHeapMB=15680, numberOfStores=49, numberOfStorefiles=14, storefileUncompressedSizeMB=7, storefileSizeMB=7, compressionRatio=1.0000, memstoreSizeMB=0, storefileIndexSizeKB=15, readRequestsCount=36210, filteredReadRequestsCount=415729, writeRequestsCount=439, rootIndexSizeKB=15, totalStaticIndexSizeKB=5, totalStaticBloomSizeKB=16, totalCompactingKVs=464, currentCompactedKVs=464, compactionProgressPct=1.0, coprocessors=[GroupedAggregateRegionObserver, Indexer, MetaDataEndpointImpl, MetaDataRegionObserver, MultiRowMutationEndpoint, ScanRegionObserver, SecureBulkLoadEndpoint, SequenceRegionObserver, ServerCachingEndpointImpl, UngroupedAggregateRegionObserver]
[...]
"Contacts,,1611126188216.14a597a0964383a3d923b2613524e0bd."
numberOfStores=2, numberOfStorefiles=2, storefileUncompressedSizeMB=7168, lastMajorCompactionTimestamp=0, storefileSizeMB=7, compressionRatio=0.0010, memstoreSizeMB=0, readRequestsCount=4393, writeRequestsCount=0, rootIndexSizeKB=14, totalStaticIndexSizeKB=5, totalStaticBloomSizeKB=16, totalCompactingKVs=0, currentCompactedKVs=0, compactionProgressPct=NaN, completeSequenceId=-1, dataLocality=0.0
[...]
可以获取有用的调整大小信息,例如堆内存的大小、区域数、作为群集状态的请求数以及以表状态形式进行压缩/解压缩的数据大小。
如果要在 HBase 群集上使用 Apache Phoenix,则还需要从 Phoenix 收集数据。
- 迁移目标表
- 表架构
- 索引
- 主密钥
在群集上连接到 Apache Phoenix
sqlline.py ZOOKEEPER/hbase-unsecure
获取表列表
!tables
获取表详细信息
!describe <Table Name>
获取索引详细信息
!indexes <Table Name>
获取主键详细信息
!primarykeys <Table Name>
迁移数据
迁移选项
可使用多种方法脱机迁移数据,但下面我们将介绍如何使用 Azure 数据工厂。
解决方案 | 源版本 | 注意事项 |
---|---|---|
Azure 数据工厂 | HBase < 2 | 易于设置。 适合用于大型数据集。 不支持 HBase 2 或更高版本。 |
Apache Spark | 所有版本 | 支持 HBase 的所有版本。 适合用于大型数据集。 需要 Spark 设置。 |
包含 Azure Cosmos DB 批量执行程序库的自定义工具 | 所有版本 | 最灵活,可使用库创建自定义数据迁移工具。 需要进行更多设置工作。 |
以下流程图使用某些条件访问可用的数据迁移方法。
使用数据工厂进行迁移
此选项适用于大型数据集。 会使用 Azure Cosmos DB 批量执行工具库。 没有检查点,因此如果在迁移过程中遇到任何问题,则必须从头开始重启迁移过程。 还可以使用数据工厂的自承载集成运行时连接到本地 HBase,或将数据工厂部署到托管 VNET,并通过 VPN 或 ExpressRoute 连接到本地网络。
数据工厂的复制活动支持将 HBase 作为数据源。 有关更多详细信息,请参阅使用 Azure 数据工厂从 HBase 复制数据一文。
可以指定 Azure Cosmos DB (API for NoSQL) 作为数据的目标。 有关详细信息,请参阅使用 Azure 数据工厂复制和转换 Azure Cosmos DB (API for NoSQL) 中的数据一文。
使用 Apache Spark 进行迁移 - Apache HBase 连接器和 Azure Cosmos DB Spark 连接器
下面是将数据迁移到 Azure Cosmos DB 的示例。 它假定 HBase 2.1.0 和 Spark 2.4.0 在同一群集中运行。
Apache Spark � Apache HBase 连接器存储库可以在 Apache Spark - Apache HBase 连接器处找到
对于 Azure Cosmos DB Spark 连接器,请参阅快速入门指南并下载适用于 Spark 版本的相应库。
将 hbase-site.xml 复制到 Spark 配置目录。
cp /etc/hbase/conf/hbase-site.xml /etc/spark2/conf/
用 Spark HBase 连接器和 Azure Cosmos DB Spark 连接器运行 spark -shell。
spark-shell --packages com.hortonworks.shc:shc-core:1.1.0.3.1.2.2-1 --repositories http://repo.hortonworcontent/groups/public/ --jars azure-cosmosdb-spark_2.4.0_2.11-3.6.8-uber.jar
Spark shell 启动后,按如下所示执行 Scala 代码。 导入从 HBase 加载数据所需的库。
// Import libraries import org.apache.spark.sql.{SQLContext, _} import org.apache.spark.sql.execution.datasources.hbase._ import org.apache.spark.{SparkConf, SparkContext} import spark.sqlContext.implicits._
为 HBase 表定义 Spark 目录架构。 此处的命名空间为“default”,表名为“Contacts”。 行键指定为键。 列、列系列和列会映射到 Spark 的目录。
// define a catalog for the Contacts table you created in HBase def catalog = s"""{ |"table":{"namespace":"default", "name":"Contacts"}, |"rowkey":"key", |"columns":{ |"rowkey":{"cf":"rowkey", "col":"key", "type":"string"}, |"officeAddress":{"cf":"Office", "col":"Address", "type":"string"}, |"officePhone":{"cf":"Office", "col":"Phone", "type":"string"}, |"personalName":{"cf":"Personal", "col":"Name", "type":"string"}, |"personalPhone":{"cf":"Personal", "col":"Phone", "type":"string"} |} |}""".stripMargin
接下来,将用于从 HBase Contacts 表获取数据的方法作为 DataFrame。
def withCatalog(cat: String): DataFrame = { spark.sqlContext .read .options(Map(HBaseTableCatalog.tableCatalog->cat)) .format("org.apache.spark.sql.execution.datasources.hbase") .load() }
使用定义的方法创建 DataFrame。
val df = withCatalog(catalog)
然后导入使用 Azure Cosmos DB Spark 连接器所需的库。
import com.microsoft.azure.cosmosdb.spark.schema._ import com.microsoft.azure.cosmosdb.spark._ import com.microsoft.azure.cosmosdb.spark.config.Config
进行用于将数据写入 Azure Cosmos DB 的设置。
val writeConfig = Config(Map( "Endpoint" -> "https://<cosmos-db-account-name>.documents.azure.cn:443/", "Masterkey" -> "<comsmos-db-master-key>", "Database" -> "<database-name>", "Collection" -> "<collection-name>", "Upsert" -> "true" ))
将 DataFrame 数据写入 Azure Cosmos DB。
import org.apache.spark.sql.SaveMode df.write.mode(SaveMode.Overwrite).cosmosDB(writeConfig)
它以高速方式并行写入,其性能较高。 另一方面,请注意,它可能会占用 Azure Cosmos DB 端的 RU/秒。
Phoenix
支持将 Phoenix 作为数据工厂数据源。 有关详细步骤,请参阅以下文档。
迁移代码
此部分介绍在 Azure Cosmos DB for NoSQL 和 HBase 中创建应用程序之间的差异。 此处的示例使用 Apache HBase 2.x API 和 Azure Cosmos DB Java SDK v4。
这些 HBase 的示例代码基于 HBase 的官方文档中所述的内容。
此处展示的 Azure Cosmos DB 的代码基于 Azure Cosmos DB for NoSQL:Java SDK v4 示例文档。 可以从该文档访问完整代码示例。
此处显示了代码迁移的映射,但这些示例中使用的 HBase RowKeys 和 Azure Cosmos DB 分区键并不总是拥有良好的设计。 根据迁移源的实际数据模型进行设计。
建立连接
HBase
Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum","zookeepernode0,zookeepernode1,zookeepernode2");
config.set("hbase.zookeeper.property.clientPort", "2181");
config.set("hbase.cluster.distributed", "true");
Connection connection = ConnectionFactory.createConnection(config)
Phoenix
//Use JDBC to get a connection to an HBase cluster
Connection conn = DriverManager.getConnection("jdbc:phoenix:server1,server2:3333",props);
Azure Cosmos DB
// Create sync client
client = new CosmosClientBuilder()
.endpoint(AccountSettings.HOST)
.key(AccountSettings.MASTER_KEY)
.consistencyLevel(ConsistencyLevel.{ConsistencyLevel})
.contentResponseOnWriteEnabled(true)
.buildClient();
创建数据库/表/集合
HBase
// create an admin object using the config
HBaseAdmin admin = new HBaseAdmin(config);
// create the table...
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("FamilyTable"));
// ... with single column families
tableDescriptor.addFamily(new HColumnDescriptor("ColFam"));
admin.createTable(tableDescriptor);
Phoenix
CREATE IF NOT EXISTS FamilyTable ("id" BIGINT not null primary key, "ColFam"."lastName" VARCHAR(50));
Azure Cosmos DB
// Create database if not exists
CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists(databaseName);
database = client.getDatabase(databaseResponse.getProperties().getId());
// Create container if not exists
CosmosContainerProperties containerProperties = new CosmosContainerProperties("FamilyContainer", "/lastName");
// Provision throughput
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);
// Create container with 400 RU/s
CosmosContainerResponse databaseResponse = database.createContainerIfNotExists(containerProperties, throughputProperties);
container = database.getContainer(databaseResponse.getProperties().getId());
创建行/文档
HBase
HTable table = new HTable(config, "FamilyTable");
Put put = new Put(Bytes.toBytes(RowKey));
put.add(Bytes.toBytes("ColFam"), Bytes.toBytes("id"), Bytes.toBytes("1"));
put.add(Bytes.toBytes("ColFam"), Bytes.toBytes("lastName"), Bytes.toBytes("Witherspoon"));
table.put(put)
Phoenix
UPSERT INTO FamilyTable (id, lastName) VALUES (1, �Witherspoon�);
Azure Cosmos DB
Azure Cosmos DB 通过数据模型来确保类型安全。 我们使用名为“Family”的数据模型。
public class Family {
public Family() {
}
public void setId(String id) {
this.id = id;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
private String id="";
private String lastName="";
}
上面是代码的一部分。 请参阅完整代码示例。
使用 Family 类定义文档并插入项。
Family family = new Family();
family.setLastName("Witherspoon");
family.setId("1");
// Insert this item as a document
// Explicitly specifying the /pk value improves performance.
container.createItem(family,new PartitionKey(family.getLastName()),new CosmosItemRequestOptions());
读取行/文档
HBase
HTable table = new HTable(config, "FamilyTable");
Get get = new Get(Bytes.toBytes(RowKey));
get.addColumn(Bytes.toBytes("ColFam"), Bytes.toBytes("lastName"));
Result result = table.get(get);
byte[] col = result.getValue(Bytes.toBytes("ColFam"), Bytes.toBytes("lastName"));
Phoenix
SELECT lastName FROM FamilyTable;
Azure Cosmos DB
// Read document by ID
Family family = container.readItem(documentId,new PartitionKey(documentLastName),Family.class).getItem();
String sql = "SELECT lastName FROM c";
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(sql, new CosmosQueryRequestOptions(), Family.class);
更新数据
HBase
对于 HBase,使用 append 方法和 checkAndPut 方法更新值。 “追加”是一个以原子方式将值追加到当前值末尾的过程,而 checkAndPut 以原子方式将当前值与预期值进行比较,并仅在它们匹配时进行更新。
// append
HTable table = new HTable(config, "FamilyTable");
Append append = new Append(Bytes.toBytes(RowKey));
Append.add(Bytes.toBytes("ColFam"), Bytes.toBytes("id"), Bytes.toBytes(2));
Append.add(Bytes.toBytes("ColFam"), Bytes.toBytes("lastName"), Bytes.toBytes("Harris"));
Result result = table.append(append)
// checkAndPut
byte[] row = Bytes.toBytes(RowKey);
byte[] colfam = Bytes.toBytes("ColFam");
byte[] col = Bytes.toBytes("lastName");
Put put = new Put(row);
put.add(colfam, col, Bytes.toBytes("Patrick"));
boolearn result = table.checkAndPut(row, colfam, col, Bytes.toBytes("Witherspoon"), put);
Phoenix
UPSERT INTO FamilyTable (id, lastName) VALUES (1, �Brown�)
ON DUPLICATE KEY UPDATE id = "1", lastName = "Whiterspoon";
Azure Cosmos DB
在 Azure Cosmos DB 中,更新被视为更新插入操作。 也就是说,如果文档不存在,将插入该文档。
// Replace existing document with new modified document (contingent on modification).
Family family = new Family();
family.setLastName("Brown");
family.setId("1");
CosmosItemResponse<Family> famResp = container.upsertItem(family, new CosmosItemRequestOptions());
删除行/文档
HBase
在 Hbase 中,没有按值选择行的直接删除方法。 你可能已与 ValueFilter 等一起实现了删除过程。在此示例中,要删除的行通过 RowKey 指定。
HTable table = new HTable(config, "FamilyTable");
Delete delete = new Delete(Bytes.toBytes(RowKey));
delete.deleteColumn(Bytes.toBytes("ColFam"), Bytes.toBytes("id"));
delete.deleteColumn(Bytes.toBytes("ColFam"), Bytes.toBytes("lastName"));
table.dalate(delete)
Phoenix
DELETE FROM TableName WHERE id = "xxx";
Azure Cosmos DB
下面显示了按文档 ID 进行的删除方法。
container.deleteItem(documentId, new PartitionKey(documentLastName), new CosmosItemRequestOptions());
查询行/文档
HBase HBase 允许使用扫描检索多个行。 可以使用筛选器指定详细扫描条件。 请参阅客户端请求筛选器以了解 HBase 内置筛选器类型。
HTable table = new HTable(config, "FamilyTable");
Scan scan = new Scan();
SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("ColFam"),
Bytes.toBytes("lastName"), CompareOp.EQUAL, New BinaryComparator(Bytes.toBytes("Witherspoon")));
filter.setFilterIfMissing(true);
filter.setLatestVersionOnly(true);
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
Phoenix
SELECT * FROM FamilyTable WHERE lastName = "Witherspoon"
Azure Cosmos DB
筛选器操作
String sql = "SELECT * FROM c WHERE c.lastName = 'Witherspoon'";
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(sql, new CosmosQueryRequestOptions(), Family.class);
删除表/集合
HBase
HBaseAdmin admin = new HBaseAdmin(config);
admin.deleteTable("FamilyTable")
Phoenix
DROP TABLE IF EXISTS FamilyTable;
Azure Cosmos DB
CosmosContainerResponse containerResp = database.getContainer("FamilyContainer").delete(new CosmosContainerRequestOptions());
其他注意事项
HBase 群集可以与 HBase 工作负载以及 MapReduce、Hive、Spark 等一起使用。 如果具有使用当前 HBase 的其他工作负载,则也需要迁移它们。 有关详细信息,请参阅每个迁移指南。
- MapReduce
- HBase
- Spark
服务器端编程
HBase 提供多种服务器端编程功能。 如果使用这些功能,则还需要迁移其处理。
HBase
-
各种筛选器在 HBase 中作为默认设置提供,但你也可以实现自己的自定义筛选器。 如果 HBase 上作为默认设置提供的筛选器不符合要求,则可以实现自定义筛选器。
-
协处理器是一种框架,可用于在区域服务器上运行自己的代码。 通过使用协处理器,可以在服务器端执行在客户端上执行的处理,并且根据处理情况,可以提高效率。 有两种类型的协处理器:观察者和终结点。
观察者
- 观察者挂钩特定操作和事件。 这是用于添加任意处理的函数。 这是类似于 RDBMS 触发器的功能。
端点
- 终结点是用于扩展 HBase RPC 的一种功能。 此功能类似于 RDBMS 存储过程。
Azure Cosmos DB
-
- Azure Cosmos DB 存储过程以 JavaScript 编写,可以执行在 Azure Cosmos DB 容器中创建、更新、读取、查询和删除项等操作。
-
- 可以为针对数据库执行的操作指定触发器。 提供了两种方法:在数据库项更改之前运行的前触发器,以及在数据库项更改之后运行的后触发器。
-
- Azure Cosmos DB 允许定义用户定义的函数 (UDF)。 也可以用 JavaScript 编写 UDF。
存储过程和触发器根据所执行的操作的复杂性来消耗 RU。 开发服务器端处理时,请检查所需使用情况,以更好地了解每个操作消耗的 RU 量。 有关详细信息,请参阅 Azure Cosmos DB 中的请求单位和优化 Azure Cosmos DB 中的请求成本。
服务器端编程映射
HBase | Azure Cosmos DB | 描述 |
---|---|---|
自定义筛选器 | 其中子句 | 如果 Azure Cosmos DB 中的 WHERE 子句无法实现自定义筛选器实现的处理,请结合使用 UDF。 |
协处理器(观察者) | 触发器 | 观察者是在特定事件之前和之后执行的触发器。 正如观察器支持前调用和后调用一样,Azure Cosmos DB 的触发器也支持前触发器和后触发器。 |
协处理器(终结点) | 存储过程 | 终结点是对每个区域执行的服务器端数据处理机制。 这类似于 RDBMS 存储过程。 Azure Cosmos DB 存储过程是使用 JavaScript 编写的。 它提供对可以通过存储过程在 Azure Cosmos DB 上执行的所有操作的访问权限。 |
注意
根据 HBase 上实现的处理,Azure Cosmos DB 中可能需要不同的映射和实现。
安全性
数据安全性的责任由客户和数据库提供程序共同分担。 对于本地解决方案,客户必须提供从终结点保护到物理硬件安全性的所有工作,这不是一个轻松的任务。 如果选择 PaaS 云数据库提供程序(例如 Azure Cosmos DB),客户参与量会减少。 Azure Cosmos DB 在 Azure 平台上运行,因此可以采用与 HBase 不同的方式来增强它。 Azure Cosmos DB 不需要安装任何额外组件来实现安全性。 建议考虑使用以下清单迁移数据库系统安全实现:
安全控制 | HBase | Azure Cosmos DB |
---|---|---|
网络安全和防火墙设置 | 使用网络设备等安全功能控制流量。 | 支持入站防火墙上基于策略的 IP 访问控制。 |
用户身份验证和精细用户控制 | 通过将 LDAP 与安全组件(如 Apache Ranger)组合在一起,进行精细的访问控制。 | 可使用帐户主密钥为每个数据库创建用户和权限资源。 也可使用 Microsoft Entra ID 对数据请求进行身份验证。 这使你可以使用精细 RBAC 模型向数据请求授权。 |
能够在多个区域复制数据来应对区域性故障 | 使用 HBase 的复制在远程数据中心创建数据库副本。 | Azure Cosmos DB 执行无配置多区域分布,并允许通过选择按钮将数据复制到中国区 Azure 周围的数据中心。 在安全性方面,多区域复制可确保数据免受本地故障影响。 |
能够从一个数据中心故障转移到另一个数据中心 | 你需要自行实现故障转移。 | 如果要将数据复制到多个数据中心,并且区域数据中心脱机运行,Azure Cosmos DB 会自动继续执行该操作。 |
在数据中心内执行本地数据复制 | HDFS 机制允许在单个文件系统中跨节点创建多个副本。 | Azure Cosmos DB 会自动复制数据以维护高可用性,即使在单个数据中心内也是如此。 可以自己选择一致性级别。 |
自动数据备份 | 没有自动备份功能。 你需要自己实现数据备份。 | Azure Cosmos DB 会定期备份并存储在异地冗余存储中。 |
保护和隔离敏感数据 | 例如,如果使用 Apache Ranger,则可使用 Ranger 策略将策略应用到表。 | 可将个人和其他敏感数据分隔到特定的容器中,并读取/写入数据,或限制对特定用户的只读访问。 |
监视攻击 | 此行为需使用第三方产品来实现。 | 使用审核日志和活动日志,可以监视帐户中的正常和异常活动。 |
响应攻击 | 此行为需使用第三方产品来实现。 | 与 Azure 支持部门联系并报告潜在攻击时,将开始一个五步事件响应过程。 |
能够地域隔离数据以遵守数据监管限制 | 需要检查每个国家/地区的限制,并自行实现。 | 保证对德国、中国、美国政府等主权区域的数据治理。 |
对受保护数据中心内的服务器实施物理保护 | 这取决于系统所在的数据中心。 | 有关最新认证的列表,请参阅多区域 Azure 合规性站点。 |
认证 | 取决于 Hadoop 发行版。 | 请参阅 Azure 合规性文档 |
监视
HBase 通常使用群集指标 Web UI 或是使用 Ambari、Cloudera Manager 或其他监视工具监视群集。 Azure Cosmos DB 允许使用内置在 Azure 平台中的监视机制。 有关 Azure Cosmos DB 监视的详细信息,请参阅监视 Azure Cosmos DB。
如果环境实现 HBase 系统监视以发送警报(例如通过电子邮件发送警报),则你可能能够将它替换为 Azure Monitor 警报。 可以基于 Azure Cosmos DB 帐户的指标或活动日志事件发出警报。
有关 Azure Monitor 中的警报的详细信息,请参阅使用 Azure Monitor 为 Azure Cosmos DB 创建警报
另请参阅可以由 Azure Monitor 收集的 Azure Cosmos DB 指标和日志类型。
备份和灾难恢复
备份
可通过多种方法获取 HBase 的备份。 例如,快照、导出、CopyTable、HDFS 数据的脱机备份和其他自定义备份。
Azure Cosmos DB 会定期自动备份数据,这不会影响数据库操作的性能或可用性。 备份存储在 Azure 存储中,可以用于在需要时恢复数据。 有两种类型的 Azure Cosmos DB 备份:
灾难恢复
HBase 是容错分布式系统,但是如果在数据中心级别发生故障时,备份位置需要故障转移,则必须使用快照、复制等实现灾难恢复。 可以采用三种复制模式设置 HBase 复制:“领导者-追随者”、“领导者-领导者”和“循环”。 如果源 HBase 实现灾难恢复,你则需要了解如何在 Azure Cosmos DB 中配置灾难恢复并满足系统要求。
Azure Cosmos DB 是一种多区域分布式数据库,具有内置灾难恢复功能。 可以将数据库数据复制到任何区域。 在某些区域中发生不太可能的故障时,Azure Cosmos DB 使数据库保持高度可用性。
仅使用单个区域的 Azure Cosmos DB 帐户可能在发生区域故障时失去可用性。 建议至少配置两个区域,以始终确保高可用性。 还可以确保写入和读取的高可用性,具体方法是将 Azure Cosmos DB 帐户配置为跨越至少两个包含多个写入区域的区域,以确保写入和读取的高可用性。 对于包含多个写入区域的多区域帐户,Azure Cosmos DB 客户端会检测并处理区域之间的故障转移。 这些是瞬间完成,不需要从应用程序进行任何更改。 这样便可以实现包含 Azure Cosmos DB 灾难恢复的可用性配置。 如前所述,可以使用三种模型来设置 HBase 复制,但可以通过配置单写入和多写入区域,使用基于 SLA 的可用性来设置 Azure Cosmos DB。
有关高可用性的详细信息,请参阅 Azure Cosmos DB 如何提供高可用性
常见问题解答
为什么迁移到 API for NoSQL 而不是 Azure Cosmos DB 中的其他 API?
API for NoSQL 在接口和服务 SDK 客户端库方面提供最佳的端到端体验。 向 Azure Cosmos DB 推出的新功能首先会在 API for NoSQL 帐户中提供。 此外,API for NoSQL 支持分析,并在生产和分析工作负载之间提供性能隔离。 如果要使用现代化技术来生成应用,API for NoSQL 则是建议选项。
是否可以将 HBase RowKey 分配给 Azure Cosmos DB 分区键?
它可能不会那么优化。 在 HBase 中,数据按指定 RowKey 进行排序,存储在区域中,并划分为固定大小。 此行为与 Azure Cosmos DB 中的分区不同。 因此,需要重新设计密钥,以根据工作负载的特征更好地分布数据。 请参阅分布部分以了解更多详细信息。
在 HBase 中,数据是按 RowKey 进行排序的,但是在 Azure Cosmos DB 中,数据是按键进行分区的。 Azure Cosmos DB 如何实现排序和归置?
在 Azure Cosmos DB 中,可以添加组合索引以按升序或降序对数据进行排序,从而提高相等性和范围查询的性能。 请参阅产品文档中的分布部分和组合索引。
使用 Hive 或 Spark 对 HBase 数据执行分析处理。 如何在 Azure Cosmos DB 中实现其现代化?
可以使用 Azure Cosmos DB 分析存储将操作数据自动同步到其他列存储。 列存储格式适用于以优化方式执行的大型分析查询,这可改进此类查询的延迟。 借助 Azure Synapse Link 可以直接从 Azure Synapse Analytics 链接到 Azure Cosmos DB 分析存储,从而构建无 ETL 的 HTAP 解决方案。 这样,你便可以对操作数据执行近乎实时的大型分析。 Synapse Analytics 支持 Azure Cosmos DB 分析存储中的 Apache Spark 和无服务器 SQL 池。 可以利用此功能迁移分析处理。 有关详细信息,请参阅分析存储。
用户如何对 Azure Cosmos DB 使用 HBase 中的时间戳查询?
Azure Cosmos DB 没有与 HBase 完全相同的时间戳版本控制功能。 但是 Azure Cosmos DB 提供了访问更改源的功能,你可以利用它进行版本控制。
将每个版本/更改存储为单独项。
读取更改源以合并/整合更改,然后使用“_ts”字段进行筛选以在下游触发相应操作。 此外,对于旧版本的数据,可以使用 TTL 使旧版本过期。
后续步骤
若要优化代码,请参阅 Azure Cosmos DB 性能提示一文。
若要探索 Java 异步 V3 SDK,请访问 SDK 参考 GitHub 存储库。