0 引言

和其他数据库一样,优化IO也是HBase提升性能的不二法宝,而提供缓存更是优化的重中之重。

根据二八法则,80%的业务请求都集中在20%的热点数据上,因此将这部分数据缓存起就可以极大地提升系统性能。

HBase在实现中提供了两种缓存结构:MemStore和BlockCache。其中MemStore称为写缓存,HBase执行写操作首先会将数据写入MemStore,并顺序写入HLog,等满足一定条件后统一将MemStore中数据刷新到磁盘,这种设计可以极大地提升HBase的写性能。不仅如此,MemStore对于读性能也至关重要,假如没有MemStore,读取刚写入的数据就需要从文件中通过IO查找,这种代价显然是昂贵的!BlockCache称为读缓存,HBase会将一次文件查找的Block块缓存到Cache中,以便后续同一请求或者邻近数据查找请求,可以直接从内存中获取,避免昂贵的IO操作。

1. Contents of the BlockCache

了解BlockCache中存放的内容,可以帮助我们更好设计BlockCache的大小。

  • Your data: Each time a Get or Scan operation occurs, the result is added to the BlockCache if it was not already cached there. If you use the BucketCache, data blocks are always cached in the BucketCache.

  • Row keys: When a value is loaded into the cache, its row key is also cached. This is one reason to make your row keys as small as possible. A larger row key takes up more space in the cache.

  • hbase:meta: The hbase:meta catalog table keeps track of which RegionServer is serving which regions. It can consume several megabytes of cache if you have a large number of regions, and has in-memory access priority, which means HBase attempts to keep it in the cache as long as possible.

  • Indexes of HFiles: HBase stores its data in HDFS in a format called HFile. These HFiles contain indexes which allow HBase to seek for data within them without needing to open the entire HFile. The size of an index is a factor of the block size, the size of your row keys, and the amount of data you are storing. For big data sets, the size can exceed 1 GB per RegionServer, although the entire index is unlikely to be in the cache at the same time. If you use the BucketCache, indexes are always cached on-heap.

  • Bloom filters: If you use Bloom filters, they are stored in the BlockCache. If you use the BucketCache, Bloom filters are always cached on-heap.

The sum of the sizes of these objects is highly dependent on your usage patterns and the characteristics of your data. For this reason, the HBase Web UI and Cloudera Manager each expose several metrics to help you size and tune the BlockCache.

将上面的缓存分为两类:

  1. 数据本身:your data、rowkeys
  2. 索引: hbase:meta、Indexes of HFiles、Bloom filters。

当使用BucketCache,数据缓存的最小单位是Block。

2. BlockCache

BlockCache是Region Server级别的,一个Region Server只有一个Block Cache,在Region Server启动的时候完成Block Cache的初始化工作。到目前为止,HBase先后实现了3种Block Cache方案,LRUBlockCache是最初的实现方案,也是默认的实现方案;HBase 0.92版本实现了第二种方案SlabCache,见HBASE-4027;HBase 0.96之后官方提供了另一种可选方案BucketCache,见HBASE-7404。

2.1 LRU Least-Recently-Used

LRU缓存把最近最少使用的数据移除,让给最新读取的数据。而往往最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance.

2.2 LRUBlockCache

LRUBlockCache将缓存分为三块:single-access区、mutil-access区、in-memory区,分别占到整个BlockCache大小的25%、50%、25%。

memory区表示数据可以常驻内存,一般用来存放访问频繁、数据量小的数据,比如元数据,用户也可以在建表的时候通过设置列族属性IN-MEMORY= true将此列族放入in-memory区。很显然,这种设计策略类似于JVM中young区、old区以及perm区。无论哪个区,系统都会采用严格的Least-Recently-Used算法

LruBlockCache内部是通过一个ConcurrentHashMap来保存所有cache的block的。

/** Concurrent map (the cache) */
private final Map<BlockCacheKey,LruCachedBlock> map;
map = new ConcurrentHashMap<BlockCacheKey,LruCachedBlock>(mapInitialSize,
mapLoadFactor, mapConcurrencyLevel);
  • LRU方案优缺点:

    • 优点:LRU方案使用JVM提供的HashMap管理缓存,简单有效。
    • 缺点:Full GC:在大内存条件下,一次Full GC很可能会持续较长时间,甚至达到分钟级别

2.2 SlabCache

使用Java NIO DirectByteBuffer技术实现了堆外内存存储。

SlabCache有两个缓存区,分别占整个BlockCache大小的80%和20%,每个缓存区分别存储固定大小的Block块:

前者主要存储小于等于64K大小的Block,后者存储小于等于128K Block,如果一个Block太大就会导致两个区都无法缓存。
  • Q: 用户设置BlockSize = 256K怎么办?

    HBase实际实现中将SlabCache和LRUBlockCache搭配使用,称为DoubleBlockCache。一次随机读中,一个Block块从HDFS中加载出来之后会在两个Cache中分别存储一份;缓存读时首先在LRUBlockCache中查找,如果Cache Miss再在SlabCache中查找,此时如果命中再将该Block放入LRUBlockCache中。

  • SlabCache存在的问题?

    SlabCache设计中固定大小内存设置会导致实际内存使用率比较低,

    而且使用LRUBlockCache缓存Block依然会因为JVM GC产生大量内存碎片。

2.3 BlockCache

2.3.1 BucketCache内存组织形式

每个bucket会有一个baseoffset变量和一个size标签,其中baseoffset变量表示这个bucket在实际物理空间中的起始地址,因此block的物理地址就可以通过baseoffset和该block在bucket的偏移量唯一确定;而size标签表示这个bucket可以存放的block块的大小。

默认14个不同大小的Bucket :4, 8, 16, 32, 40, 48, 56, 64, 96, 128, 192, 256, 384, 512 KB

优点:可以缓存不同大小的数据块Block。

2.3.2 使用BucketAllocator类实现对Bucket的组织管理

  1. HBase会根据每个bucket的size标签对bucket进行分类,相同size标签的bucket由同一个BucketSizeInfo管理;
  2. HBase在启动的时候为每种size标签分配一个bucket,最后所有剩余的bucket都分配最大的size标签,默认分配(512+1)K
  3. Bucket的size标签可以动态调整,比如64K的block数目比较多,65K的bucket被用完了以后,其他size标签的完全空闲的bucket可以转换成为65K的bucket,但是至少保留一个该size的bucket。

2.3.3 Block缓存写入、读取流程

  • RAMCache是一个存储blockkey和block对应关系的HashMap;
  • WriteThead是整个block写入的中心枢纽,主要负责异步的写入block到内存空间;
  • BucketAllocator主要实现对bucket的组织管理,为block分配内存空间;
  • IOEngine是具体的内存管理模块,主要实现将block数据写入对应地址的内存空间;
  • BackingMap也是一个HashMap,用来存储blockKey与对应物理内存偏移量的映射关系,用来根据blockkey定位具体的block;

其中实线表示cache block流程,虚线表示get block流程。

2.3.4 BucketCache工作模式

  • BucketCache默认有三种工作模式:

    heap、offheap和file;

三者不同之处是对应的最终存储介质有所不同,即上述所讲的IOEngine有所不同。

  • heap模式和offheap模式,使用内存作为最终存储介质。

    分配内存时,offheap快;读内存时,heap快。heap模式受GC影响

  • file模式

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

3. BlockCache参数设置

  • 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>

4. BlockCache使用场景

  1. 在’缓存全部命中’场景下,LRU君可谓完胜CBC君。因此如果总数据量相比JVM内存容量很小的时候,选择LRU君;

  2. 在所有其他存在缓存未命中情况的场景下, LRU君的GC性能几乎只有CBC君的1/3,而吞吐量、读写延迟、IO、CPU等指标两者基本相当,因此建议选择CBC。

之所以在’缓存全部命中’场景下LRU的各项指标完胜CBC,而在’缓存大量未命中’的场景下,LRU各项指标与CBC基本相当,是因为HBase在读取数据的时候,如果都缓存命中的话,对于CBC,需要将堆外内存先拷贝到JVM内,然后再返回给用户,流程比LRU君的堆内内存复杂,延迟就会更高。而如果大量缓存未命中,内存操作就会占比很小,延迟瓶颈主要在于IO,使得LRU和CBC两者各项指标基本相当。

  • BlockCache不同配置场景

1)如果请求的数据比较符合缓存,命中率比较高,使用LRUBlockCache方式会比CombinedBlockCache的吞吐量高上20%(但也会牺牲一些垃圾回收)。

1)如果需要缓存的数据超过堆大小的情况下,推荐使用Block Cache下的off-heap。

2)当scan获取数据时,可以通过setCacheBlocks方法来设置是否使用block cache,对于频繁访问的行才建议使用block cache。

3)对于MapReduce的Scan作为输入任务,应该设置为setCacheBlocks(false)。

4)如果缓存遇到持续高的驱逐速率,这会导致LruBlockCache大量的垃圾回收,请使用CombinedBlockCache。

5)CombinedBlockCache在固态磁盘上使用file文件模式具有更好的垃圾回收,但吞吐量低于CombinedBlockCache使用offheap模式。

5. 小结

BlockCache先使用默认参数LRUBlockCache

最佳参数:根据监控指标做优化,加大内存并兼顾GC时间。

参考文献

hbase实践(十六) BlockCache的更多相关文章

  1. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  2. 十六款值得关注的NoSQL与NewSQL数据库--转载

    原文地址:http://tech.it168.com/a2014/0929/1670/000001670840_all.shtml [IT168 评论]传统关系型数据库在诞生之时并未考虑到如今如火如荼 ...

  3. VMware vSphere 服务器虚拟化之二十六 桌面虚拟化之View Persona Management

    VMware vSphere 服务器虚拟化之二十六 桌面虚拟化之View Persona Management 实验失败告终,启动VMware View Persona Management服务报10 ...

  4. 小程序实践(六):view内部组件排版

    涉及知识点: 1.垂直排列,水平排列 2.居中对齐 示例: 1.默认排版 , 一个父组件里面两个子view 显示效果: 2.先给父view设置一个高度和颜色值,用于看效果 3.实现水平排列和垂直排列的 ...

  5. ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 try.dot.net 的正确使用姿势 .Net NPOI 根据excel模板导出excel、直接生成excel .Net NPOI 上传excel文件、提交后台获取excel里的数据

    ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案   ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不 ...

  6. 读《构建之法》一、二、十六章随笔a

    第一章    概论 “软件团队要从需求分析开始,把合适的需求梳理出来,然后逐步开展后续工作”:——p3 问题:好的用户体验要从软件分析开始,那么软件分析仅仅是从用户的需求出发吗? 我的看法:需求分析是 ...

  7. 20145302张薇《Java程序设计》第十六周课程总结

    20145302 <Java程序设计>第十六周课程总结 实验报告链接汇总 实验一 Java开发环境的熟悉 实验二 Java面向对象程序设计 实验三 敏捷开发与XP实践 实验四 Andoid ...

  8. 跟我学SpringCloud | 第十六篇:微服务利剑之APM平台(二)Pinpoint

    目录 SpringCloud系列教程 | 第十六篇:微服务利剑之APM平台(二)Pinpoint 1. Pinpoint概述 2. Pinpoint主要特性 3. Pinpoint优势 4. Pinp ...

  9. 选择阿里云数据库HBase版十大理由

    根据Gartner的预计,全球非关系型数据库(NoSQL)在2020~2022预计保持在30%左右高速增长,远高于数据库整体市场. 阿里云数据库HBase版也是踏着技术发展的节奏,伴随着NoSQL和大 ...

  10. Flask 教程 第十六章:全文搜索

    本文翻译自The Flask Mega-Tutorial Part XVI: Full-Text Search 这是Flask Mega-Tutorial系列的第十六部分,我将在其中为Microblo ...

随机推荐

  1. TCP 客户端编程

    1.Qt中TCP客户端编程 对Qt编程而言,网络只是数据传输的通道: Qt提供了QTcpSocket类(封装了TCP协议细节): 将QTcpSocket的对象当做黑盒使用,进行数据首发. 1.1QTc ...

  2. Information Cartography

    作者:Dafna Shahaf 会议:ACM 2015.    研究大背景:自动化地从很大数据集中提取结构化的知识变得越来越难.在本篇文章中,我们将探索我们在文献中(25,26,27)中创立的方法来自 ...

  3. vbox配置共享磁盘

    本人实在配置Oracle rac的时候,进行共享磁盘的配置 以下操作要在虚拟机关机的情况下进行: 接下来按照步骤走即可

  4. 『Linux』第一节: 部署虚拟环境

    一. 准备工具 1. VMware Workstation Pro下载 1.1 VMware Workstation Pro 激活许可证 UY758-0RXEQ-M81WP-8ZM7Z-Y3HDA V ...

  5. S03_CH13_ZYNQ A9 TCP UART双核AMP例程

    S03_CH13_ZYNQ A9 TCP UART双核AMP例程 13.1概述 ZYNQ中存在两个独立的ARM核,在很多应用场景中往往只需使用其中的1个核心即可.然而,对于复杂的设计,例如多任务,并行 ...

  6. 【百度之星2019】Strassen

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6719 在本题中,我们只有两种方法计算两个的矩阵的乘积,第一种为定义法,需要次乘法和次加法.第二种为 ...

  7. 并不对劲的THUWC2020

    day -inf 因为一些(不是寒假时长锐减的)小原因,今年(2020)THUWC在去年(2019)就举办了! 这导致某个小弱智只能临阵磨枪了QAQ- day 1 早: 没有看到吕爷,签到.试机. 签 ...

  8. Linux Mysql 备份与还原

    1. 备份 cd /var/lib/mysql //进入到MySQL库目录 mysqldump -u root -p 数据库>/root/backup/数据库.sql 然后输入密码 2. 还原 ...

  9. (十五)Activitivi5之多用户任务分配

    一.概念 我们在开发的时候,有一种情况是这样的, 我们有一个任务,可以让多个用户中的任何一个人办理即可,比如某个审批任务, 张三,李四,王五他们中的任何一人办理下都行,这时候,我们用到多用户任务分配. ...

  10. android 自动化测试案例之 MonkeyRunner

    #-*- coding: UTF-8 -*- #上面第一行是设置文件编码,windows下第一行必须是这个#文件名 MonkeyRunner.py#功能: 使用monkey runner测试app,此 ...