网易视频云:HBase GC的前生今世 演进篇
网易视频云是网易倾力龅歧仲半打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,为客户提供稳定流畅、低时延、高并发的视频直播、录制、存储、转码及点播等音视频的PaaS服务。在线教育、远程医疗、娱乐秀场、在线金融等各行业及企业用户只需经过简单的开发即可打造在线音视频平台。现在,网易视频云与大家分享一下HBase GC的前生今世–演进篇。
最原始的HBase CMS GC相当严重,经常会因为碎片过多导致Promotion Failure,严重影响业务的读写请求。幸运的是,HBase并没有止步不前,很多优化方案相继被提出并贡献给社区,本文要介绍的就是几个比较重要的核心优化,分别是针对Memstore所作的两个优化:Thread-Local Allocation Buffer和MemStore Chunk Pool 以及针对BlockCache所作的优化:BuckctCache方案。在详细介绍这几个优化之前有必要简单介绍一下HBase GC优化的目标,很直观的,第一是要尽量避免长时间的Full GC,避免影响用户的读写请求;第二是尽量减少GC时间,提高读写性能;接着分别来看HBase针对GC所做的各种优化:
MemStore GC优化一-Thread-Local Allocation Buffer
HBase数据写入操作实际上并没有直接将数据写入磁盘,而是先写入内存并顺序写入HLog,之后等待满足某个特定条件后统一将内存中的数据刷新到磁盘。一个RegionServer通常由多个Region组成,每张Region通常包含一张表的多个列族,而每个列族对应一块内存区域,这块内存被称为MemStore,很显然,一个RegionServer会由多个Region构成,一个Region会由多个MemStore构成。
最原始的HBase版本存在很严重的内存碎片,经常会导致长时间的Full GC,其中最核心的问题就出在MemStore这里。因为一个RegionServer由多个Region构成,不同Region的数据写入到对应Memstore,在JVM看来其实是混合在一起写入Heap的,此时假如Region1上对应的所有MemStore执行落盘操作,就会出现下图所示场景:
很显然,经过优化后YGC时间降低了40+%左右,FGC的次数以及时间更是大幅下降。
对于需要深入了解HBase针对BlockCache所做的GC优化的朋友,强烈建议首先阅读之前的3篇BlockCache 系列博文:part1 , part2 和part3。文中重点介绍了BlockCache的两种实现方案:LRUBlockCache和BucketCache。
BlockCache优化-BuckctCache方案
其中LRUBlockCache是目前HBase的默认方案,这种方案会将内存区分为3个部分:single-access区、mutil-access区以及in-memory区,一个Block块从HDFS中加载出来之后首先放入signle区,后续如果有多次请求访问到这块数据的话,就会将这块数据移到mutil-access区。随着Block数据从single-access区晋升到mutil-access区,基本就伴随着对应的内存对象从young区到old区,晋升到old区的Block被淘汰后会变为内存垃圾,最终由CMS回收掉,CMS回收之后必然会产生大量的内存碎片,碎片空间一直累计就会产生臭名昭著的Full GC。
为了减少频繁CMS GC 产生的碎片问题,社区采纳了阿里开发者的新方案:BucketCache。这种方案还是采用“将小碎片整理为大碎片”的思路,由程序在初始化的时候就申请了很多大小为2M的Bucket,数据Block的Get/Cache动作只是对这片空间的访问/覆写,CMS碎片会自然大大降低。BucketCache有三种工作模式:heap、offheap以及file,其中heap模式表示将数据存储在JVM堆内存,offheap模式表示将数据Block存储到操作系统内存,file模式表示将数据Block存储到类似于SSD的外部高速缓存上;很显然,offheap模式和file模式根本没有将数据Block存在JVM堆内存,所以几乎不会出现Full GC,而heap模式即使数据存储在JVM堆内存,也会因为内存由程序独立管理大大降低内存碎片。
针对BlockCache的两种实现方案,分别简单地对内存碎片产生情况和GC情况进行了统计,结果如下:
从结果可以看出,BucketCache大大减少了碎片的产生,而且YGC和FGC时间也极大地得到了改善。需要注意的是,此结论是在部分缓存未命中的情况下得出的,缓存全部命中的场景结果会有所不同。