HBase最佳实践-CMS GC调优

HBase发展到当下,对其进行的各种优化从未停止,而GC优化更是其中的重中之重。从0.94版本提出MemStoreLAB策略、Memstore Chuck Pool策略对写缓存Memstore进行优化开始,到0.96版本提出BucketCache以及堆外内存方案对读缓存BlockCache进行优化,再到后续2.0版本宣称会引入更多堆外内存,可见HBase会将堆外内存的使用作为优化GC的一个战略方向。然而无论引入多少堆外内存,都无法避免读写全路径使用JVM内存,就拿BucketCache中offheap模式来讲,即使HBase数据块是缓存在堆外内存的,但是在读取的时候还是会首先将堆外内存中的block加载到JVM内存中,再返回给用户。可见,无论使用多少堆外内存,对JVM内存的使用终究是绕不过去,既然绕不过去,就还是需要落脚于GC本身,对GC本身进行优化。本文就将会介绍HBase应用场景下CM...

继续阅读

HBase Compaction的前生今世-改造之路

上一篇文章主要基于工作流程对compaction进行了介绍,同时说明了compaction的核心作用是通过合并大量小文件为一个大文件来减少hfile的总数量,进而保证读延迟的稳定。合并文件首先是读出所有小文件的KVs,再写入同一个大文件,这个过程会带来严重的IO压力和带宽压力,对整个系统的读请求和写请求带来不同程度的影响。

因此HBase对于compaction的设计总是会追求一个平衡点,一方面需要保证compaction的基本效果,另一方面又不会带来严重的IO压力。然而,并没有一种设计策略能够适用于所有应用场景或所有数据集。在意识到这样的问题之后,HBase就希望能够提供一种机制可以在不同业务场景下针对不同设计策略进行测试,另一方面也可以让用户针对自己的业务场景选择合适的compaction策略。因此,在0.96版本中HBase对架构进行了一定的调整,一方面提供了Compaction插件接...

继续阅读

HBase Compaction的前生今世-身世之旅

了解HBase的童鞋都知道,HBase是一种Log-Structured Merge Tree架构模式,用户数据写入先写WAL,再写缓存,满足一定条件后缓存数据会执行flush操作真正落盘,形成一个数据文件HFile。随着数据写入不断增多,flush次数也会不断增多,进而HFile数据文件就会越来越多。然而,太多数据文件会导致数据查询IO次数增多,因此HBase尝试着不断对这些文件进行合并,这个合并过程称为Compaction。

Compaction会从一个region的一个store中选择一些hfile文件进行合并。合并说来原理很简单,先从这些待合并的数据文件中读出KeyValues,再按照由小到大排列后写入一个新的文件中。之后,这个新生成的文件就会取代之前待合并的所有文件对外提供服务。HBase根据合并规模将Compaction分为了两类:MinorCompaction和MajorCom...

继续阅读

HBase最佳实践-内存规划

线上HBase集群应该如何进行参数配置?这其实是很多HBase初学者在实践环节都可能会遇到的问题,有些人会选择默认配置,有些人会选择其他公司的推荐配置;诚然,这样的参数配置在大多数情况下都能正常工作,但性能却未必最佳、资源未必都能被合理利用。本文结合笔者的实践经验,针对不同应用场景,对多种工作模式下的参数进行详细说明,并结合相关示例对集群规划中最核心模块-内存规划进行介绍。一方面希望读者能够了解HBase内存相关知识细节,另一方面能够将这些知识应用于实践、不断对集群进行优化。

HBase中内存规划直接涉及读缓存BlockCache、写缓存MemStore,影响系统内存利用率、IO利用率等资源以及读写性能等,重要性不言而喻。主要配置也是针对BlockCache和MemStore进行,然而针对不同业务类型(简单说来主要包括读多写少型和写多读少型),内存的相关配置却完全不同。再者,对于读缓存Blo...

继续阅读

HBase最佳实践-客户端超时机制

上篇博文结合一起线上问题介绍了HBase客户端基于退避算法的重试机制,并分析得出在某些场景下如果重试策略设置不当会导致长时间的业务阻塞。除了重试机制外,业务童鞋最关心的就是超时机制了。客户端超时设置对整个系统的稳定性以及敏感性至关重要,一旦没有超时设置或超时时间设置过长,服务器端的长时间卡顿必然会引起客户端阻塞等待,进而影响上层应用。好在HBase提供了多个客户端参数设置超时,主要包括hbase.rpc.timeout /hbase.client.operation.timeout /hbase.client.scanner.timeout.period。然而这些参数官方并没有给出具体的介绍,导致开发人员并不真正理解这些参数的含义。接下来本文分别对这三个参数进行介绍,应用童鞋可以根据自己的实际情况对这三个参数进行设置。

hbase.rpc.timeou

从字面意思就可知道,该参数表示一次RP...

继续阅读

HBase最佳实践 – 客户端重试机制

在运维HBase的这段时间里,发现业务用户一方面比较关注HBase本身服务的读写性能:吞吐量以及读写延迟,另一方面也会比较关注HBase客户端使用上的问题,主要集中在两个方面:是否提供了重试机制来保证系统操作的容错性?是否有必要的超时机制保证系统能够fastfail,保证系统的低延迟特性?

这个系列我们集中介绍HBase客户端使用上的这两大问题,本文通过分析之前一个真实的案例来介绍HBase客户端提供的重试机制,并通过配置合理的参数使得客户端在保证一定容错性的同时还能够保证系统的低延迟特性。

案发现场

最近某业务在使用HBase客户端读取数据时出现了大量线程block的情况,业务方保留了当时的线程堆栈信息,如下图所示

a

看到这样的问题,首先从日志和监控排查了业务表和region server,确认了在很长时间内确实没有请求进来,除此之外并没有其他有用的信息,同时也没有接到该集群上其他用户的异常反馈...

继续阅读

HBase GC的前生今世 – 演进篇

最原始的HBase CMS GC相当严重,经常会因为碎片过多导致Promotion Failure,严重影响业务的读写请求。幸运的是,HBase并没有止步不前,很多优化方案相继被提出并贡献给社区,本文要介绍的就是几个比较重要的核心优化,分别是针对Memstore所作的两个优化:Thread-Local Allocation Buffer和MemStore Chunk Pool 以及针对BlockCache所作的优化:BucketCache方案。在详细介绍这几个优化之前有必要简单介绍一下HBase GC优化的目标,很直观的,第一是要尽量避免长时间的Full GC,避免影响用户的读写请求;第二是尽量减少GC时间,提高读写性能;接着分别来看HBase针对GC所做的各种优化

MemStore GC优化一 - Thread-Local Allocation Buffe

HBase数据写入操作实际上并...

继续阅读

HBase GC的前生今世 – 身世篇

在之前的HBase BlockCache系列文章中已经简单提到:使用LRUBlockCache缓存机制会因为CMS GC策略导致内存碎片过多,从而可能引发臭名昭著的Full GC,触发可怕的'stop-the-world'暂停,严重影响上层业务;而Bucket Cache缓存机制因为在初始化的时候就申请了一片固定大小的内存作为缓存,缓存淘汰不再由 JVM管理,数据Block的缓存操作只是对这篇空间的访问和覆盖,因而大大减少了内存碎片的出现,降低了Full GC发生的频率。那CMS GC策略如何导致内存碎片过多?内存碎片过多如何触发Full GC?HBase在演进的道路上又如何不断优化CMS GC?接下来这个系列《HBase GC的前生今生》将会为你一一揭开谜底,这个系列一共两篇文章,本篇文章-’身世篇’将会带你全面了解HBase的GC机制,后面一篇-’演进篇’将会给你道出HBase在发展的...

继续阅读

HBase BlockCache系列 - 性能对比测试报告

HBase BlockCache系列文章到了终结篇,几个主角的是是非非也该有个了断了,在SlabCache被早早地淘汰之后,站在华山之巅的也就仅剩LRU君(LRUBlockCache)和CBC君(CombinedBlockCache)。谁赢谁输,我说了不算,你说了也不算,那就来让数据说话。这篇文章主要对比LRU君和CBC君(offheap模式)分别在四种场景下几种指标(GC、Throughput、Latency、CPU、IO等)的表现情况。四种场景分别是缓存全部命中、少大部分缓存命中、少量缓存命中、缓存基本未命中。

需要注意的是,本文的所有数据都来自社区文档,在这里分享也只是给大家一个参考,更加详细的测试数据可以阅读文章《Comparing BlockCache DeploysHBASE-1132附件报告。

说明:本文所有图都以时间为横坐标,纵坐标为对应指标。每张图都会分别显示LRU君和...

继续阅读

HBase BlockCache系列 - 探求BlockCache实现机制

HBase BlockCache系列第一篇文章《走进BlockCache》从全局视角对HBase中缓存、Memstore等作了简要概述,并重点介绍了几种BlockCache方案及其演进过程,对此还不了解的可以点这里。本文在上文的基础上深入BlockCache内部,对各种BlockCache方案具体工作原理进行详细分析。Note:因为SlabCache方案在0.98版本已经不被建议使用,因此本文不针对该方案进行讲解;至于LRU方案和Bucket方案,因为后者更加复杂,本文也会花更多篇幅详细介绍该方案的实现细节。

LRUBlockCach

LRUBlockCache是HBase目前默认的BlockCache机制,实现机制比较简单。它使用一个ConcurrentHashMap管理BlockKey到Block的映射关系,缓存Block只需要将BlockKey和对应的Block放入该HashMap中,查询缓存就根据BlockKey从HashMap中获取即可。同时该方案采用严格的LRU淘汰算法,当Block Cache总量达到一定阈值之后就会启动淘汰机制,最近最少使用的Block会被置换出来。在具体的实现细节方面,需要关注三点

1. 缓存分层策略

HBase在LRU缓存基础上,采用了缓存分层设计,将整个...

继续阅读