V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shipinyun2016
V2EX  ›  推广

网易视频云: HBase GC 的前生今世 – 演进篇

  •  
  •   shipinyun2016 · 2016-07-20 11:30:45 +08:00 · 1576 次点击
    这是一个创建于 3047 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,为客户提供稳定流畅、低时延、高并发的视频直播、录制、存储、转码及点播等音视频的 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 执行落盘操作,就会出现下图所示场景:

    1

    为了优化这种内存碎片可能导致的 Full GC , HBase 借鉴了 Arena Allocation 内存管理方式,它通过顺序化分配内存、内存数据分块等特性使得内存碎片更加粗粒度,有效改善 Full GC 情况;

    具体实现原理如下:

    1. 每个 MemStore 会实例化出来一个 MemStoreLAB

    2. MemStoreLAB 会申请一个 2M 大小的 Chunk 数组和一个 Chunk 偏移量,初始值为 0

    3. 当一个 KeyValue 值插入 MemStore 后, MemStoreLAB 会首先通过 KeyValue.getBuffer()取得 data 数组,并将 data 数组复制到 Chunk 数组中,之后再将 Chunk 偏移量往前移动 data.length

    4. 如果当前 Chunk 满了之后,再调用 new byte[ 2 * 1024 * 1024]申请一个新的 Chunk

    很显然,通过申请 2M 大小的 Chunk 可以使得内存碎片更加粗粒度,官方在优化前后通过设置 -xx:PrintFLSStatistics = 1 统计了老生代的 Max Chunk Size 分别随时间的变化曲线,如下图所示:

    2 3

    由上图可以看出,未优化前碎片会大量出现导致频繁的 Full GC ,优化后虽然依然会产生大量碎片,但是最大碎片大小一直会维持在 1e + 08 左右,极大地降低了 Full GC 频率。

    MemStore GC 优化二 – MemStore Chunk Pool

    然而一旦一个 Chunk 写满之后,系统就会重新申请一个新的 Chunk ,这些 Chunk 大部分都会经过多次 YGC 之后晋升到老生代,如果某个 Chunk 再没有被引用就会被 JVM 垃圾回收。很显然,不断申请新的 Chunk 会导致 YGC 频率不断增多, YGC 频率增加必然会导致晋升到老生代的 Chunk 增多,进而增加 CMS GC 发生的频率。如果这些 Chunk 能够被循环利用,系统就不需要申请新的 Chunk ,这样就会使得 YGC 频率降低,晋升到老生代的 Chunk 就会减少, CMS GC 发生的频率就会降低。这就是 MemStore Chunk Pool 的核心思想,具体实现如下:

    1. 系统会创建一个 Chunk Pool 来管理所有未被引用的 chunks ,这些 chunk 就不会再被 JVM 当作垃圾回收掉了

    2. 如果一个 Chunk 没有再被引用,将其放入 Chunk Pool

    3. 如果当前 Chunk Pool 已经达到了容量最大值,就不会再接纳新的 Chunk

    4. 如果需要申请新的 Chunk 来存储 KeyValue ,首先从 Chunk Pool 中获取,如果能够获取得到就重复利用,如果为 null 就重新申请一个新的 Chunk

    官方针对该优化也进行了简单的测试,使用 jstat -gcutil 对优化前后的 JVM GC 情况进行了统计,具体的测试条件和测试结果如下所示:

    4

    很显然,经过优化后 YGC 时间降低了 40+%左右, FGC 的次数以及时间更是大幅下降。

    BlockCache 优化- BuckctCache 方案

    对于需要深入了解 HBase 针对 BlockCache 所做的 GC 优化的朋友,强烈建议首先阅读之前的 3 篇 BlockCache 系列博文: part1 , part2 和 part3 。文中重点介绍了 BlockCache 的两种实现方案: LRUBlockCache 和 BucketCache 。

    其中 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 情况进行了统计,结果如下:

    5

    从结果可以看出, BucketCache 大大减少了碎片的产生,而且 YGC 和 FGC 时间也极大地得到了改善。需要注意的是,此结论是在部分缓存未命中的情况下得出的,缓存全部命中的场景结果会有所不同。

    总结

    所有构建在 JVM 上的应用或多或少都会受到 GC 的影响,尤其对于大内存系统更是如此, HBase 也不例外。针对 GC 问题,一方面我们期待 JVM 能够做出更多地改进和优化,另一方面,我们也可以从内存管理方面进行更多地探索,不断优化内存的使用。 HBase 在 0.98 之后的版本还不断针对 GC 进行着优化,后续再进行补充!

    更多技术分享,请关注网易视频云官方网站( http://vcloud.163.com/)

    或者网易视频云官方微信( vcloud163 )进行交流与咨询

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2526 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 01:49 · PVG 09:49 · LAX 17:49 · JFK 20:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.