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

转载自:http://hbasefly.com/2016/04/26/hbase-blockcache-2/

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

 

LRUBlockCache

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

 

1. 缓存分层策略

HBase在LRU缓存基础上,采用了缓存分层设计,将整个BlockCache分为三个部分:single-access、mutil-access和inMemory。需要特别注意的是,HBase系统元数据存放在InMemory区,因此设置数据属性InMemory = true需要非常谨慎,确保此列族数据量很小且访问频繁,否则有可能会将hbase.meta元数据挤出内存,严重影响所有业务性能。

 

2. LRU淘汰算法实现

系统在每次cache block时将BlockKey和Block放入HashMap后都会检查BlockCache总量是否达到阈值,如果达到阈值,就会唤醒淘汰线程对Map中的Block进行淘汰。系统设置三个MinMaxPriorityQueue队列,分别对应上述三个分层,每个队列中的元素按照最近最少被使用排列,系统会优先poll出最近最少使用的元素,将其对应的内存释放。可见,三个分层中的Block会分别执行LRU淘汰算法进行淘汰。

 

3. LRU方案优缺点

LRU方案使用JVM提供的HashMap管理缓存,简单有效。但随着数据从single-access区晋升到mutil-access区,基本就伴随着对应的内存对象从young区到old区 ,晋升到old区的Block被淘汰后会变为内存垃圾,最终由CMS回收掉(Conccurent Mark Sweep,一种标记清除算法),然而这种算法会带来大量的内存碎片,碎片空间一直累计就会产生臭名昭著的Full GC。尤其在大内存条件下,一次Full GC很可能会持续较长时间,甚至达到分钟级别。大家知道Full GC是会将整个进程暂停的(称为stop-the-wold暂停),因此长时间Full GC必然会极大影响业务的正常读写请求。也正因为这样的弊端,SlabCache方案和BucketCache方案才会横空出世。

 

 

BucketCache

相比LRUBlockCache,BucketCache实现相对比较复杂。它没有使用JVM 内存管理算法来管理缓存,而是自己对内存进行管理,因此不会因为出现大量碎片导致Full GC的情况发生。本节主要介绍BucketCache的具体实现方式(包括BucketCache的内存组织形式、缓存写入读取流程等)以及如何配置使用BucketCache。

 

 

内存组织形式

下图是BucketCache的内存组织形式图,其中上面部分是逻辑组织结构,下面部分是对应的物理组织结构。HBase启动之后会在内存中申请大量的bucket,如下图中黄色矩形所示,每个bucket的大小默认都为2MB。每个bucket会有一个baseoffset变量和一个size标签,其中baseoffset变量表示这个bucket在实际物理空间中的起始地址,因此block的物理地址就可以通过baseoffset和该block在bucket的偏移量唯一确定;而size标签表示这个bucket可以存放的block块的大小,比如图中左侧bucket的size标签为65KB,表示可以存放64KB的block,右侧bucket的size标签为129KB,表示可以存放128KB的block。

70074

 

HBase中使用BucketAllocator类实现对Bucket的组织管理:

1. HBase会根据每个bucket的size标签对bucket进行分类,相同size标签的bucket由同一个BucketSizeInfo管理,如上图,左侧存放64KB block的bucket由65KB BucketSizeInfo管理,右侧存放128KB block的bucket由129KB BucketSizeInfo管理。

2. HBase在启动的时候就决定了size标签的分类,默认标签有(4+1)K、(8+1)K、(16+1)K … (48+1)K、(56+1)K、(64+1)K、(96+1)K … (512+1)K。而且系统会首先从小到大遍历一次所有size标签,为每种size标签分配一个bucket,最后所有剩余的bucket都分配最大的size标签,默认分配 (512+1)K,如下图所示:



22222

 

3. Bucket的size标签可以动态调整,比如64K的block数目比较多,65K的bucket被用完了以后,其他size标签的完全空闲的bucket可以转换成为65K的bucket,但是至少保留一个该size的bucket。

 

 

Block缓存写入、读取流程

下图是block写入缓存以及从缓存中读取block的流程示意图,图中主要包括5个模块,其中RAMCache是一个存储blockkey和block对应关系的HashMap;WriteThead是整个block写入的中心枢纽,主要负责异步的写入block到内存空间;BucketAllocator在上一节详细介绍过,主要实现对bucket的组织管理,为block分配内存空间;IOEngine是具体的内存管理模块,主要实现将block数据写入对应地址的内存空间;BackingMap也是一个HashMap,用来存储blockKey与对应物理内存偏移量的映射关系,用来根据blockkey定位具体的block;其中紫线表示cache block流程,绿线表示get block流程。

33333

 

 

Block缓存写入流程

1. 将block写入RAMCache。实际实现中,HBase设置了多个RAMCache,系统首先会根据blockkey进行hash,根据hash结果将block分配到对应的RAMCache中;

2. WriteThead从RAMCache中取出所有的block。和RAMCache相同,HBase会同时启动多个WriteThead并发的执行异步写入,每个WriteThead对应一个RAMCache;

3. 每个WriteThead会将遍历RAMCache中所有block数据,分别调用bucketAllocator为这些block分配内存空间;

4. BucketAllocator会选择与block大小对应的bucket进行存放(具体细节可以参考上节‘内存组织形式’所述),并且返回对应的物理地址偏移量offset;

5. WriteThead将block以及分配好的物理地址偏移量传给IOEngine模块,执行具体的内存写入操作;

6. 写入成功后,将类似<blockkey,offset>这样的映射关系写入BackingMap中,方便后续查找时根据blockkey可以直接定位;

 

 

Block缓存读取流程

1. 首先从RAMCache中查找。对于还没有来得及写入到bucket的缓存block,一定存储在RAMCache中;

2. 如果在RAMCache中没有找到,再在BackingMap中根据blockKey找到对应物理偏移地址offset;

3. 根据物理偏移地址offset可以直接从内存中查找对应的block数据;

 

 

 

BucketCache工作模式

BucketCache默认有三种工作模式:heap、offheap和file;这三种工作模式在内存逻辑组织形式以及缓存流程上都是相同的,参见上节讲解。不同的是三者对应的最终存储介质有所不同,即上述所讲的IOEngine有所不同。

 

其中heap模式和offheap模式都使用内存作为最终存储介质,内存分配查询也都使用Java NIO ByteBuffer技术,不同的是,heap模式分配内存会调用byteBuffer.allocate方法,从JVM提供的heap区分配,而后者会调用byteBuffer.allocateDirect方法,直接从操作系统分配。这两种内存分配模式会对HBase实际工作性能产生一定的影响。影响最大的无疑是GC ,相比heap模式,offheap模式因为内存属于操作系统,所以基本不会产生CMS GC,也就在任何情况下都不会因为内存碎片导致触发Full GC。除此之外,在内存分配以及读取方面,两者性能也有不同,比如,内存分配时heap模式需要首先从操作系统分配内存再拷贝到JVM heap,相比offheap直接从操作系统分配内存更耗时;但是反过来,读取缓存时heap模式可以从JVM heap中直接读取,而offheap模式则需要首先从操作系统拷贝到JVM heap再读取,显得后者更费时。

 

file模式和前面两者不同,它使用Fussion-IO或者SSD等作为存储介质,相比昂贵的内存,这样可以提供更大的存储容量,因此可以极大地提升缓存命中率。

 

BucketCache配置使用

BucketCache方案的配置说明一直被HBaser所诟病,官方一直没有相关文档对此进行介绍。本人也是一直被其所困,后来通过查看源码才基本了解清楚,在此分享出来,以便大家学习。需要注意的是,BucketCache三种工作模式的配置会有所不同,下面也是分开介绍,并且没有列出很多不重要的参数:

heap模式


<hbase.bucketcache.ioengine>heap</hbase.bucketcache.ioengine>
//bucketcache占用整个jvm内存大小的比例
<hbase.bucketcache.size>0.4</hbase.bucketcache.size>
//bucketcache在combinedcache中的占比
<hbase.bucketcache.combinedcache.percentage>0.9</hbase.bucketcache.combinedcache.percentage>

offheap模式

<hbase.bucketcache.ioengine>offheap</hbase.bucketcache.ioengine>
<hbase.bucketcache.size>0.4</hbase.bucketcache.size>
<hbase.bucketcache.combinedcache.percentage>0.9</hbase.bucketcache.combinedcache.percentage>

file模式

<hbase.bucketcache.ioengine>file:/cache_path</hbase.bucketcache.ioengine>
//bucketcache缓存空间大小,单位为MB
<hbase.bucketcache.size>10 * 1024</hbase.bucketcache.size>
//高速缓存路径
<hbase.bucketcache.persistent.path>file:/cache_path</hbase.bucketcache.persistent.path>

 

 

 

总结

HBase中缓存的设置对随机读写性能至关重要,本文通过对LRUBlockCache和BucketCache两种方案的实现进行介绍,希望能够让各位看官更加深入地了解BlockCache的工作原理。BlockCache系列经过两篇内容的介绍,基本已经解析完毕,那在实际线上应用中到底应该选择哪种方案呢?下一篇文章让我们一起看看HBase社区发布的BlockCache报告!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CDH- Hive HWI 配置

目录 一、HWI安装 二、其中遇到一些问题&#xff1a; 1.遇到如下问题&#xff0c;将jre环境中的toos.jar 服务到lib目录下 2.CDH中没有hwi相关配置参数&#xff0c;手动加入并修改端口为9998&#xff0c;发现并未生效&#xff0c;暂时未找到原因所在。 一、HWI安装 通过查看…

Hive - HWI 简单使用

进入HWI web页面 查看数据库中的表&#xff1a; 单击Create Session&#xff0c;并输入任务名称&#xff08;自定义&#xff09; 输入相关信息 Result File:结果输出文件 Error File:错误输出文件(可不填) Query&#xff1a;需要执行的语句,一些需要设置的参数也在这里面进…

html之插入图片

GIF、JPEG、PNG是最符合在网页设计中使用的格式&#xff0c;但是要想将它们呈现在网页中&#xff0c;必须将它们链接在网页&#xff0c;这是通过HTML中添加到图片的路径链接来实现的。 使用html中的img可以实现该功能 图片的源地址(src属性) <img src"文件路径"…

html之figure元素和figcaption元素为图片声明标题

figure和figcaption元素结合来为图片、视频、表格或者嵌入元素声明标题。以前使用如下方式为图片添加标题&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&g…

常用数学符号大全、关系代数符号

http://www.dataguru.cn/thread-247437-1-1.html 常用数学符号大全、关系代数符号 1、几何符号   ⊥ ∥ ∠ ⌒ ⊙ ≡ ≌ △   2、代数符号   ∝ ∧ ∨ &#xff5e; ∫ ≠ ≤ ≥ ≈ ∞ ∶   3、运算符号   如加号&#xff08;&a…

Segment-based Disparity Refinement with Occlusion Handling for Stereo Matching翻译和理解

摘要 摘要:本文提出了一种视差细化方法&#xff0c;通过对视差统计意义的探讨&#xff0c;直接细化赢者通吃视差图。根据基于分割的立体匹配的主要步骤&#xff0c;将参考图像过度分割为超像素&#xff0c;并通过改进的随机样本对每个超像素进行视差面拟合共识(RANSAC)。我们设…

Hadoop文章收集汇总 - 如禁止转载,请及时联系本人 收集学习互联网各位前辈分享的文章

工具自动自动集成文章列表与URL 公众号名称标题作者发布时间Hadoop实操如何使用Sentry管理Hive仓库目录外的其他目录的acl同步Fayson2018/9/30 8:27Hadoop实操如何使用Impala合并小文件Fayson2018/9/29 1:14Hadoop实操如何规划设置Kafka Broker的heap sizeFayson2018/9/28 0:27…

html之文档的头部和元数据定义(上)

什么叫元数据&#xff1f; 要理解这个问题&#xff0c;首先要知道“元”是什么。元(meta)&#xff0c;一般被我们翻译成“关于……的……”。 元数据(meta data)——“data about data” 关于数据的数据&#xff0c;一般是结构化数据&#xff08;如存储在数据库里的数据&#x…

win10(UEFI)和Ubuntu双系统安装,无法进入ubuntu。

因为win10采用UEFI引导&#xff0c;所以在安装Ubuntu系统的时候着重注意 其中一个分区为efi作为引导分区 要将安装的启动引导器(grub2)设备选择在efi分区上 如下图&#xff1a;

双目标定与矫正 matlab

matlab版本有2015a 或更新的本 1.预先拍摄好多幅标定板图像 像这样&#xff1a; 分别将左右图像放在left和right文件夹中。 2.相机标定 选择APPS,下拉菜单选择"stereo camera calibration" 进入一下界面&#xff0c;点击“add image”,分别设置camera1 &#xff0…

堆排序原理及算法实现(最大堆)

堆排序 堆排序是利用堆的性质进行的一种选择排序。下面先讨论一下堆。 1.堆 堆实际上是一棵完全二叉树&#xff0c;其任何一非叶节点满足性质&#xff1a; Key[i]<key[2i1]&&Key[i]<key[2i2]或者Key[i]>Key[2i1]&&key>key[2i2] 即任何一非叶节点的…

Hbase Region in transition (RIT) 异常解决

查看Hbase状态&#xff0c;突然发现出现了RIT&#xff0c;并且很长时间了~ 查看了一些相关RIT介绍 &#xff08;部分介绍和Hbase2.0不同&#xff0c;如&#xff1a;RIT状态信息2.0已不在zookeeper保存&#xff09; https://mp.weixin.qq.com/s?__bizMzU5OTQ1MDEzMA&mid224…

邻接表的构建、DFS、BFS搜索

接着上次的文章“图的构建&#xff08;邻接链表法&#xff09;”&#xff0c;邻接链表法构建图相对来说比较简单&#xff0c;并且遍历起来也相对简单&#xff0c;但是要是动态添加图的节点和图的边&#xff0c;则是实在不方便&#xff0c;不过现在不管那么多&#xff0c;今天的…

Storm性能简单测试

看了很多关于Storm性能的文章&#xff0c;说法不一&#xff0c;自己根据实际业务测一下是否能满足自身要求&#xff08;只做了简单集群和代码调优&#xff09; 场景&#xff1a;kafka消费数据标准化后存储到Hbase中 服务器资源&#xff1a;两台32G内存做Supervisor 使用资源平…

Hbase Shell 介绍

目录 Scan 创建表 Count 清空表数据 删除数据 删除表 删除列簇 判断表是否为‘enable’ 插入 Region管理 Scan 查询某个表某个列的数据&#xff1a; scan tableName,{COLUMN>列族&#xff1a;列,LIMIT>需要查看条数} 指定开始Rowkey查询 scan tableName,{STARTRO…

拓扑排序 详解 + 并查集 详解 + 最小生成树详解

若您发现本文有什么错误&#xff0c;请联系我&#xff0c;我会及时改正的&#xff0c;谢谢您的合作&#xff01; 本文为原创文章&#xff0c;转载请注明出处 本文链接 &#xff1a; http://www.cnblogs.com/Yan-C/p/3943940.html 。 哎呀&#xff0c;好久了啊&#xff0c;想…

Impala Shell 简单命令

目录 1.更新元数据 2.对查询结果去格式化 3.查询结果存储到文件 4.去格式化后指定分隔符 5.-p或者--show-profiles:显示查询的执行计划(与EXPLAIN语句输出相同)和每个查询语句底层的执行步骤的详细信息. 6.指定主机名连接 (-i) 7.执行查询语句 8.指定脚本文件执行SQL …

CDH邮件预警

转载自&#xff1a;http://blog.51cto.com/feature09/2055835 在CDH的7180页面找到Cloudera Managerment Service 如图所示&#xff1a; 在Configuration中&#xff0c;搜索alert 设置接收信息的邮箱。 设置内容都在图片上&#xff1a; 添加邮件页眉说明&#xff0c;第一行显…

结构光双目视觉测距原理

结构光视觉技术是一种主动投影式的三维测量技术&#xff0c;通过使用投影仪和相机组成的系统来对物体进行三维测量 系统结构&#xff1a; 硬件系统&#xff1a; 常见编码方法&#xff1a; 结构光图案编码 常用的是格雷码和传统的二进制码相比&#xff0c;格雷码的编码数中任意…

c++静态成员函数为什么不能为虚函数?

知乎用户 three passions govern my life2 人赞同可以把静态成员函数看作是“命名空间受限的普通函数”&#xff0c;所以它不能有运行时多态发布于 2015-06-23 添加评论 感谢 分享收藏 • 没有帮助 • 举报 • 作者保留权利Elvis Wang C程序员转型Java中6 人赞同其实我觉得这个…