hbase怎么读(hbase数据库)

牵着乌龟去散步 怎么读 7

大家好,今天来为大家分享hbase怎么读的一些知识点,和hbase数据库的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!

本文目录

  1. 如何加快hbase读取数据的效率
  2. HBase 写 *** 能优化
  3. Hbase读写原理

一、如何加快hbase读取数据的效率

业务上目前主要计算逻辑的数据源是hbase,但是我们没有工具对hbase的数据进行单条更改造数据来验证逻辑,之前的做法是把hbase的数据都导出来,改完再重新载入回去,或使用hbase shell接口进行更改(有一个 *** 就是hbase shell get出来的数据汉字是看不出来的),效率低,也不便于自动化的回归。测试非常的被动。

于是在师姐的建议下期望有 *** 作hbase数据的工具来提高我们的效率,及大数据的验证。

工具使用j *** a编写的jar包,在ihbase.sh进行简单数据处理对jar包进行调用。主要功能为数据的增删改查,支持gbk,utf8编码。通过配置一个xml格式的配置文件(也可以不配置)。

1.properties.sh:在里面配置hbase,hadoop等环境变量,里面目前默认是我们测试集群的配置作为参考。注意一些基础的jar包一定要有。

2.config:xml格式的配置hbase导出数据的信息。在海量导出数据或根据rowkey到处数据的时候使用。

1../ihbase–t table_name-rowkey rowkey-enc encoding-s

-enc encoding这个的目的是指定以什么编码读出hbase数据,目前支持utf8,gbk。如果不加该参数则默认以utf读出。

查看表名为table_name,rowkey为rowkey的数据。

2../ihbase–t表名–k CF:COLUMN=value–k CF:COLUMN=value–w column-s

./ihbase.sh–t"test"–k"a:name=jkfs"–k"a:id=111"-w"nid"-s

查询满足a:name=jkfs且a:id=111的记录,若加上-w参数,则只显示-w传进去的列。若不加-w显示所有列。

(这个命令一般很少用,因为使用这个=的filer需要扫hbase全表,因为这种方式很少使用,所以暂时没考虑如何优化)

1../ihbase–t table_name–rowkey rowkey–delete

2../ihbase–t table_name–k CF:COLUMN=value–k CF:COLUMN=value–delete

./ihbase–t test–k"a:id=jaks"-k"name=a:jkasj"-delete

删除满足a:id=jaks且a:name=jkasf的数据(目前支持and进行删除,不支持or,原理同该方式的查询)

./ihbase–t table_name–rowkey rowkey–v CF:COLUMN=value–v CF:COLUMN=value-a

./ihbase.sh–t"a:test"-rowkey"111"–v"a:name=jkfs"–v"id=111"-a

添加rowkey为111的数据,后面key,value可以任意指定。如果rowkey已经存在,则报错不进行添加。

1../ihbase–t table_name–rowkey rowkey–v key=value-v key=value-u

./ihbase.sh-t"test"-rowkey"1111"–v"name=jkasjd"-u

根据rowkey进行修改一条记录的列数据

2../ihbase–t table_name–k key=value–k CF:COLUMN=value-v CF:COLUMN=value-u

./ihbase.sh–t test–k"a:name=jksdj"–k"mge=kjdk"–v"a:name=huanyu"-u

根据非rowkey进行修改,-k提供修改的条件,-u提供要修改的列的数数据。(原理同查询,scan全表)

五.导出hbase指定列的数据(所有数据)

./ihbase-f config此处有一个 *** :就是导出表的配置文件必须放在bin的目录下。如果不喜欢这样也可以修改ihbase脚本进行调整。

config为配置导出表信息的xml配置

<in_enc>gbk</in_enc>

<out_enc>utf8</out_enc>

<tablename>test</tablename>

<field_separator>&# *** ;001</field_separator>

<record_separator>&# *** ;002</record_separator>

<outpath>/test/huanyu/hbase</outpath>

in_enc:hbase中的编码,以解析hbase中数据使用的编码。

out_enc:输出到hdfs路径上的编码。

field_separator:如果导出多个字段则作为多个字段间的分隔符。

record_separator:导出数据的行分隔符。(除了&# *** ;n的字符,因为默认会分行)。

column:导出的字段。如果不存在该字段则导出''。

outpath:导出数据的路径。(其实应在代码中把这个路径先删除的,但是怕用户忘记修改路径误删除,所以没有这么做)

六.导出hbase指定行的指定列的数据

config里面配置导出的列,字符编码表名等信息。

rfile配置导出哪些rowkey的数据。(一个rowkey一行)

二、HBase 写 *** 能优化

上一篇文章主要介绍了HBase读 *** 能优化的基本套路,本篇文章来说道说道如何诊断HBase写数据的异常问题以及优化写 *** 能。和读相比,HBase写数据流程倒是显得很简单:数据先顺序写入HLog,再写入对应的缓存Memstore,当Memstore中数据大小达到一定阈值(128M)之后, *** 会异步将Memstore中数据flush到HDFS形成小文件。

HBase数据写入通常会遇到两类问题,一类是写 *** 能较差,另一类是数据根本写不进去。这两类问题的切入点也不尽相同,如下图所示:

优化原理:数据写入流程可以理解为一次顺序写WAL+一次写缓存,通常情况下写缓存延迟很低,因此提升写 *** 能就只能从WAL入手。WAL机制一方面是为了确保数据即使写入缓存丢失也可以恢复,另一方面是为了集群之间异步 *** 。默认WAL机制开启且使用同步机制写入WAL。首先考虑业务是否需要写WAL,通常情况下大多数业务都会开启WAL机制(默认),但是对于部分业务可能并不特别关心异常情况下部分数据的丢失,而更关心数据写入吞吐量,比如某些推荐业务,这类业务即使丢失一部分用户行为数据可能对推荐结果并不构成很大影响,但是对于写入吞吐量要求很高,不能造成数据队列阻塞。这种场景下可以考虑关闭WAL写入,写入吞吐量可以提升2x~3x。退而求其次,有些业务不能接受不写WAL,但可以接受WAL异步写入,也是可以考虑优化的,通常也会带来1x~2x的 *** 能提升。

优化推荐:根据业务关注点在WAL机制与写入吞吐量之间做出选择

其他注意点:对于使用Increment *** 作的业务,WAL可以设置关闭,也可以设置异步写入, *** 同Put类似。相信大多数Increment *** 作业务对WAL可能都不是那么敏感~

优化原理:HBase分别提供了单条put以及批量put的API接口,使用批量put接口可以减少客户端到RegionServer之间的RPC连接数,提高写入 *** 能。另外需要注意的是,批量put请求要么全部成功返回,要么抛出异常。

优化建议:使用批量put进行写入请求

优化原理:业务如果可以接受异常情况下少量数据丢失的话,还可以使用异步批量提交的方式提交请求。提交分为两阶段执行:用户提交写请求之后,数据会写入客户端缓存,并返回用户写入成功;当客户端缓存达到阈值(默认2M)之后批量提交给RegionServer。需要注意的是,在某些情况下客户端异常的情况下缓存数据有可能丢失。

优化建议:在业务可以接受的情况下开启异步批量提交

优化原理:当前集群中表的Region个数如果小于RegionServer个数,即Num(Region of Table)< Num(RegionServer),可以考虑切分Region并尽可能分布到不同RegionServer来提高 *** 请求并发度,如果Num(Region of Table)> Num(RegionServer),再增加Region个数效果并不明显。

优化建议:在Num(Region of Table)< Num(RegionServer)的场景下切分部分请求负载高的Region并迁移到其他RegionServer;

优化原理:另一个需要考虑的问题是写入请求是否均衡,如果不均衡,一方面会导致 *** 并发度较低,另一方面也有可能造成部分节点负载很高,进而影响其他业务。分布式 *** *** 别害怕一个节点负载很高的情况,一个节点负载很高可能会拖慢整个集群,这是因为很多业务会使用Mutli批量提交读写请求,一旦其中一部分请求落到该节点无法得到及时响应,就会导致整 *** 量请求超时。因此不怕节点宕掉,就怕节点奄奄一息!

优化建议:检查RowKey设计以及预分区策略,保证写入请求均衡。

KeyValue大小对写入 *** 能的影响巨大,一旦遇到写入 *** 能比较差的情况,需要考虑是否由于写入KeyValue数据太大导致。KeyValue大小对写入 *** 能影响曲线图如下:

图中横坐标是写入的一行数据(每行数据10列)大小,左纵坐标是写入吞吐量,右坐标是写入平均延迟(ms)。可以看出随着单行数据大小不断变大,写入吞吐量急剧下降,写入延迟在100K之后急剧增大。

说到这里,有必要和大家分享两起在生产线环境因为业务KeyValue较大导致的严重问题,一起是因为大字段业务写入导致其他业务吞吐量急剧下降,另一起是因为大字段业务scan导致RegionServer宕机。

案件一:大字段写入导致其他业务吞吐量急剧下降

部分业务反馈集群写入忽然变慢、数据开始堆积的情况,查看集群表级别的数据读写QPS *** ,发现问题的之一个关键点:业务A开始写入之后整个集群其他部分业务写入QPS都几乎断崖式下跌,初步怀疑黑手就是业务A。

下图是当时业务A的写入QPS(事后发现 *** 忘了截取其他表QPS断崖式下跌的惨象),但是之一感觉是QPS并不高啊,凭什么去影响别人!

于是就继续查看其他 *** 信息,首先确认 *** 资源(主要是IO)并没有到达瓶颈,其次确认了写入的均衡 *** ,直至看到下图,才 *** 到影响其他业务写入的第二个关键点:RegionServer的handler(配置150)被残暴耗尽:

对比上面两张图,是不是发现出奇的一致,那就可以基本确认是由于该业务写入导致这台RegionServer的handler被耗尽,进而其他业务拿不到handler,自然写不进去。那问题来了,为什么会这样?正常情况下handler在处理完客户端请求之后会立马释放,唯一的解释是这些请求的延迟实在太大。

试想,我们去汉堡店排队买汉堡,有150个窗口服务,正常情况下大家买一个很快,这样150个窗口可能只需要50个服务。假设忽然来了一批大汉,要定制超大汉堡,好了,所有的窗口都工作起来,而且因为大汉堡不好 *** 导致服务很慢,这样必然会导致其他排队的用户长时间等待,直至超时。

可回头一想这可是写请求啊,怎么会有这么大的请求延迟!和业务方沟通之后确认该表主要存储语料库文档信息,都是平均100K左右的数据,是不是已经猜到了结果,没错,就是因为这个业务KeyValue太大导致。KeyValue太大会导致HLog文件写入频繁切换、flush以及compaction频繁触发,写入 *** 能急剧下降。

目前针对这种较大KeyValue写入 *** 能较差的问题还没有直接的解决方案,好在社区已经意识到这个问题,在接下来即将发布的下一个大版本HBase 2.0.0版本会针对该问题进行深入优化,详见 HBase MOB,优化后用户使用HBase存储文档、 *** 等二进制数据都会有极佳的 *** 能体验。

案件二:大字段scan导致RegionServer宕机

案件现场:有段时间有个0.98集群的RegionServer经常频繁宕机,查看日志是由于”j *** a.lang.OutOfMemoryError: Requested array size exceeds VM limit”,如下图所示:

原因分析:通过查看源码以及相关文档,确认该异常发生在scan结果数据回传给客户端时由于数据量太大导致申请的array大小超过JVM规定的更大值( Interge.Max_Value-2)。造成该异常的两种最常见原因分别是:

有的童鞋就要提问啦,说如果已经对返回结果大小做了 *** ,在表列太宽的情况下是不是就可以不对列数量做 *** 呢。这里需要澄清一下,如果不对列数据做 *** ,数据总是一行一行返回的,即使一行数据大小大于设置的返回结果 *** 大小,也会返回完整的一行数据。在这种情况下,如果这一行数据已经超过array大小阈值,也会触发OOM异常。

解决方案:目前针对该异常有两种解决方案,其一是升级集群到1.0,问题都解决了。其二是要求客户端访问的时候对返回结果大小做 *** (scan.setMaxResultSize(2 1024 1024))、并且对列数量做 *** (scan.setBatch(100)),当然,0.98.13版本以后也可以对返回结果大小在服务器端进行 *** ,设置参数hbase.server.scanner. *** x.result.size即可

上述几点主要针对写 *** 能优化进行了介绍,除此之外,在一些情况下还会出现写异常,一旦发生需要考虑下面两种情况(GC引起的不做介绍):

问题解析:以RegionServer级别flush进行解析,HBase设定一旦整个RegionServer上所有Memstore占用内存大小总和大于配置文件中upperlimit时, *** 就会执行RegionServer级别flush,flush算 *** 首先按照Region大小进行排序,再按照该顺序依次进行flush,直至总Memstore大小低至lowerlimit。这种flush通常会block较长时间,在日志中会发现“Memstore is above high water *** rk and block 7452 ms”,表示这次flush将会阻塞7s左右。

问题解析:对于数据写入很快的集群,还需要特别关注一个参数:hbase.hstore.blockingStoreFiles,此参数表示如果当前hstore中文件数大于该值, *** 将会强制执行compaction *** 作进行文件合并,合并的过程会阻塞整个hstore的写入。通常情况下该场景发生在数据写入很快的情况下,在日志中可以发现”Waited 3722ms on a compaction to clean up‘too *** ny store files“

上文已经从写 *** 能优化以及写异常诊断两个方面对HBase中数据写入可能的问题进行了详细的解释,相信在0.98版本的基础上对写入来说已经是更好的解决方案了。但是有些业务可能依然觉得不够快,毕竟”更快”是所有存储 *** 活着的动力,那还有提高空间吗?当然,接下来简单介绍HBase之后版本对写 *** 能优化的两点核心改进:

这个特 *** 意味着可以将WAL单独置于SSD上,这样即使在默认情况下(WALSync),写 *** 能也会有很大的提升。需要注意的是,该特 *** 建立在HDFS 2.6.0+的基础上,HDFS以前版本不支持该特 *** 。具体可以参考官方jira:

该特 *** 也是对WAL进行改造,当前WAL设计为一个RegionServer上所有Region共享一个WAL,可以想象在写入吞吐量较高的时候必然存在资源竞争,降低整体 *** 能。针对这个问题,社区小伙伴(阿里巴巴大神)提出Multiple WALs机制,管理员可以为每个Namespace下的所有表设置一个共享WAL,通过这种方式,写 *** 能大约可以提升20%~40%左右。具体可以参考官方jira:

三、Hbase读写原理

不同列族分别存在不同的文件夹里。

首先Hbase是依赖于HDFS和zookeeper的。

Zookeeper分担了H *** ster的一部分功能,客户端进行DML语句的时候,都是先跟ZK交互。

RegionServer管理了很多的Region(表),RegionServer里面的WAL(HLog)是预写入日志,功能是防止内存中的数据没有来的及落盘时丢失。在Region里面管理的Store管理的是列族,Store里面有Mem Store(内存),Flush之后,删除内存中的数据,同时写入文件StoreFile Hfile,Hfile其实是在DataNode里面的。

Hbase命名空间下有一张元数据表meta表和namespace表。meta表里面保存了要 *** 作的表所在的位置等元数据。

(1)首先客户端向zk请求元数据表所在的RegionServer,zk返回给客户端meta表所在的regionServer。

(2)然后客户端再去对应的RegionServer查找meta表,找到真正要 *** 作的表所在的regionServer,同时把meta表的信息缓存下来,加快后续的查询。

(3)然后客户端再向目标表所在的RegionServer发送put请求。先把数据写到Hlog里面,再写到内存MemStore,数据会在内存排序,然后向客户端发送ack,到这里对于客户端来说写数据已经结束了。再等到MemStore的刷写时机后,将数据刷写到Hfile.

注:meta表所在的位置信息保存在zk的meta-region-server节点上,客户端首先就是在这个节点上差询meta表所在的RegionServer。meta表里面的信息就是表与其对应的RegionServer的信息

这个stu表可能不止一条,因为stu表可能数据量大了之后根据RowKey进行了切分,并且可能会在不同的机器上。

全局的MemStore的容量,默认是堆内存的40%。这个容量值会触发flush *** 作,所有的MemStore都要刷写,flush *** 作会阻塞读写 *** 作。

会刷写并阻塞到到MemStore大小降到它的更大容量的95%

可以设置日志的大小和数量,当达到一定数量,刷写到HDFS

(1)从zk找meta表所在的RegionServer

(2)从上述RegionServer里的meta表里找目标表所在的RegionServer,同时把meta表缓存,加速后面的查询。

(3)向目标表所在的RegionServer发送get请求。可以从block Cache,MemStore还有StoreFile里面查,具体从哪查根据时间戳,查时间戳大的,具体就都查然后merge取最新。

RegionServer里面有block Cache可以缓存磁盘的数据,加速查询。如果block Cache里面有,就将缓存和MemStore的数据merge然后取最新时间戳,没有就是把磁盘读的和MemStore里面的合并。所以hbase大多数读要走磁盘,所以读很慢。

每次刷写会生成新的Hfile,Hfile很小并且数量多的时候会影响查询的速度。所以要进行合并。合并分为minor Compaction和 *** jor Compaction

minor Compaction将临近的若干较小的Hfile合并成一个较大的Hfile,不会清理过期和删除的数据, *** jor Compaction会将一个Store里面的所有Hfile合并成一个大的Hfile,并且会清理掉过期和删除的数据。

数据的读写可以不依赖H *** ster,只需要指定zookeeper,但是H *** ster负责region调度的元数据

(1)flush在同一个内存中清除过期或删除(删除标记也是一行数据)的数据,但是如果数据不同的版本分布在不同的memStroe,就不能清除。删除的标记在flush之后不会被删,但在后面的 *** jor compaction会把删除标记删除掉。

(2) *** jor compaction会清除过期或删除的数据。

默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动拆分,两个子Region开始都会在一个Regionserver里面,但是出于负载均衡的考虑,H *** ster有可能会将某个Region传给其他的RegionServer。

(1)当一个Region中的某个Store下的StoreFile的总大小查过某个值,由参数hbase.hregion. *** x.filesize设定(默认10g),该Region就会按照RowKey进行拆分。

(2)在新版本中这个值是Min(R^2*"hbase.hregion.memStore.flush.size(128M)","hbase.hregion. *** x.filesize"),R是当前RegionServer中属于该Table的Region个数。分region是按照RowKey切分的。这会导致数据倾斜,就是因为切分的阈值在变化,导致切分之后的region数据量不均匀,导致热点的问题。所以在建表的时候要做预分区,就是用RowKey规划好多少个region,不让hbase自己的切分逻辑切分。

官方建议只用一个列族,防止不同的列族之间数据不均匀,单一列族数据量增多,导致全局的flush,数据量小的列族也要flush,这样会形成很多小的storeFile。

(1)设置RowKey:打的删除标记是deleteFamily,删除多个版本

(2)设置RowKey+Family:打的标记是deleteFamily,删除多个版本

(3)设置RowKey+family+column:有addColumn()和addColumns().addColumn是删除最新的版本或者删除指定时间戳的版本,删除标记是delete标记。addColumns是删除所有的版本或者删除指定时间戳或之前的版本,删除标记是deleteColumn

Delete的 *** 作其实也是put *** 作,put的是删除的标记。

在Hbase中HMaster负责 *** HRegionServer的生命周期,均衡RegionServer的负载,如果HMaster挂掉了,那个整个Hbase集群将处于不健康的状态,并且此时的工作状态不会维持太久。所以Hbase支持对HMaster的高可用配置。

在Hbase的conf目录下新建backup- *** sters文件,vim加入备份Master,比如sl *** e01,sl *** e02.在把文件分发到各个sl *** e里,然后再启动hbase就能实现HMaster的高可用了。

每一个region维护着StartRow和EndRow,如果加入的数据符合某个region维护的RowKey范围,则该数据交给这个region维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高Hbase *** 能。

(3)按照文件中设置的规则预分区

这里如果文件里面给的分区键不是按照顺序的,hbase会先帮我们把键排序,然后按照键来分区。

admin的创建表的 *** 有多个重载,可以只传表的描述,也可以加入分区的信息。admin.createTable

规划分区要考虑未来数据量和机器的规模。虽然提前做了分区,但是最后如果分区大于了10G,还是会触发split。假设一台机器有100G磁盘,那么预分区尽量大于10个,这样就能避免预分区之后又触发了大于10G的split。

(1)希望数据能够尽量均匀的分配在多个分区里面(散列 *** )。

(3)长度原则(生产环境70到100位)

hbase怎么读(hbase数据库)-第1张图片-

一次通话的记录:13112341233-> *** 98768771 2018-12-12 12:12:21 568

RowKey的前面一般会拼上000_,001_,...,298_

这样做的好处是,根据前三位就能知道哪个分区。

(1)我们希望 *** 号尽量分布在不同的分区,但是相同的 *** 号数据集中在同一个分区,这样方便查询某个用户的通话信息。000_13112341233

(2)因为每个人通话的需求不同,也希望把同一个人的通话记录也分布在不同的分区里面。000_13112341233_2019-12-12

哈希取余:[(13112341234^201912).hash]%299

假设要查询某用户2019年2月的通话记录,可以用13112341234 201902做startRowkey,13112341234 201903做endRowKey

(2)用户社交:关注用户,取关用户

因为正常情况一个用户的粉丝和关注都不多,可以用一行存储关注和粉丝的情况。

(3)初始化页面的表(显示关注的人的最近三条微博)

关于hbase怎么读和hbase数据库的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签: hbase 数据库 怎么

抱歉,评论功能暂时关闭!