在规划 HBase 群集的容量和执行初始配置时,需要考虑几个因素。首先要充分了解 HBase 如何在内部处理数据。
磁盘上的物理数据大小与数据的逻辑大小不同,并受以下因素影响:
HBase 开销增加
参见 keyvalue 和 keysize 。每个键值(单元格)至少 24 个字节可以更多。小键/值意味着更多的相对开销。
KeyValue 实例聚合为块,这些块已编制索引。索引也必须存储。 Blocksize 可以基于每个 ColumnFamily 进行配置。见 regions.arch 。
区域服务器 wal 的大小增加(通常固定且可忽略不计 - 小于 RS 内存大小的一半,每 RS)。
HDFS 复制增加 - 通常是 x3。
除了存储数据所需的磁盘空间之外,由于区域计数和大小的一些实际限制,一个 RS 可能无法提供任意大量的数据(参见 ops.capacity.regions )。
节点数也可以由读取和/或写入所需的吞吐量驱动。每个节点可以获得的吞吐量很大程度上取决于数据(尤其是密钥/值大小)和请求模式,以及节点和系统配置。如果负载可能是节点数量增加的主要驱动因素,则应该针对峰值负载进行规划。 PerformanceEvaluation 和 ycsb 工具可用于测试单个节点或测试集群。
对于写入,通常每个 RS 可以达到 5-15Mb / s,因为每个区域服务器只有一个活动的 WAL。读取没有很好的估计,因为它很大程度上取决于数据,请求和缓存命中率。 perf.casestudy 可能会有帮助。
由于 GC 的成本,RS 目前无法使用非常大的堆。每个服务器运行多个 RS-es 也没有好办法(除了每台机器运行多个 VM)。因此,建议专用于一个 RS 的~20-24Gb 或更少的存储器。大堆大小需要 GC 调整。参见 gcpause , trouble.log.gc 和其他地方(TODO:哪里?)
通常较少的区域使得运行集群更加平滑(您可以随后手动拆分大区域(如果需要)以在集群上传播数据或请求加载);每个 RS 20-200 个区域是合理的范围。无法直接配置区域数量(除非您完全 disable.splitting );调整区域大小以达到给定表大小的目标区域大小。
为多个表配置区域时,请注意,可以通过 HTableDescriptor 以及 shell 命令在每个表的基础上设置大多数区域设置。这些设置将覆盖hbase-site.xml
中的设置。如果您的表具有不同的工作负载/用例,那么这很有用。
另请注意,在这里讨论区域大小时, HDFS 复制因子不会(也不应该)被考虑在内,而其他因素 ops.capacity.nodes.datasize 应该是。 因此,如果你的数据被 HDFS 压缩和复制 3 种方式,“9 Gb 区域”意味着 9 Gb 的压缩数据。 HDFS 复制因子仅影响磁盘使用,对大多数 HBase 代码不可见。
您可以使用 HMaster UI 查看给定表的当前区域数。在“表”部分中,“在线区域”列中列出了每个表的联机区域数。此总计仅包括内存中状态,不包括禁用或脱机区域。
在生产场景中,如果您拥有大量数据,通常会关注每台服务器可以拥有的最大区域数。 太多地区就此问题进行了技术讨论。基本上,区域的最大数量主要由 memstore 内存使用量决定。每个地区都有自己的 memstore;它们长大到可配置的大小;通常在 128-256 MB 范围内,请参见 hbase.hregion.memstore.flush.size 。每个列族存在一个 memstore(因此,如果表中有一个 CF,则每个区域只有一个)。 RS 将总内存的一部分专用于其存储器(参见 hbase.regionserver.global.memstore.size )。如果超出此内存(memstore 使用率过高),则可能会导致不良后果,例如无响应的服务器或压缩风暴。每个 RS 的区域数量(假设一个表)的良好起点是:
((RS memory) * (total memstore fraction)) / ((memstore size)*(# column families))
这个公式是伪代码。以下是使用实际可调参数的两个公式,首先是 HBase 0.98+,第二个是 HBase 0.94.x.
HBase 0.98.x
((RS Xmx) * hbase.regionserver.global.memstore.size) / (hbase.hregion.memstore.flush.size * (# column families))
HBase 0.94.x
((RS Xmx) * hbase.regionserver.global.memstore.upperLimit) / (hbase.hregion.memstore.flush.size * (# column families))+
如果给定的 RegionServer 具有 16 GB 的 RAM,并且具有默认设置,则该公式可以达到 16384 * 0.4 / 128~51 个区域,每个 RS 是一个起点。公式可以扩展到多个表;如果它们都具有相同的配置,只需使用总系列数。
这个数字可以调整;上面的公式假设您所有的区域都以大致相同的速率填充。如果只有一部分区域将被主动写入,则可以将结果除以该分数以获得更大的区域计数。然后,即使写入所有区域,也不会均匀地填充所有区域存储器,并且最终出现抖动,即使它们是(由于并发刷新的数量有限)。因此,人们可以拥有比起点多 2-3 倍的区域;然而,增加的数字会增加风险。
对于写入繁重的工作负载,可以在配置中增加 memstore 分数,但代价是块缓存;这也将允许一个人拥有更多的地区。
HBase 通过跨多个服务器的区域来扩展。因此,如果您有 16 个数据的 2 个区域,则在 20 节点计算机上,您的数据将集中在几台计算机上 - 几乎整个群集都将处于空闲状态。这真的不够强调,因为一个常见的问题是将 200MB 数据加载到 HBase 中,然后想知道为什么你真棒的 10 节点集群没有做任何事情。
另一方面,如果您拥有大量数据,您可能还需要选择更多区域以避免区域过大。
对于生产场景中的大型表,最大区域大小主要受到压缩的限制 - 非常大的压缩,尤其是压缩。 major,会降低集群性能。目前,推荐的最大区域大小为 10-20Gb,最佳区域为 5-10Gb。对于较早的 0.90.x 代码库,regionsize 的上限约为 4Gb,默认值为 256Mb。
区域分成两部分的大小通常通过 hbase.hregion.max.filesize 配置;有关详细信息,请参阅 arch.region.splits 。
如果你不能很好地估计表的大小,那么在开始时,最好坚持使用默认的区域大小,对于热表可能会更小(或者手动拆分热区以将负载分散到集群上),或者与如果您的细胞大小往往较大(100k 及以上),则区域尺寸较大。
在 HBase 0.98 中,添加了实验条带压缩功能,允许更大的区域,特别是对于日志数据。见 ops.stripe 。
根据区域大小和每个区域服务器区域数量的上述数字,在乐观估计中,每个 RS 10 GB×100 个区域将为每个区域服务器提供高达 1TB 的服务,这与一些报告的多 PB 用例一致。但是,重要的是要考虑 RS 级别的数据与缓存大小比率。每个服务器有 1TB 的数据和 10 GB 的块缓存,只有 1%的数据会被缓存,这几乎不能覆盖所有的块索引。
首先,参见重要配置。请注意,某些配置(多于其他配置)取决于特定方案。特别注意:
hbase.regionserver.handler.count - 请求处理程序线程数,对高吞吐量工作负载至关重要。
config.wals - WAL 文件的阻塞数量取决于您的 memstore 配置,应相应地设置以防止在执行大量写入时可能阻塞。
然后,在设置群集和表时需要考虑一些因素。
根据读/写卷和延迟要求,最佳压缩设置可能不同。有关详细信息,请参见压缩。
但是,在为大数据量配置时,请记住压缩会影响写入吞吐量。因此,对于写入密集型工作负载,您可以选择较少频繁的压缩和每个区域的更多存储文件。压缩的最小文件数(hbase.hstore.compaction.min
)可以设置为更高的值; hbase.hstore.blockingStoreFiles 也应该增加,因为在这种情况下可能会累积更多文件。您也可以考虑手动管理压缩: managed.compactions
根据每个 RS 的区域的目标数量(参见 ops.capacity.regions.count )和 RS 的数量,可以在创建时预分割表。当表开始填满时,这将避免一些昂贵的拆分,并确保表已经分布在许多服务器上。
如果预计该表会增长到足以证明其合理性,则应创建每个 RS 至少一个区域。不建议立即分成完整目标区域数(例如 50 * RSes 数),但可以选择低中间值。对于多个表,建议保守预分裂(例如,每个 RS 最多预分割 1 个区域),特别是如果您不知道每个表将增长多少。如果分割太多,最终可能会出现太多区域,某些表区域的区域太多。
对于预分割方法,请参见手动区域分割决策和 precreate.regions 。