Hbase写数据,存数据,读数据的详细过程 分类: B7_HBASE 2015-03-15 20:11 117人阅读 评论(0) 收藏

Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增加到必定阈值 -> 出发Compact合并操做 -> 多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除 -> 当StoreFiles Compact后,逐步造成愈来愈大的StoreFile -> 单个StoreFile大小超过必定阈值后,触发Split操做,把当前Region Split成2个Region,Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer 上。

Hbase写数据和存数据的过程

Hbase写数据,存数据,读数据的详细过程

 

Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增加到必定阈值 -> 出发Compact合并操做 -> 多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除 -> StoreFiles Compact后,逐步造成愈来愈大的StoreFile -> 单个StoreFile大小超过必定阈值后,触发Split操做,把当前Region Split2RegionRegion会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer 上,使得原先1Region的压力得以分流到2Region上由此过程可知,HBase只是增长数据,有所得更新和删除操做,都是在Compact阶段作的,因此,用户写操做只须要进入到内存便可当即返回,从而保证I/O高性能。算法

对上述流程的补充:

补充1HStore存储是HBase存储的核心,其中由两部分组成,一部分是MemStore,一部分是StoreFiles数据库

补充2HLog的功能:缓存

在分布式系统环境中,没法避免系统出错或者宕机,一旦HRegionServer之外退出,服务器

MemStore中的内存数据就会丢失,引入HLog就是防止这种状况。多线程

工做机制:每 个HRegionServer中都会有一个HLog对象,HLog是一个实现Write Ahead Log的类,每次用户操做写入Memstore的同时,也会写一份数据到HLog文件,HLog文件按期会滚动出新,并删除旧的文件(已持久化到 StoreFile中的数据)。当HRegionServer意外终止后,HMaster会经过Zookeeper感知,HMaster首先处理遗留的 HLog文件,将不一样regionlog数据拆分,分别放到相应region目录下,而后再将失效的region(带有刚刚拆分的log从新分配,领取到这些region的 HRegionServerLoad Region的过程当中,会发现有历史HLog须要处理,所以会Replay HLog中的数据到MemStore中,而后flushStoreFiles完成数据恢复。分布式

补充3Region就是StoreFilesStoreFiles里由HFile构成,Hfile里由hbasedata块构成,一个data块里面又有不少keyvalue对,每一个keyvalue里存了咱们须要的值。性能

补充4测试

Hbase写数据,存数据,读数据的详细过程

咱们观察上面这一幅图:优化

一 张表,有两个列族(红颜色的一个,黄颜色的一个),一个列族有两个列,从图中能够看出,这就是列式数据库的最大特色,同一个列族的数据在在一块儿的,咱们还 发现若是是有多个版本,同时也会存多个版本。最后咱们还发现里面存了这样的值:r1:键值,cf1:列族的名字,c1:列明。t1:版本号,value值 (最后一幅图说明的是value值能够存放的位置)。经过这样的见解,咱们发现若是咱们设计表的时候把这几个东西:r1:键值,cf1:列族的名 字,c1:列明的名字取短一点是否是咱们会省出好多存储的空间!spa

还有,咱们从这一幅图中还应该获得这样的认识

我 们看倒数第二张图,字段筛选的效率从左到右明显降低,因此在keyvalue的设计时用户能够考虑把一些重要的筛选信息左移到合适的位置,从而在不改变数 据量的状况下,提升查询性能。那么简单的说就是用户应当尽可能把查询维度或信息存储在行健中,由于它筛选数据的效率最高。

获得上面的认识后,咱们应该还要会有这样的觉悟:

HBase 的数据存储时会被有顺序的存储到一个特定的范围,由于咱们存储的时候通常都是按顺序的,因此会一直存到同一个region上,因为一个region只能由 一个服务器管理,这样咱们总是添加到同一个region上,会形成读写热点,从而使集群性能降低。那么解决这个的办法仍是有的,我能想到的就是,好比咱们 有9台服务器,那么咱们就回去当前时间,而后摸9,加到行健前缀,这样就会被平均的分到不一样的region服务器上了,这样带来的好处是,由于相连的数据 都分布到不一样的服务器上了,用户能够多线程并行的读取数据,这样查询的吞吐量会提升。

关于咱们版本的控制,咱们要么就让多台服务器上的时间都同步,要么干脆就在put插入数据的时候,就设置一个客户端的时间戳来代替。(由于咱们要是不显示的添加,人家就给咱们在本身的服务器上添加了本身的时间了。)

补充5:

设 计表的时候,有两种设计方式,一种是高表设计,一种是胖表设计。根据HBase的拆分规则,咱们的高表设计更容易拆分(使用组合键),不过,若是咱们设计 成胖表,而咱们的这个胖里的数据须要常常修改,这样设计是很合理的,由于咱们的HBase保证了行级的原子性,若是设计成高表,反而就不合适了,由于不能 保证跨行的原子性。

补充6:

写缓存

每 一个put的操做其实是RPC的操做,它将客户端的数据传送到服务器而后返回,这只适合小数据量的操做,若是有个应用程序须要每秒存储上千行数据到 HBase表中,这样处理就不太合适了。HBase的API配备了一个客户端的写缓冲区,缓冲区负责收集put操做,而后调用RPC操做一次性将put送 往服务器。默认状况下,客户端缓冲区是禁止的。能够经过自动刷写设置为FALSE来激活缓冲区。 table.setAutoFlush(false);void flushCommits () throws IOException这个方法是强制 将数据写到服务器。用户还能够根据下面的方法来配置客户端写缓冲区的大小。 void setWritaeBufferSize(long writeBufferSize) throws IOException;默认大小是 2MB,这个也是适中的,通常用户插入的数据不大,不过若是你插入的数据大的话,可能要考虑增大这个值。从而容许客户端更高效地必定数量的数据组成一组通 过一次RPC请求来执行。给每一个用户的HTable设置一个写缓冲区也是一件麻烦的事,为了不麻烦,用户能够在

Hbase-site.xml中给用户设置一个较大的预设值。

<property>

<name>hbase.client.write.buffer</name>

<value>20971520</value>

</property>

补充7:

hbase支持大量的算法,而且支持列族级别以上的压缩算法,除非有特殊缘由,否则咱们应该尽可能使用压缩,压缩一般会带来较好的 性能。经过一些测试,咱们推荐使用SNAPPY这种算法来进行咱们hbase的压缩。

Hbase读数据:

client->zookeeper->.ROOT->.META-> 用户数据表zookeeper记录了.ROOT的路径信息(root只有一个region),.ROOT里记录了.META的region信息, (.META可能有多个region),.META里面记录了region的信息。

补充1:

在 HBase中,全部的存储文件都被划分红了若干个小存储块,这些小存储块在get或scan操做时会加载到内存中,他们相似于RDBMS中的存储单元页。 这个参数的默认大小是64K。经过以上方式设置:void setBlocksize(int s);(HBase中Hfile的默认大小就是64K跟 HDFS的块是64M不要紧)HBase顺序地读取一个数据块到内存缓存中,其读取相邻的数据时就能够再内存中读取而不须要从磁盘中再次读取,有效地减小 了磁盘I/O的次数。这个参数默认为TRUE,这意味着每次读取的块都会缓存到内存中。可是,若是用户顺序读取某个特定的列族,最好将这个属性设置为 FALSE,从而禁止使用缓存快。上面这样描述的缘由:若是咱们访问特定的列族,可是咱们仍是启用了这个功能,这个时候咱们的机制会把咱们其它不须要的列 族的数据也加载到了内存中,增长了咱们的负担,咱们使用的条件是,咱们获取相邻数据。 void setBlockCacheEnabled(boolean blockCacheEnable);

补充2:

1:禁止自动刷写。

咱们有大批数据要插入时,若是咱们没有禁止,Put实例会被逐个的传送到regio服务器

,若是用户禁止了自动刷写的功能,put操做会在写缓冲区被填满时才会被送出。

2:使用扫描缓存。

若是HBase被用做一个mapreduce做业的输入源,请最好将做为mapreduce做业输入扫描

器实例的缓存用setCaching()方法设置为比默认值1更大的数。使用默认值意味着map

任务会在处理每条记录时都请求region服务器。不过,这个值要是500的话,则一次

可传送500条数据到客户端进行处理,固然了这数据也是根据你的状况定的。

这个是行级的,在咱们的119页有说明。

3:限定扫描范围。

这个是很好理解的,好比咱们要处理大量行(特别是做为mapreduce的输入源),其中

用到scan的时候咱们有Scan.addFamily();的方法,这个时候咱们若是只是须要到

这个列族中的几个列,那么咱们必定要精确。由于过多的列会致使效率的损失。

4:关闭resultScanner

固然了这个不能提升咱们的效率,可是若是没关就会对效率有影响。

5:块缓存的用法

首先咱们的块缓存是经过Scan.setCacheBolcks();的启动的,那些被频繁访问的行

咱们应该使用缓存块,可是mapreduce做业使用扫描大量的行,咱们就不应使用这个

了。(这个块缓存跟我在第四节中提到的那个块是不同的)。

6:优化获取行健的方式

固然用这个的前提是,咱们只须要表中的行健时,才能用。那么怎么用在411页有说明。

7:关闭Put上的WAL

书上是这么说,可是我我的以为这个功能仍是不用的好,由于咱们关闭了这个功能,

服务器就不会把put写入到WAL,而是直接写到memstore里,这样一旦服务器出现故障

咱们的数据就丢失了。

相关文章
相关标签/搜索