HBase查询优化

1.概述

HBase是一个实时的非关系型数据库,用来存储海量数据。但是,在实际使用场景中,在使用HBase API查询HBase中的数据时,有时会发现数据查询会很慢。本篇博客将从客户端优化和服务端优化两个方面来介绍,如何提高查询HBase的效率。

2.内容

这里,我们先给大家介绍如何从客户端优化查询速度。

2.1 客户端优化

客户端查询HBase,均通过HBase API的来获取数据,如果在实现代码逻辑时使用API不当,也会造成读取耗时严重的情况。

2.1.1 Scan优化

在使用HBase的Scan接口时,一次Scan会返回大量数据。客户端向HBase发送一次Scan请求,实际上并不会将所有数据加载到本地,而是通过多次RPC请求进行加载。这样设计的好处在于避免大量数据请求会导致网络带宽负载过高影响其他业务使用HBase,另外从客户端的角度来说可以避免数据量太大,从而本地机器发送OOM(内存溢出)。

默认情况下,HBase每次Scan会缓存100条,可以通过属性hbase.client.scanner.caching来设置。另外,最大值默认为-1,表示没有限制,具体实现见源代码:

/*** @return the maximum result size in bytes. See {@link #setMaxResultSize(long)}*/public long getMaxResultSize() {return maxResultSize;}/*** Set the maximum result size. The default is -1; this means that no specific* maximum result size will be set for this scan, and the global configured* value will be used instead. (Defaults to unlimited).** @param maxResultSize The maximum result size in bytes.*/public Scan setMaxResultSize(long maxResultSize) {this.maxResultSize = maxResultSize;return this;}

一般情况下,默认缓存100就可以满足,如果数据量过大,可以适当增大缓存值,来减少RPC次数,从而降低Scan的总体耗时。另外,在做报表呈现时,建议使用HBase分页来返回Scan的数据。

2.1.2 Get优化

HBase系统提供了单条get数据和批量get数据,单条get通常是通过请求表名+rowkey,批量get通常是通过请求表名+rowkey集合来实现。客户端在读取HBase的数据时,实际是与RegionServer进行数据交互。在使用批量get时可以有效的较少客户端到各个RegionServer之间RPC连接数,从而来间接的提高读取性能。批量get实现代码见org.apache.hadoop.hbase.client.HTable类:

public Result[] get(List<Get> gets) throws IOException {if (gets.size() == 1) {return new Result[]{get(gets.get(0))};}try {Object[] r1 = new Object[gets.size()];batch((List<? extends Row>)gets, r1, readRpcTimeoutMs);// Translate.Result [] results = new Result[r1.length];int i = 0;for (Object obj: r1) {// Batch ensures if there is a failure we get an exception insteadresults[i++] = (Result)obj;}return results;} catch (InterruptedException e) {throw (InterruptedIOException)new InterruptedIOException().initCause(e);}}

从实现的源代码分析可知,批量get请求的结果,要么全部返回,要么抛出异常。

2.1.3 列簇和列优化

通常情况下,HBase表设计我们一个指定一个列簇就可以满足需求,但也不排除特殊情况,需要指定多个列簇(官方建议最多不超过3个),其实官方这样建议也是有原因的,HBase是基于列簇的非关系型数据库,意味着相同的列簇数据会存放在一起,而不同的列簇的数据会分开存储在不同的目录下。如果一个表设计多个列簇,在使用rowkey查询而不限制列簇,这样在检索不同列簇的数据时,需要独立进行检索,查询效率固然是比指定列簇查询要低的,列簇越多,这样影响越大。

而同一列簇下,可能涉及到多个列,在实际查询数据时,如果一个表的列簇有上1000+的列,这样一个大表,如果不指定列,这样查询效率也是会很低。通常情况下,在查询的时候,可以查询指定我们需要返回结果的列,对于不需要的列,可以不需要指定,这样能够有效地的提高查询效率,降低延时。

2.1.4 禁止缓存优化

批量读取数据时会全表扫描一次业务表,这种提现在Scan操作场景。在Scan时,客户端与RegionServer进行数据交互(RegionServer的实际数据时存储在HDFS上),将数据加载到缓存,如果加载很大的数据到缓存时,会对缓存中的实时业务热数据有影响,由于缓存大小有限,加载的数据量过大,会将这些热数据“挤压”出去,这样当其他业务从缓存请求这些数据时,会从HDFS上重新加载数据,导致耗时严重。

在批量读取(T+1)场景时,建议客户端在请求是,在业务代码中调用setCacheBlocks(false)函数来禁止缓存,默认情况下,HBase是开启这部分缓存的。源代码实现为:

/*** Set whether blocks should be cached for this Get.* <p>* This is true by default.  When true, default settings of the table and* family are used (this will never override caching blocks if the block* cache is disabled for that family or entirely).** @param cacheBlocks if false, default settings are overridden and blocks* will not be cached*/public Get setCacheBlocks(boolean cacheBlocks) {this.cacheBlocks = cacheBlocks;return this;}/*** Get whether blocks should be cached for this Get.* @return true if default caching should be used, false if blocks should not* be cached*/public boolean getCacheBlocks() {return cacheBlocks;}

2.2 服务端优化

HBase服务端配置或集群有问题,也会导致客户端读取耗时较大,集群出现问题,影响的是整个集群的业务应用。

2.2.1 负载均衡优化

客户端的请求实际上是与HBase集群的每个RegionServer进行数据交互,在细分一下,就是与每个RegionServer上的某些Region进行数据交互,每个RegionServer上的Region个数上的情况下,可能这种耗时情况影响不大,体现不够明显。但是,如果每个RegionServer上的Region个数较大的话,这种影响就会很严重。笔者这里做过统计的数据统计,当每个RegionServer上的Region个数超过800+,如果发生负载不均衡,这样的影响就会很严重。

可能有同学会有疑问,为什么会发送负载不均衡?负载不均衡为什么会造成这样耗时严重的影响?

1.为什么会发生负载不均衡?

负载不均衡的影响通常由以下几个因素造成:

  • 没有开启自动负载均衡
  • 集群维护,扩容或者缩减RegionServer节点
  • 集群有RegionServer节点发生宕机或者进程停止,随后守护进程又自动拉起宕机的RegionServer进程

针对这些因素,可以通过以下解决方案来解决:

  • 开启自动负载均衡,执行命令:echo "balance_switch true" | hbase shell
  • 在维护集群,或者守护进程拉起停止的RegionServer进程时,定时调度执行负载均衡命令:echo "balancer" | hbase shell

2.负载不均衡为什么会造成这样耗时严重的影响?

这里笔者用一个例子来说,集群每个RegionServer包含由800+的Region数,但是,由于集群维护,有几台RegionServer节点的Region全部集中到一台RegionServer,分布如下图所示:

这样之前请求在RegionServer2和RegionServer3上的,都会集中到RegionServer1上去请求。这样就不能发挥整个集群的并发处理能力,另外,RegionServer1上的资源使用将会翻倍(比如网络、磁盘IO、HBase RPC的Handle数等)。而原先其他正常业务到RegionServer1的请求也会因此受到很大的影响。因此,读取请求不均衡不仅会造成本身业务性能很长,还会严重影响其他正常业务的查询。同理,写请求不均衡,也会造成类似的影响。故HBase负载均衡是HBase集群性能的重要体现。

2.2.2 BlockCache优化

BlockCache作为读缓存,合理设置对于提高读性能非常重要。默认情况下,BlockCache和Memstore的配置各站40%,可以通过在hbase-site.xml配置以下属性来实现:

  • hfile.block.cache.size,默认0.4,用来提高读性能
  • hbase.regionserver.global.memstore.size,默认0.4,用来提高写性能

本篇博客主要介绍提高读性能,这里我们可以将BlockCache的占比设置大一些,Memstore的占比设置小一些(总占比保持在0.8即可)。另外,BlockCache的策略选择也是很重要的,不同的策略对于读性能来说影响不大,但是对于GC的影响却比较明显,在设置hbase.bucketcache.ioengine属性为offheap时,GC表现的很优秀。缓存结构如下图所示:

设置BlockCache可以在hbase-site.xml文件中,配置如下属性:

<!-- 分配的内存大小尽可能的多些,前提是不能超过 (机器实际物理内存-JVM内存) -->
<property>  <name>hbase.bucketcache.size</name>  <value>16384</value> 
</property>
<property><name>hbase.bucketcache.ioengine</name><value>offheap</value> 
</property>

设置块内存大小,可以参考入下表格:

标号描述计算公式或值结果
A物理内存选择:on-heap(JVM)+off-heap(Direct)单台物理节点内存值,单位MB262144
BHBASE_HEAPSIZE('-Xmx)单位MB20480
C-XX:MaxDirectMemorySize,off-heap允许的最大内存值A-B241664
Dphfile.block.cache.size和hbase.regionserver.global.memstore.size总和不要超过0.8读取比例占比*0.80.5*0.8=0.4
DmJVM Heap允许的最大BlockCache(MB)B*Dp20480*0.4=8192
Ephbase.regionserver.global.memstore.size设置的最大JVM值0.8-Dp0.8-0.4=0.4
F用于其他用途的off-heap内存,例如DFSClient推荐1024到20482048
GBucketCache允许的off-heap内存C-F241664-2048=239616

另外,BlockCache策略,能够有效的提高缓存命中率,这样能够间接的提高热数据覆盖率,从而提升读取性能。

2.2.3 HFile优化

HBase读取数据时会先从BlockCache中进行检索(热数据),如果查询不到,才会到HDFS上去检索。而HBase存储在HDFS上的数据以HFile的形式存在的,文件如果越多,检索所花费的IO次数也就必然增加,对应的读取耗时也就增加了。文件数量取决于Compaction的执行策略,有以下2个属性有关系:

  • hbase.hstore.compactionThreshold,默认为3,表示store中文件数超过3个就开始进行合并操作
  • hbase.hstore.compaction.max.size,默认为9223372036854775807,合并的文件最大阀值,超过这个阀值的文件不能进行合并

 另外,hbase.hstore.compaction.max.size值可以通过实际的Region总数来计算,公式如下:

hbase.hstore.compaction.max.size = RegionTotal / hbase.hstore.compactionThreshold

2.2.4 Compaction优化

Compaction操作是将小文件合并为大文件,提高后续业务随机读取的性能,但是在执行Compaction操作期间,节点IO、网络带宽等资源会占用较多,那么什么时候执行Compaction才最好?什么时候需要执行Compaction操作?

1.什么时候执行Compaction才最好?

实际应用场景中,会关闭Compaction自动执行策略,通过属性hbase.hregion.majorcompaction来控制,将hbase.hregion.majorcompaction=0,就可以禁止HBase自动执行Compaction操作。一般情况下,选择集群负载较低,资源空闲的时间段来定时调度执行Compaction。

如果合并的文件较多,可以通过设置如下属性来提生Compaction的执行速度,配置如下:

<property><name>hbase.regionserver.thread.compaction.large</name><value>8</value><description></description>
</property>
<property><name>hbase.regionserver.thread.compaction.small</name><value>5</value><description></description>
</property>

2.什么时候需要执行Compaction操作?

一般维护HBase集群后,由于集群发生过重启,HBase数据本地性较低,通过HBase页面可以观察,此时如果不执行Compaction操作,那么客户端查询的时候,需要跨副本节点去查询,这样来回需要经过网络带宽,对比正常情况下,从本地节点读取数据,耗时是比较大的。在执行Compaction操作后,HBase数据本地性为1,这样能够有效的提高查询效率。

3.总结

本篇博客HBase查询优化从客户端和服务端角度,列举一些常见有效地优化手段。当然,优化还需要从自己实际应用场景出发,例如代码实现逻辑、物理机的实际配置等方面来设置相关参数。大家可以根据实际情况来参考本篇博客进行优化。

4.结束语

这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

另外,博主出书了《Hadoop大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。

转载于:https://www.cnblogs.com/smartloli/p/9425343.html

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

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

相关文章

NEC SV8100电话交换机配置梓博电话计费系统

为了节约办公成本&#xff0c;规范电话使用。公司最近为NEC SV8100电话交换机系统上线了一套梓博的电话计费系统。先将配置过程分享给各位。 1、登录电话交换机系统&#xff08;默认用户名tech、密码12345678&#xff09; 2、点击系统数据配置按钮 2、通过10-01选项调整电话交换…

判断闰年 php,PHP怎么判断一年是否为闰年?

判断是否为闰年的条件是满足下列二者条件之一&#xff1a;年号能被4整除、但不能被100整除&#xff0c;二是年号能被4整除&#xff0c;又能被400整除。那么PHP怎么判断一年是否为闰年&#xff1f;下面本篇文章就来给大家介绍一下使用PHP判断一年是否为闰年的方法&#xff0c;希…

redis desktop manager_面试官:Redis分布式锁如何解决锁超时问题?

Java面试笔试面经、Java技术每天学习一点Java面试关注不迷路作者&#xff1a;wangzaiplus来源&#xff1a;https://www.jianshu.com/u/8cb4591440ca一、前言关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完…

python print 换行_Python学习 | Python的基础语法

Python 语言与 Perl&#xff0c;C 和 Java 等语言有许多相似之处。但是&#xff0c;也存在一些差异&#xff0c;编写Paython程序之前需要对语法有所了解&#xff0c;才能编写规范的Python程序。一、行和缩进Python最大的特点之一就是Python 的代码块不使用大括号 {}了&#xff…

python 创建文件_Python入学首次项目,新手必看,简单易操作

继昨天文章python软件pycharm安装教程之后&#xff0c;今天则给新手小白们分享一哈&#xff0c;怎么制作并创建文件。print “hello world”&#xff1b;如后期需要资料文件的则可以私信留言&#xff0c;领取首次项目资料。本节知识点&#xff1a;python项目的创建pycharm的使用…

ajax跨域实现

2019独角兽企业重金招聘Python工程师标准>>> 我们都知道ajax是不能跨域的&#xff0c;那么怎么实现ajax跨域呢&#xff1f; 看了看jquery&#xff0c;当然&#xff0c;jquery封装的很好&#xff0c;$.ajax就可以实现跨域&#xff0c;只需要在参数中配置一下即可&am…

python leetcode_leetcode 刷题经验,主力 python

1. 树的先序遍历可以求高度&#xff0c;后序遍历可以求深度。剑指 Offer 55 - II. 平衡二叉树​leetcode-cn.com2. 二叉搜索树的中序遍历可以递增地返回所有元素。逆序的中序遍历&#xff08;即先右子节点&#xff0c;再根节点&#xff0c;再左子节点&#xff09;可以递减的返回…

sqlldr 导入乱码,Oracle客户端字符集问题

2019独角兽企业重金招聘Python工程师标准>>> 1&#xff0c;查Oracle数据库创建时候的字符集&#xff1a; Oracle服务器端执行 SQL> select name, value$ from sys.props$ where name like NLS%; NAME VALUE$ ------------------------------ -------------------…

Python在mysql中进行操作是十分容易和简洁的

首先声明一下&#xff0c;我用的是Windows系统&#xff01; 1、在Python中对mysql数据库进行操作首先要导入pymysql模块&#xff0c;默认情况下&#xff0c;Python中是没有安装这个模块的&#xff0c; 可以在Windows的命令行中用pip install pymysql来安装&#xff08;注意要连…

讲php fpm的书,细说PHP-fpm

最近在研究PHP的源码&#xff0c;有时候会延伸到很多东西。这里就专程找了下php-fpm的内容学习下。是什么&#xff1f;在理解php-fpm之前&#xff0c;我们要先搞清楚几个关键词以及他们之间的关系:CGIFastCGIphp-fpmphp-cgi.CGI:(Common Gateway Interface)&#xff0c;即通用网…

安卓微软雅黑字体ttf_618巨献丨精致的悦黑5字重小字体

悦黑字体简介去年双十一当天&#xff0c;小编应大家要求&#xff0c;分享了一款悦黑小字体&#xff0c;苹果和安卓都有&#xff1a;双十一巨献&#xff1a;令人瑟瑟发抖的5字重悦黑小字体大半年时间过去了&#xff0c;一直没有更新&#xff0c;今天抽空更新一下。悦黑是由造字工…

伪静态隐藏域名后缀_你想知道的动态URL、静态URl、伪静态URL概念及区别都在这里!...

【小宅按】我们说url的动态、静态、伪静态三种形式&#xff0c;其实从严格分类上来说&#xff0c;伪静态也是动态的一种&#xff0c;只是表现形式为静态。参考&#xff1a;动态url、静态url和伪静态url的详细讲解 - 好文分享动态URl动态页面的特征1、以ASP、PHP、JSP、ASP.NET …

700多位老人的“智慧”养老记

“智慧”养老&#xff0c;受益的不只是居住养老公寓的老年人&#xff0c;养老机构本身也受益匪浅。 2012年12月&#xff0c;由汇晨养老公司机构管理有限公司(简称汇晨养老公司)与NEC中国共同开发的智能老年公寓信息化系统投入运行&#xff0c;生活在北京昌平区北七家汇晨老年公…

docker 安装nginx_docker安装nginx搭建简单文件共享服务

使用nginx开启目录浏览功能&#xff0c;实现简单的http文件共享服务。一、 首先拉取nginx镜像&#xff0c;我使用的是arm32v7/nginx镜像。docker pull arm32v7/nginx二、运行一个临时的nginx实例&#xff0c;复制容器内的nginx.conf配置文件到主机上docker run --name tmp-ngin…

java _web之Servlet简单应用

Servlet是一种独立于平台和协议的服务器端的Java应用程序&#xff0c;可以生成动态的web页面。它担当Web浏览器或其他http客户程序发出请求、与http服务器上的数据库或应用程序之间交互的中间层。 所谓动态网页&#xff0c;就是在不同时刻或不同条件下访问Web服务器上的同一个页…

mysql redis hbase_MySQL之基本介绍

MySQL基本介绍在学习任何一款编程语言的过程中&#xff0c;我们会发现如果我们想要存储一些数据到本地硬盘的时候无疑是有些麻烦的。今天&#xff0c;我们就学一个和储存数据有关的数据库管理系统——MySQL。为啥要学会使用数据库呢&#xff1f;因为数据库可以方便的将数据存放…

linux mysql 修改root密码_Mac下重置mysql的root密码

php中文网最新课程每日17点准时技术干货分享我的mysql版本 MYSQL V5.7.9&#xff0c;旧版本请使用&#xff1a;UPDATE mysql.user SET PasswordPASSWORD(新密码) WHERE Userroot;Mac OS X - 重置 MySQL Root密码密码太多记不住&#xff1f;&#xff1f;你是否忘记了Mac OS 的My…

DHCP option 150与option 66的区别

转载于:https://blog.51cto.com/jaymimijay/1150777

python期末知识点_史上最全的Python知识点整理之基本语法

一、程序的格式框架 1.缩进 缩进是指每行语句前的空白区域&#xff0c;用来表示Python程序间的包含和层次关系。 一般语句不需要缩进&#xff0c;顶行书写且不留空白。 当表示分支、循环、函数、类等含义&#xff0c;在if&#xff0c;while&#xff0c;for&#xff0c;def&…

php网页多个倒计时,怎么实现一个页面有多个倒计时同时进行

后台返回时间&#xff0c;一个页面中有多个表格每个表格中有一行用来显示后台给的时间&#xff0c;比如说后台给一号表格10分钟的倒计时时间&#xff0c;给2号表格15分钟的倒计时时间&#xff0c;那我要怎么做才能使得这两个倒计时都能进行&#xff1f;&#xff1f;我自己模拟了…