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,一经查实,立即删除!

相关文章

全国计算机等级考试题库二级C操作题100套(第49套)

第49套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;将形参s所指字符串中所有ASCII码值小于97 的字符存入形参t所指字符数组中&#xff0c;形成一个新串&#xff0c;并统计出符合条件的字符个数 作为函数值返回。 例如&#xff0c;形参s所指的字符串为&…

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分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完…

全国计算机等级考试题库二级C操作题100套(第50套)

第50套&#xff1a; 给定程序中&#xff0c;函数fun的功能是:有NN矩阵&#xff0c;以主对角线为对称线&#xff0c;对称元素相加并将结果存放在左下三角元素中&#xff0c;右上三角元素置为0。例如&#xff0c;若N3&#xff0c;有下列矩阵&#xff1a; 1 2 3 4 5 6 7 8 9 计算…

《CLR via C#》读书笔记 之 参数

第九章 参数 2013-02-27 9.3 以传引用的方式向方法传递参数 默认情况下&#xff0c;CLR假定所有方法参数都是传值的。当传递引用类型的对象时&#xff0c;也默认是传值的&#xff0c;只不过这个值是引用&#xff08;指针&#xff09;本身。 CLR允许以传引用的方式传递参数。在C…

学习笔记整理之模式化方法

第一步 要分清要用那个不变的参数去实现 &#xff08;比如我现在要用 ID进行验证 则&#xff0c;验证完毕后实现的抽象方法的参数是 操作数&#xff0c;所以操作 的方法的参数是操作数&#xff09;先new 个要实现的方法比如 New StudentManger(id,name) 此方法要把继承的抽象的…

php组合查询,PHP组合查询多条件查询实例代码第1/2页

先向大家说明需求&#xff1a;按照我们系统的要求&#xff0c;我们将通过部门名称、员工姓名、PC名称、IP地址等等字段来进行组合查询从而得到想要的数据结果。那么&#xff0c;为了简单起见&#xff0c;我们用两个条件(部门名称、员工姓名)的组合查询来向大家说明这一技术技巧…

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

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

解决linux下source /etc/profile关闭终端失效问题

本来想配置环境变量的&#xff0c;看网上和博客上很多说改/etc/profile&#xff0c;然后source /etc/profile之后就可以永久保存使环境变量生效&#xff0c;但是终端一关闭&#xff0c;就环境变量就失效了&#xff0c;其他终端也用不了。网上有说在当前用户目录下创建.bash_pro…

bind php,PHP – bind_result到数组

我正在为一个返回多个结果的查询使用一个预准备语句,我想在一个数组中使用它.但是bind_result不能用于数组,所以我就是这样做的&#xff1a;$read_items $db->stmt_init();$read_items->prepare("SELECT item_id, item_name FROM items");$read_items->exe…

SQL Server遍历表中记录的2种方法

SQL Server遍历表一般都要用到游标&#xff0c;SQL Server中可以很容易的用游标实现循环&#xff0c;实现SQL Server遍历表中记录。本文将介绍利用使用表变量和游标实现数据库中表的遍历。 表变量来实现表的遍历 以下代码中&#xff0c;代码块之间的差异已经用灰色的背景标记。…

全国计算机等级考试题库二级C操作题100套(第51套)

第51套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;计算出形参s所指字符串中包含的单词个数, 作为函数值返回。为便于统计&#xff0c;规定各单词之间用空格隔开。 例如&#xff0c;形参s所指的字符串为&#xff1a;This is a C language program.&#x…

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

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

php柱形图 数据sql,ThinkPHP 5.1 读取数据库中的图片

如果一个图片直接存在数据库中&#xff0c;可以用以下方法读出来。环境ThinkPHP 5.1 ,sqlsrv&#xff0c;pdo_sqlsrv代码//pdo 方式$pdonew PDO(sqlsrv:Serverlocalhost;DatabaseSD31022_Sample, sa, Sql2008);$stmt$pdo->prepare(select picture from crm_affixinfo where …

Babelfish

题目描述 You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have a dictionary to help you understand them.输入 Input consists of up to 100,000 dictionary entries, follo…

ajax跨域实现

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

全国计算机等级考试题库二级C操作题100套(第52套)

第52套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;将NN矩阵中元素的值按列右移1个位置&#xff0c; 右边被移出矩阵的元素绕回左边。例如&#xff0c;N3&#xff0c;有下列矩阵 1 2 3 4 5 6 7 8 9 计算结果为 3 1 2 6 4 5 9 7 8 请在程序的下划线处填入正…

python leetcode_leetcode 刷题经验,主力 python

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

普及几个小常识,新手技能补充

一&#xff0c;如何设置门户或者论坛为首页&#xff1f;后台界面》导航管理&#xff0c;看向每个导航的最后面&#xff0c;有选择是否设置为首页&#xff0c;选中的即为打开之后的首页。二&#xff0c;如何添加二级导航&#xff0c;后台界面》导航管理&#xff0c;添加二级导航…