

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# HBase on Amazon S3（Amazon S3 存储模式）
<a name="emr-hbase-s3"></a>

在 Amazon EMR 版本 5.2.0 及更高版本上运行 HBase 时，您可以启用 HBase on Amazon S3，这将提供以下优势：
+ HBase 根目录存储在 Amazon S3 中，包括 HBase 存储文件和表元数据。此数据在集群外部持续存在且可跨 Amazon EC2 可用区访问，您无需使用快照或其它方法进行恢复。
+ 对于 Amazon S3 中的存储文件，您可以针对计算要求而非数据要求调整 Amazon EMR 集群的大小（在 HDFS 上为 3 倍复制）。
+ 使用 Amazon EMR 版本 5.7.0 及更高版本，您可设置只读副本集群，这允许您将数据的只读副本保留在 Amazon S3 中。如果主集群变得不可用，您可以访问只读副本集群中的数据以同时执行读取操作。
+ 在 Amazon EMR 版本 6.2.0 到 7.3.0 中，持久性 HFile 跟踪使用名为 `hbase:storefile` 的 HBase 系统表直接跟踪用于读取操作的 HFile 路径。默认情况下，此功能处于启用状态，不需要执行手动迁移。在 7.3.0 以上的版本中，HFile 路径使用文件跟踪器进行跟踪，将 HFile 路径直接存储在存储目录中的元文件中。

**注意**  
使用 Amazon EMR 7.4.0 之前版本并正在迁移到 EMR-7.4.0 及更高版本的用户，请参阅从以前的 HBase 版本[迁移，](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hbase-migrate.html)并按照可用的升级文档进行操作以确保平稳过渡。

下图显示与 HBase on Amazon S3 相关的 HBase 组件。

![HBase on Amazon S3 架构。](https://docs.aws.amazon.com/zh_cn/emr/latest/ReleaseGuide/images/hbase_s3.png)


## 启用 HBase on Amazon S3
<a name="emr-hbase-s3-enable"></a>

您可以使用亚马逊 EMR 控制台、或亚马逊 EMR API 在 Amazon S3 上 AWS CLI启用 HBase。该配置是集群创建期间的一个选项。使用控制台时，您可以通过 **Advanced options (高级选项)** 选择相应设置。在使用 AWS CLI时，使用 `--configurations ` 选项提供 JSON 配置对象。配置对象的属性指定了 Amazon S3 中的存储模式和根目录位置。您指定的 Amazon S3 位置应位于 Amazon EMR 集群所在的区域内。一次仅一个活动集群可使用 Amazon S3 中的相同 HBase 根目录。有关控制台步骤和使用创建集群的详细示例 AWS CLI，请参阅。[创建带 HBase 的集群](emr-hbase-create.md)以下 JSON 代码段中显示了示例配置对象。

```
{
  "Classification": "hbase-site",
  "Properties": {
    "hbase.rootdir": "{{s3://amzn-s3-demo-bucket/my-hbase-rootdir}}"}
},
{
  "Classification": "hbase",
  "Properties": {
  "hbase.emr.storageMode":"{{s3}}"
  }
}
```

**注意**  
如果您使用 Amazon S3 存储桶作为 HBase 的 `rootdir`，您必须在 Amazon S3 URI 的末尾添加斜杠。例如，为了避免出现问题，您必须使用 `"hbase.rootdir: s3://amzn-s3-demo-bucket/"`，而不是 `"hbase.rootdir: s3://amzn-s3-demo-bucket"`。

## 使用只读副本集群
<a name="emr-hbase-s3-read-replica"></a>

在使用 HBase on Amazon S3 设置主集群后，您可创建和配置只读副本集群，此集群提供对与主集群相同的数据的只读访问权限。当您需要同步访问权限以查询数据或在主集群变得不可用的情况下进行连续访问时，这会很有用。只读副本功能适用于 Amazon EMR 5.7.0 版和更高版本。

主集群和只读副本集群的设置方式相同，但有一个重要差异。两者都指向相同的 `hbase.rootdir` 位置。不过，只读副本集群的 `hbase` 分类包括 `"hbase.emr.readreplica.enabled":"true"` 属性。

只读副本集群设计用于只读操作，不应对其执行任何手动压缩或写入操作。对于 7.4.0 之前的 Amazon EMR 版本，当启用了只读副本功能时，建议在只读副本集群上禁用压缩。这种预防措施是必要的，因为在主群集上启用持久 HFile 跟踪功能后，只读副本群集可能会压缩系统表，从而可能导致主群集出现错误 FileNotFoundException 。在只读副本集群上禁用压缩可防止主集群和只读副本集群之间的数据不一致。

例如，对于前面主题中所示的主集群的 JSON 分类，EMR 版本低于 7.4.0 的只读副本集群的配置如下：

```
{
  "Classification": "hbase-site",
  "Properties": {
    "hbase.rootdir": "{{s3://amzn-s3-demo-bucket/my-hbase-rootdir}}",
    "hbase.regionserver.compaction.enabled": "false"			
  }
},
{
  "Classification": "hbase",
  "Properties": {
  "hbase.emr.storageMode":"{{s3}}",
  "hbase.emr.readreplica.enabled":"true"
  }
}
```

对于 7.3.0 之后的 Amazon EMR 版本，我们现在使用[存储文件跟踪](#emr-hbase-store-file-tracking)功能，因此无需禁用压缩。

**注意**  
使用 Amazon EMR 版本 7.12.0 或更高版本时，请使用以下示例配置：  

```
{
  "Classification": "hbase-site",
  "Properties": {
    "hbase.rootdir": "{{s3://{S3_LOCATION}}}"
  }
},
{
  "Classification": "hbase",
  "Properties": {
    "hbase.emr.storageMode": "s3",
    "hbase.emr.readreplica.enabled.v2": "true"
  }
}
```

### 添加数据时同步只读副本
<a name="w2aac33c37c15c16"></a>

由于只读副本使用主集群写入 Amazon S3 的 HBase StoreFiles 和元数据，因此只读副本仅与 Amazon S3 数据存储一样新。在写入数据时，以下指导信息可帮助您最大程度地缩短主集群和只读副本之间的滞后时间。
+ 如果可能，请在主集群上批量加载数据。有关更多信息，请参阅 Apache HBase 文档中的[批量加载](http://hbase.apache.org/0.94/book/arch.bulk.load.html)。
+ 将存储文件写入 Amazon S3 的刷新操作应在添加数据后尽快进行。手动刷新或优化刷新设置以最大限度地减少滞后时间。
+ 如果压缩可能会自动运行，请运行手动压缩以避免触发压缩时出现不一致。
+ 在只读副本集群上，当任何元数据发生变化时（例如，当 HBase 区域拆分或压缩时，或者添加或删除表时），请运行 `refresh_meta` 命令。
+ 在只读副本集群上，在表中添加或更改记录后，运行 `refresh_hfiles` 命令。

![将数据与 HBase 只读副本同步](https://docs.aws.amazon.com/zh_cn/emr/latest/ReleaseGuide/images/hbase-read-replica.png)


## 持久性 HFile 跟踪
<a name="emr-hbase-s3-hfile-tracking"></a>

持久性 HFile 跟踪使用名为 `hbase:storefile` 的 HBase 系统表直接跟踪用于读取操作的 HFile 路径。将其它数据添加到 HBase 时，新的 HFile 路径将添加到表中。这将删除重命名操作作为关键写入路径 HBase 操作中的提交机制，并通过从 `hbase:storefile` 系统表（而不是文件系统目录列表）读取来缩短打开 HBase 区域时的恢复时间。此功能在 Amazon EMR 版本 6.2.0 至 7.3.0 中默认启用，无需任何手动迁移步骤。

**注意**  
使用 HBase 存储文件系统表的持久性 HFile 跟踪不支持 HBase 区域复制功能。有关 HBase 区域复制的更多信息，请参阅[Timeline-consistent 高可用读取次数](http://hbase.apache.org/book.html#arch.timelineconsistent.reads)。

**禁用持久性 HFile 跟踪**

从 Amazon EMR 发行版 6.2.0 开始，默认启用持久性 HFile 跟踪。要禁用持久性 HFile 跟踪，请在启动集群时指定以下配置覆盖：

```
{
  "Classification": "hbase-site",
  "Properties": {
    "hbase.storefile.tracking.persist.enabled":"false",
    "hbase.hstore.engine.class":"org.apache.hadoop.hbase.regionserver.DefaultStoreEngine"
  }
}
```

**注意**  
重新配置 Amazon EMR 集群时，必须更新所有实例组。

**手动同步存储文件表**

当创建新的 HFile 实例时，storefile 表会保持最新状态。但是，如果 storefile 表由于任意原因与数据文件不同步，则可以使用以下命令手动同步数据：

**同步线上区域中的存储文件表:**

`hbase org.apache.hadoop.hbase.client.example.RefreshHFilesClient <table>`

**同步离线区域中的存储文件表:**
+ 删除存储文件表 znode。

  ```
  echo "ls /hbase/storefile/loaded" | sudo -u hbase hbase zkcli
  [<tableName>, hbase:namespace]
  # The TableName exists in the list
  echo "delete /hbase/storefile/loaded/<tableName>" | sudo -u hbase hbase zkcli
  # Delete the Table ZNode
  echo "ls /hbase/storefile/loaded" | sudo -u hbase hbase zkcli
  [hbase:namespace]
  ```
+ 分配区域（在“hbase shell”中运行）。

  ```
  hbase cli> assign '<region name>'
  ```
+ 如果分配失败。

  ```
  hbase cli> disable '<table name>'
  hbase cli> enable '<table name>'
  ```

**扩缩存储文件表**

默认情况下，存储文件表可拆分为四个区域。如果存储文件表的写入负载仍然较重，之后可以手动拆分该表。

要拆分特定的热点区域，请使用以下命令（在“hbase shell”中运行）。

```
hbase cli> split '<region name>'
```

要拆分该表，请使用以下命令（在“hbase shell”中运行）。

```
hbase cli> split 'hbase:storefile'
```

## 存储文件跟踪
<a name="emr-hbase-store-file-tracking"></a>

默认情况下，我们使用**FileBasedStoreFileTracker**实现。此实现直接在存储目录中创建新文件，无需进行重命名操作。它在内存中保存已提交的 hfile 实例列表，以每个存储目录中的元文件为后盾。每当提交新的 hfile 时，给定存储中的*跟踪文件*列表都会更新，并使用列表内容写入新的元文件，同时丢弃包含过时列表的先前元文件。有关存储文件跟踪的更多信息，请参阅《Apache HBase 参考指南》**中的[存储文件跟踪](https://hbase.apache.org/book.html#storefiletracking)。

从亚马逊 EMR 版本 7.4.0 开始， FileBasedStoreFile 跟踪器实现默认处于启用状态：

```
{
  "Classification": "hbase-site",
  "Properties": {
    hbase.store.file-tracker.impl: "org.apache.hadoop.hbase.regionserver.storefiletracker.FileBasedStoreFileTracker"
   }
}
```

要禁用该 FileBasedStoreFileTracker 实现，请在启动集群时指定以下配置替代：

```
{
  "Classification": "hbase-site",
  "Properties": {
    hbase.store.file-tracker.impl: "org.apache.hadoop.hbase.regionserver.storefiletracker.DefaultStoreFileTracker"
   }
}
```

**注意**  
重新配置 Amazon EMR 集群时，必须更新所有实例组。

## 为 HBase 配置 S3A 读取策略
<a name="emr-hbase-s3a-read-policy"></a>

从 Amazon EMR 版本 7.10 开始，Amazon S3 上的 HBase 使用 S3A 文件系统客户端。默认情况下，`fs.s3a.experimental.input.fadvise` 属性设置为 `normal`。在此模式下，S3A 根据观察到的输入流访问模式自动在顺序读取策略和随机读取策略之间进行调整。

Amazon S3 上的 HBase 依赖顺序读取来进行压缩、扫描和批量加载。在某些情况下，普通模式可能会切换到随机读取策略。即使后续读取保持顺序，也可能发生这种情况。发生这种情况时，压缩、扫描和批量加载的读取性能可能会显著降低。

**受影响的版本**  
此问题适用于带有 HBase 的 Amazon EMR 版本 7.10、7.11、7.12 和 7.13。

如果您遇到以下任何症状，请将 S3A 读取策略设置为：`sequential`
+ 缓慢压实
+ HFile 的数量越来越多
+ 刷新操作受阻导致`RegionTooBusyException`错误
+ 与早期的 Amazon EMR 版本相比，扫描和批量加载操作较慢

创建集群时指定以下配置：

```
[
  {
    "Classification": "hbase-site",
    "Properties": {
      "fs.s3a.experimental.input.fadvise": "sequential"
    }
  }
]
```

将此属性应用`hbase-site.xml`于所有节点。此更改将在您重新启动 HBase 主服务器和区域服务器进程后生效。

**Cluster-wide 推荐配置**  
我们建议您将受影响版本上的所有 HBase 工作负载设置`fs.s3a.experimental.input.fadvise`为`sequential`全集群。如果仅将该设置应用于单个命令，则压缩和扫描的性能会持续下降。

### 为批量加载操作配置读取策略
<a name="emr-hbase-s3a-read-policy-bulkload"></a>

如果您只需要提高批量加载性能而不更改集群范围的配置，则可以将该属性直接传递给该命令。`completebulkload`

要对单个批量加载操作使用顺序读取策略，请执行以下操作：

```
sudo -u hbase hbase completebulkload \
  -Dfs.s3a.experimental.input.fadvise=sequential \
  s3://amzn-s3-demo-bucket/path/to/hfiles table_name
```

或者，您可以使用 EMRFS 进行批量加载操作：

```
sudo -u hbase hbase completebulkload \
  -Dfs.s3.impl=com.amazon.ws.emr.hadoop.fs.EmrFileSystem \
  s3://amzn-s3-demo-bucket/path/to/hfiles table_name
```

## 运营注意事项
<a name="emr-hbase-s3-performance"></a>

HBase 区域服务器用于 BlockCache 将读取的数据存储在内存中 BucketCache ，并将读取的数据存储在本地磁盘上。此外，区域服务器用于 MemStore 将写入的数据存储在内存中，并使用预写日志在数据写入 Amazon S3 中的 HBase 之前在 HDFS 中存储写入的数据。 StoreFiles 集群的读取性能与可从内存中或磁盘缓存中读取记录的频率有关。缓存丢失会导致从 Amazon S3 中读取记录，与从 HDFS 读取相比，Amazon S3 的延迟要长得多，标准差也更高。 StoreFile 此外，Amazon S3 的最大请求速率低于可从本地缓存中检索内容的速率，因此对于需要进行大量读取操作的工作负载来说，缓存数据可能非常重要。有关 Amazon S3 性能的更多信息，请参阅《Amazon Simple Storage Service 用户指南》**中的[性能优化](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PerformanceOptimization.html)。

为了提高性能，建议您在 EC2 实例存储中尽可能多地缓存数据集。由于 BucketCache 使用区域服务器的 EC2 实例存储，因此您可以选择具有足够实例存储的 EC2 实例类型，并添加 Amazon EBS 存储以适应所需的缓存大小。您还可以使用该`hbase.bucketcache.size`属性增加附加的实例存储和 EBS 卷BucketCache 的大小。默认设置为 8192MB。

对于写入而言， MemStore 刷新频率以及次要和主要压缩期间的 StoreFiles 刷新次数可以显著增加区域服务器响应时间。为了获得最佳性能，可以考虑增加 fl MemStore ush 和 hRegion 区块乘数的大小，这会增加两次主要压缩之间的间隔时间，但如果使用只读副本，也会增加一致性延迟。在某些情况下，使用较大的文件块大小（但小于 5GB）触发 EMRFS 中的 Amazon S3 分段上载功能也许能够获得更佳性能。Amazon EMR 的数据块大小默认为 128MB。有关更多信息，请参阅[HDFS 配置](emr-hdfs-config.md)。在通过刷新和压缩来衡量性能时，我们很少看到有客户的数据块大小超过 1GB。此外，当 StoreFiles 需要压缩的数量较少时，HBase 压缩和区域服务器会发挥最佳性能。

由于需要对大量目录进行重命名，因此从 Amazon S3 中删除表需要花费大量时间。请考虑禁用表而不是删除表。

有一个 HBase 清理器，用于清理旧的 WAL 文件并存储文件。对于 Amazon EMR 版本 5.17.0 及更高版本，全局启用清理器，且以下配置属性可用于控制清理器行为。


| 配置属性 | 默认 值 | 说明 | 
| --- | --- | --- | 
| `hbase.regionserver.hfilecleaner.large.thread.count` | 1 | 为清理过期的大型 HFile 而分配的线程数。 | 
| `hbase.regionserver.hfilecleaner.small.thread.count` | 1 | 为清理过期的小型 HFile 而分配的线程数。 | 
| `hbase.cleaner.scan.dir.concurrent.size` | 设置为所有可用内核的四分之一。 | 用于扫描 oldWAL 目录的线程数。 | 
| `hbase.oldwals.cleaner.thread.size` | 2 | 用于清理 oldWAL 目录下的 WAL 的线程数。 | 

对于 Amazon EMR 5.17.0 及更早版本，在运行大量工作负载时，清理器操作会影响查询性能；因此，我们建议您只在非高峰时间启用清理器。清理器拥有以下 HBase shell 命令：
+ `cleaner_chore_enabled` 查询是否启用了清理器。
+ `cleaner_chore_run` 手动运行清理器来删除文件。
+ `cleaner_chore_switch` 启用或禁用清理器并返回清理器的先前状态。例如，`cleaner_chore_switch true` 启用清理器。

### 用于 HBase on Amazon S3 性能优化的属性
<a name="emr-hbase-s3-properties"></a>

使用 HBase on Amazon S3 时，可调整以下参数来优化工作负载的性能。


| 配置属性 | 默认 值 | 说明 | 
| --- | --- | --- | 
| `hbase.bucketcache.size` | 8192 | 在区域服务器 Amazon EC2 实例 BucketCache 存储和 EBS 卷上预留的磁盘空间量，以 MB 为单位。此设置适用于所有区域服务器实例。较大的 BucketCache 尺寸通常对应于性能的提高 | 
| `hbase.hregion.memstore.flush.size` | 134217728 | 触发对 Amazon S3 的 memstore 刷新的数据限制（以字节为单位）。 | 
| `hbase.hregion.memstore.block.multiplier` | 4 | 确定阻止更新的 MemStore 上限的乘数。如果 MemStore 超出值`hbase.hregion.memstore.flush.size`乘以此值，则会阻止更新。 MemStore 刷新和压缩可能会解锁更新。 | 
| `hbase.hstore.blockingStoreFiles` | 10 | 在阻止更新之前 StoreFiles ，商店中可以存在的最大数量。 | 
| `hbase.hregion.max.filesize` | 10737418240 | 区域被拆分之前的大小上限。 | 

### 关闭并恢复集群而不丢失数据
<a name="emr-hbase-s3-shutdown"></a>

要在不丢失尚未写入 Amazon S3 的数据的情况下关闭 Amazon EMR 集群，您应该将 MemStore 缓存刷新到 Amazon S3 以写入新的存储文件。首先，您需要禁用所有表格。在向集群添加步骤时，可使用以下步骤配置。有关更多信息，请参阅《*Amazon EMR 管理指南》*中的[使用 AWS CLI 和控制台执行步骤](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-work-with-steps.html)。

```
Name="Disable all tables",Jar="command-runner.jar",Args=["/bin/bash","/usr/lib/hbase/bin/disable_all_tables.sh"]	
```

或者，您可以直接运行以下 bash 命令。

```
bash /usr/lib/hbase/bin/disable_all_tables.sh
```

禁用所有表格后，使用 HBase shell 和以下命令刷新`hbase:meta`表。

```
flush 'hbase:meta'
```

然后，您可以运行 Amazon EMR 集群上提供的 shell 脚本来刷新MemStore 缓存。您可以将它作为步骤添加，也可以使用集群中 AWS CLI直接运行它。该脚本禁用所有 HBase 表，这会导致每个区域 MemStore中的服务器刷新到 Amazon S3。如果此脚本成功完成，数据将保留在 Amazon S3 中，并且可以终止集群。

要使用相同 HBase 数据重新启动集群，请在 AWS 管理控制台 或使用`hbase.rootdir`配置属性中指定与先前集群相同的 Amazon S3 位置。