CDH用MSLAB避免Hbase FullGC
使用Hbase过程中如果出现长时间Stop-The-World GC,会造成以下两种影响:
1. 在Stop-The-World GC过程中,用户请求被阻塞,导致明显的延迟甚至超时。
2. Hbase通过zookeeper维系集群节点存活。如果长时间没有向zookeeper发送ping消息,则master会启动任务让其他节点接替该节点。
JAVA GC
目前java主要采用分代垃圾回收策略。这种策略假设java虚拟机里的对象either die young, or stick around for quite a long time。不同生命期的对象采用各自最合适的垃圾回收算法可以提高回收效率。
年轻代采用ParNew GC:首先停止所有java工作线程,然后跟踪左右对象的引用确定对象是否存活,最后移动这些对象到另一个区域并更新所有引用指向到新的对象地址。parNew GC 的速度很快,因为年轻代的空间本来就很小,而且这是多线程并行回收。这种基于复制的垃圾回收再回收空间同时也把空间进行压缩,即空闲空间集中在一起。
老年代垃圾回收CMS:
老年代垃圾回收主要采用CMS,回收分几个阶段,有的是Stop-The-Word的,有的阶段可以和java工作线程并行执行。Stop-The-Word的两个阶段时间很短,并发阶段则可以和工作线程并行执行,因此整个过程不会对请求有太大延迟;另外,垃圾CMS不会对回收后的空间进行压缩,因此会产生内存碎片。具体步骤如下:
· initial-mark (stops the world). In this phase, the CMS collector places a mark on the root objects. A root object is something directly referenced from a live Thread – for example, the local variables in use by that thread. This phase is short because the number of roots is very small.
· concurrent-mark (concurrent). The collector now follows every pointer starting from the root objects until it has marked all live objects in the system.
· remark (stops the world). Since objects might have had references changed, and new objects might have been created during concurrent-mark, we need to go back and take those into account in this phase. This is short because a special data structure allows us to only inspect those objects that were modified during the prior phase.
· concurrent-sweep (concurrent). Now, we proceed through all objects in the heap. Any object without a mark is collected and considered free space. New objects allocated during this time are marked as they are created so that they aren’t accidentally collected.
CMS有两种失败的情况,这两种情况一旦发生,则CMS回收算法变成Stop-the-world的单线程复制垃圾回收,将所有数据拷贝到jvm堆空间的开始处。
1) Concurrent Mode Failure:即CMS在垃圾回收过程中还没来得及释放空间,源源不断的java对象被写入进老年代,导致老年代空间占满从而无法继续执行java工作线程。这种情况可以通过设置CMSInitiatingOccupancyFraction 参数解决。
2)Promotion Failure due to Fragmentation:CMS如期进行了垃圾回收,但是由于CMS不会对堆空间进行压缩,从而导致堆内存碎片;而且CMS执行次数越多,会是碎片更严重。最后的结果就是线程请求分配一个稍大的对象时,已经找不到一块满足大小条件的连续堆空间。这种情况基本无法避免,hbase在应用采用MSLAB主要就是解决CMS垃圾回收后的碎片问题。可以通过设置java启动参数-XX:PrintFLSStatistics=1,让java在垃圾回收时打印出垃圾回收时空闲空间,不连续的内存块数,以及不连续的内存块的最大块大小。
试验:估计堆碎片
设置了CMSInitiatingOccupancyFraction 为合理的值可以避免Concurrent Mode Failure,则HBASE中产生的长时间停顿基本确定是由于内存碎片引起的stop-the-world垃圾回收造成。首先确定什么情况下容易导致内存碎片,分别对以下三种场景进行试验测试:
· Write-only: writes rows with 10 columns, each 100 bytes, across 100M distinct row keys.
· Read-only with cache churn: reads data randomly for 100M distinct row keys, so that the data does not fit in the LRU cache.
· Read-only without cache churn: reads data randomly for 10K distinct row keys, so that the data fits entirely in the LRU cache
实验结果:
结果图中上半部分表示堆空间中的空闲大小,下半部分表示各个时刻堆内存中最大连续内存块的大小。从图可知,三种场景的内存特征是很不一样的。横坐标表示时间。
下面具体查看各种场景:
Write-only Workload
从图中可以看出,空闲内存从2.8G到3.8G之间波动。每次空闲内存减小到2.8G时,老年代堆内存使用达到initiating occupancy fraction 阈值,从而进行CMS垃圾回收,释放1G空间。测试期间空闲内存稳定在这个固定区间,说明没有内存泄露。max_chunk 的值一直减小到几乎接近零,直到没有办法进行内存分配,此时进行Stop-The-world垃圾回收,对内存进行进行压缩,空闲空间拼接在一起。
Read-only Workload with Cache Churn
带cache的读测试中,读取的记录数远比LRU block cache大,因此随着大量记录被放入堆中然后被释放掉可见很大的内存空闲空间波动。带缓存读的情况下垃圾回收比单纯写入场景时垃圾回收频繁的多,但是最大连续可用内存空间却相对稳定,几乎保持常量大小。
Read-only Workload without Cache Churn
不带缓存的读场景,由于每次只需要读入特定的RPC请求的记录,从而对象非常少,且不会进入老年代,因此老年代不存在垃圾回收。空闲空间和最大连续空间保持常量。
试验结论
1. 我们一直想消除的full GC是由堆内存碎片引起的,而不是concurrent-mode failure
2. write-only 场景比两种读场景更容易导致内存碎片。
为什么写数据导致内存碎片?
Hbase将一张表自动分成很多分区,叫做region,表很大的时候一个节点可能维护很多region,每个region在内存里维护一个memStore,实际上是一个sorted Map。内存是有限的,当内存使用达到一个限制时,则会出发某些Region的memstore的flush。由于region很多,写入的数据是无序的,各个region的memStore中的数据在内存中混在一起,当一个region去flush时,就会形成内存的碎片,flush次数越多,碎片化就更严重,最终就需要stop-the-world垃圾回收整理碎片啦。假如一个节点有五个region(用不同的颜色表示),则一个region flush 后结果如下图:
MSLAB
如上描述,一个regionserver的内存里各个region的数据混合在一起,当某个region被flush到磁盘时,就会形成很多堆碎片。其实这跟java中gc模型的假设是冲突的:同一时间创建的对象,会在同一时间消亡。这个问题可以通过arena allocation来解决—每次分配内存时都是在一个更大的叫做arena的内存区域分配。一个典型的实现是TLAB,即每个线程维护自己的arena,每个线程用到的对象都在自己的arena区域分配。其实,jvm早已经实现了TLAB,但是这个对于hbase不适用,因为hbase的regionserver使用一个单独的线程来处理所有region的请求,就算这个线程用arena方式分配还是会把所有region的数据混在一起。因此hbase自己实现了MSLAB,即每个region的memStore自己实现了arena,使各个region的数据分开,就不会形成太细的碎片。Arena里存放的是KeyValue对象,这个对象,这些KeyValue对象时一样大的,不会导致严重碎片,相反这些KeyValue对象引用的字节数组才是引起碎片的主因。因此要做的就是把这些字节数组分配在一起。
MSLAB的具体实现:
1) Each MemStore instance has an associated instance of a new class MemStoreLAB.
2)MemStoreLAB retains a structure called curChunk which consists of a 2MB byte[] and a nextFreeOffset pointer starting at 0.
3)When a KeyValue is about to be inserted into the MemStore, it is first copied into curChunk and the nextFreeOffsetpointer is bumped by the length of the new data.
4) Should the 2MB chunk fill up, a new one is allocated from the JVM using the usual method: new byte[2*1024*1024].
使用MSLAB的试验结果:从图可知,随着数据写入时间变长,最大连续内存块趋于稳定,而不像之前减小到接近0并触发Stop-The-world gc。
配置使用MSLAB
Configuration |
Description |
hbase.hregion.memstore.mslab.enabled |
Set to true to enable this feature |
hbase.hregion.memstore.mslab.chunksize |
The size of the chunks allocated by MSLAB, in bytes (default 2MB) |
hbase.hregion.memstore.mslab.max.allocation |
The maximum size byte array that should come from the MSLAB, in bytes (default 256KB) |
相关推荐
在Java编程环境中,操作HBase并将其数据写入HDFS(Hadoop Distributed File System)是一项常见的任务,特别是在大数据处理和分析的场景下。本篇将详细介绍如何使用Java API实现这一功能,以及涉及到的关键技术和...
- 涉及了在HBase中进行模式设计时需要考虑的要素,包括列族的创建、行键设计、版本数量控制等。 - 探讨了支持的数据类型和使用第二索引以及替代查询路径。 - 讨论了设计时的一些限制和用例,以及对操作和性能产生...
在IT行业中,尤其是在大数据处理领域,HBase是一个广泛使用的分布式、高性能、列式存储的NoSQL数据库。HBase是建立在Hadoop文件系统(HDFS)之上,为处理大规模数据提供了一个高效的数据存储解决方案。而Spring Data...
本指南针对HBase的中文用户,旨在帮助读者更好地理解和使用HBase,特别是在Python环境中进行开发。 ### 一、HBase简介 HBase是Google Bigtable的开源实现,它具有高度可扩展性,能够存储海量数据,并且支持实时...
讲师:陈杨——快手大数据高级研发工程师 ...内容概要:(1)讲解hbase coprocessor的原理以及使用场景,(2) coprocessor整个流程实战,包括开发,加载,运行以及管理(3)结合1,2分析coprocessor在rsgroup中的具体使用
HBase是一种分布式的、面向列的数据库管理系统,它利用Hadoop HDFS作为其文件存储系统,使用Hadoop MapReduce来处理HBase中的海量数据,并且使用Zookeeper作为其协同服务。HBase以表的形式存储数据,表由行和列组成...
3.1. 从HBase 0.20.x or 0.89.x 升级到 HBase 0.90.x 3.2. 从 0.90.x 到 0.92.x 4. The HBase Shell 4.1. 使用脚本 4.2. Shell 技巧 5. 数据模型 5.1. 概念视图 5.2. 物理视图 5.3. 表 5.4. 行 5.5. 列族 5.6. Cells...
用户可以在MapReduce程序中访问HBase中的数据,也可以将MapReduce作为批量加载数据到HBase中的手段。 ### HBase安全 HBase的安全章节讲述了如何安全地访问HBase集群,包括安全客户端访问、访问控制和安全批量加载...
HBase是一种分布式、基于列族的NoSQL数据库,由Apache软件基金会开发并维护,是Hadoop生态系统中的重要组件。这份“HBase官方文档中文版”提供了全面深入的HBase知识,帮助用户理解和掌握如何在大数据场景下有效地...
本文将详细介绍如何将MySQL中的数据处理成JSON格式并导入到HBase中。 首先,我们需要了解MySQL的基本操作。MySQL是一个流行的开源RDBMS,它支持SQL语言,用于创建、查询、更新和删除数据库中的记录。在本场景中,...
HBase 0.97 中文文档 HBase 0.97 中文文档 HBase 0.97 中文文档
HBase是Apache软件基金会下的Hadoop项目中的一个子项目,它是一个分布式、面向列的NoSQL数据库系统,主要用来解决大量结构化数据的存储和实时读写访问问题。HBase的设计灵感来源于谷歌的Bigtable,提供了对海量数据...
这可以通过修改`hbase-site.xml`文件中的`hbase.master.info.port`和`hbase.master.info.address`属性来实现,指定多个Master节点。例如: ```xml <name>hbase.master.info.address <value>master1:60010,...
在本文中,作者使用了HBaseConfiguration.create()方法来创建配置对象,并设置了"hbase.zookeeper.quorum"和"hbase.zookeeper.property.clientPort"两个参数。 知识点2:HTablePool的使用 HTablePool是HBase中的一...
通过阅读《HBase中文教程》,Java开发者不仅可以了解HBase的基本原理,还能学会如何在实际工作中运用HBase解决大数据存储和处理问题,提升项目效率。无论是对大数据感兴趣的初学者,还是有经验的开发者,都能从这本...
通过这两份文档,读者可以全面了解HBase的工作原理、使用方法和最佳实践,从而在大数据处理场景中有效地利用HBase进行数据存储和查询。无论是要进行大数据项目开发,还是进行系统运维,这些文档都将提供宝贵的知识和...
- **HBase的历史**:HBase起源于一个叫做Hadoop的项目中的子项目,最初是为了实现一个类似于Bigtable的功能而创建的。 - **术语介绍**: - **背景层**(Backdrop):HBase运行于Hadoop之上,利用Hadoop提供的分布式...
本文将详细讲解如何在Hadoop环境中安装HBase以及如何使用Java API进行数据操作。 首先,我们需要进行HBase的安装。下载HBase的安装包,例如hbase-1.2.6-bin.tar.gz,将其解压缩到/usr/local目录下,然后重命名解压...
在本实验中,我们主要聚焦于HBase,这是一个基于谷歌Bigtable设计的开源NoSQL数据库,广泛应用于大数据存储场景。实验旨在让参与者熟练掌握HBase的Shell操作,包括创建表、输入数据以及进行特定查询。以下是详细步骤...
HBase,作为Apache Hadoop生态系统中的一个分布式、高性能、列式存储的NoSQL数据库,常用于处理大规模数据。虽然HBase提供了命令行接口(CLI)供用户操作数据库,但这种交互方式对于复杂查询和管理任务可能不够直观...