HBase BufferedMutator与PutList性能对比

6

最近我发现了HBase的BufferedMutator类,可以用于批量插入和删除数据。 之前我使用List将数据放入hTable.put(putList)来完成相同任务。 但是测试我的代码似乎没有显示出太大的差异,而我改为使用mutator.mutate(putList);进行操作。 使用BufferedMutator相比于PutList是否有明显的性能提升呢?

1个回答

13

简短回答

BufferedMutator 通常比仅使用 Table#put(List<Put>) 提供更好的吞吐量,但需要适当调整 hbase.client.write.bufferhbase.client.max.total.taskshbase.client.max.perserver.taskshbase.client.max.perregion.tasks,以获得良好性能。

解释

当您将一组 puts 传递给 HBase 客户端时,它会按目标区域进行分组,并通过目标区域服务器批处理这些组。每个批次发送一个单独的 rpc 请求。这减少了 rpc 开销,特别是在 Puts 很小的情况下,从而使每个请求的 rpc 开销显著。

Table 客户端立即将所有 Puts 发送到区域服务器并等待响应。这意味着可以发生的任何批处理都限于单个 API 调用中的 Puts 数量,并且 api 调用从调用者的角度是同步的。然而,BufferedMutator 在缓冲区中缓冲 Puts 并根据当前缓冲大小在后台线程中决定刷新缓冲的 Puts,这些线程由称为 AsyncProcess 的类包装。从调用者的角度来看,每个 API 调用仍然是同步的,但整个缓冲策略提供了更好的批处理。后台刷新模型还允许连续的请求流,这与更好的批处理相结合,意味着能够支持更多客户端线程。但是,由于这种缓冲策略,缓冲区越大,对调用者可见的每个操作的延迟就越差,但通过拥有更多的客户端线程可以维持更高的吞吐量。

一些控制 BufferedMutator 吞吐量的配置如下:

hbase.client.write.buffer: 缓冲区的大小 (字节) (越高的值提供更好的峰值吞吐量,但会消耗更多内存)

hbase.client.max.total.tasks: 在 AsyncProcess 开始阻塞请求之前集群中挂起的请求数量(数字越大越好,但可能会使客户端繁忙或造成服务器超负荷)

hbase.client.max.perserver.tasks:一个Region Server上未处理请求的数量达到该值之后,AsyncProcess开始阻塞请求。

hbase.client.max.perregion.tasks:每个Region上未处理请求的数量。

同样地,为了完整性,应当明确的是,如果瓶颈在服务器端而不是客户端,使用BufferedMutator比在客户端使用Table并不能带来太多性能提升。


我们可以看到,BufferedMutator 像是一个放置操作的缓冲区,它会将请求批处理直到“批处理条件”被满足(时间或大小限制),然后将其刷新到区域服务器。在操作上,BufferedMutator 和 PutList 应该表现得相同,不会有区别吗? - Parijat Purohit
2
是的,没错。实际上,HTable#put 内部使用 BufferedMutator#mutate 并在此之后立即调用 BufferedMutator#flush()。HTable#setAutoFlush API 可以用于禁用/启用 HTable 中的自动刷新行为。如果禁用,则 HTable 客户端将变成 BufferedMutator。但是,HTable#setAutoFlush API 已被弃用,建议您直接使用 BufferedMutator,以便获得更好的客户端写入吞吐量。 - Ashu Pachauri
@AshuPachauri,您能否建议我需要更改哪些配置(我正在使用默认配置)以避免在Hbase.Put操作期间出现InterruptedIOException的情况。https://stackoverflow.com/questions/52312089/how-to-avoid-interruptedioexception-in-hbase-put-operation - Roshan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接