大数据之hbase的写数据过程详解

带着问题来寻找答案:
1.HBASE的读写过程就是HBASE的寻址过程
2.如何快速的寻找到地址?
3.为什么hbase可以快速的查询 写入数据?
4.Hbase的数据模型:底层存储的数据到底是怎么样的过程 ?
5.Hbase的数据模型设计:数据文件最终存储在hdfs的结构是怎么样的?并不是key value
客户端发起写数据请求
构建Put对象:一个Put对象代表一行数据记录,可以添加多个列的数据。
如上例所示, RowKey为“012005000201” ,包含3个列:name,gender,address。
Put or PutList?
HBase提供了两个主要的写数据接口,一个可以写入单行数据,即Put接口,另一个可以批量写入多行数据,即PutList接口。事实上, Put仅是PutList的一种特殊情形。因此,后面的流程介绍仅仅涉及PutList。
找region:
如何快速的找到region?
答:找mata表中的metaregion
我们如何快速的找到我的表的元数据信息在meta表中哪个metaregion的位置?
答:zookeeper
Meta表的路由信息:这个表有哪些region 每一个region在哪些位置上
这里写图片描述
不论是读还是写,首先是找region
Metaregion
Userregion
数据
为什么写入数据需要找region而不是直接追加?
mysql:insert操作 新数据直接追加
mysl的寻址过程:一张表对应一个文件,找到表就是找到文件,新数据直接追加在末尾

Habse:
在一张表中,region管理一定范围内的数 rowkey按字典排序
第一个region的start key是空不是0
一张表的不同region可以放到不同的主机中去

Put:数据根据不同的rowkey,插入到不同的region中
当数据量很大时,hbase:meta表也会被拆分成多个 region,称之为metaregion,也可能会被放到不同的主机上,这些metaregion存储的就是某一些表的路由信息,也就是:userregion,region所属的regionserve信息

Regionserver内部按照什么来进行分配数据:rowkey字典排序

数据分组:这里写图片描述
任务交给regionserver之后,regionser做什么?
数据进入的时候,并不是一条一条的进入的,有可能是很多条,比如list一次来10w条数据,
这么大的数据,拿到数据以后,有2种处理方式:
1.每一条数据都要建立一次连接,一条一条的写入数据
2.对数据进行分组,分2次
1分:按照region来分 根据rowkey, 数据分发到不同的region中
2分:存在可能多个region可能在一台主机regionserver的情况,这种情况就会把几个相同主机的region放在一起,方便批量处理 根据region分,分发到不同的regionserver中

打比方:图书馆采购书本
先按书的编号分类
再将已经分类的数据分到不同的楼层,同一楼层,批量处理
往RegionServer发送写数据请求:也就是说在regionser拿到数据前就进行了数据的分这里写图片描述
1.利用HBase自身封装的RPC框架,来完成数据发送操作。往多个RegionServer发送请求是并行操作。
2.客户端发送完写数据请求后,会自动等待请求处理结果。
3.如果客户端没有捕获到任何的异常,则认为所有的数据都已经被写入成功。
4.如果全部写入失败,或者部分写入失败,客户端能够获知详细的失败Key值列表。从这里也可以看出, PutList操作是不保证原子性的。
比如:在mysql中,inseret多条数据,假如最后一条写入失败,所有的数据进行数据回滚,这就是原子性操作
Hbase的原子性:
只能够保证一行的原子性 ,不能保证putlist一次的所有数据原子性,为什么?
因为Habse对于整体数据没有原子性,hbase在put数据时,即使后面的数据put失败,其他的数据还是会正常put进入hdfs,即使再次put相同的数据,hbase数据put自动向下覆盖,即使多次put相同的数据也不影响 ,只有时间戳可能会不同
什么是一行数据的原子性?
假如一行数据中有多个字段,如果不能保证一行数据的原子性,可能会出现部分字段put进hdfs中,这样的情况,这条数据就会出问题,因此一行数据的原子性必须要有保证,put成功,一行数据全部成功,否则put失败

只要第一次的数据进入hdfs开始写入,后面的数据想写失败都很难,为什么?
因为:数据在写的时候,所有的数据,已经进入hbase,完成数据的划分,也就是数组划分,划分到不同的region,region划分到不同的regionserver

如何获取hbase写入hfs之后的回调函数的值?
在这个值,可以获取到哪些数据写入成功,哪些数据写入失败
有那种情况,put了多条数据,但是显示的数量少于put的数量?
字段名相同的时候,也就是同一个cell,时间戳的最大值会覆盖其他的值

Region写数据流程这里写图片描述
这里写图片描述
应用了zookeeper的分布式事务锁的方式:
1.获取region锁 有了这个锁的region,想要获取这个有锁的region的进程必须等待
2.依次获取各行的锁:拿到每一行的锁
3.先将拿到锁的一行数据,写入到memstore中,
4.释放写入完毕的这一行数据的行锁
5.写数据到wal中
6.Memstore和wal都写入以后,释放region锁

Hbase的不同版本,menstore和wal写入的顺序是有差异的
1.0以前的老版本:先写wal,写完了以后再写memstore
新版本:memstore和wal是并行同时写数据,但是由于memstore’是将数据写入内存中,而wal是将数据写入hdfs中,因此memstore写数据的速度要块,因此memstore先于wal结束,释放行锁

为什么数据通过wal已经写入到hdfs中了,还要通过memstore再将数据往 内存中写一次呢?
答:是为了数据的写入和读取的速度块
为什么会有回滚操作机制?
有可能写入到内存成功,但是没有成功的写入到hdfs中,比如hdfs的主机挂掉了,没有写入成功,就不能正常的释放锁,因此就会产生异常,然后启动回滚的操作,将内存的数据也删除
回滚就会可能出现脏读的情况:刷新的速度比释放锁的速度块 ,刷新了就把内存中的数据,立马写入到hdfs中 这个可能大概是千万毫秒分子1
先写memstore再写wal的优缺点?
优点:这条数据没有写入到hdfs中,用户就可以访问了====habse速度快的原因
缺点:脏读

HBase LSM Tree :这里写图片描述
1.将Put/Delete的数据暂时保存在每个Region的内存中,即MemStore中。写内存,避免多Region情形下带来的过多的分散IO操作。
2.数据在写入到MemStore之后,也会顺序写入到HLog中,来保证数据的安全。

为什么delete的数据会保存到我们的memstore中?为什么不是找到数据后直接删掉?
操作Io是如何删除一条数据?
先创建一个新文件,然后将原文件一行一行的拷贝到新文件,当读取到要删除的一条数据时,跳过不读取,继续将剩下的读取到新文件,然后将原文件删除,将新文件的名字改成原文件的名字

逻辑删除:没有真正删除,而是将数据状态改为关闭
物理删除:delete从物理层面删除,删除数据就不存在了
如何选择物理删除?逻辑删除?对后面的业务有没有影响
因为:将delete的数据放在memstore,然后把每一个cell标记为删除,当我们查找数据时,先在memstore中查找,如果发现查找的数据,标记为删除,就不继续进行操作,直接返回给用户,数据不存在
这里写图片描述
存在如下3种场景,会触发一个Region的Flush操作:
1.该Region的MemStore的总大小,达到了预设的Flush Size阈值。这种场景下的Flush操作,当它把memstore中的数据写出到hdfs的hfile文件的时候,在这个时间内,是处于阻塞的状态,此时不允许写入数据到memstore。通常仅瞬间堵塞用户的读写操作。但如果超出预设Flush Size阈值过多的话,也可能会引起较长时间的堵塞。

2.RegionServer的总内存大小超出了预设的阈值大小。这种场景下,在总内存没有降低到预设的阈值以下之前,可能会较长时间堵塞。 比如:总内存可用大小50M,预设置flush值100M,因此50M的时候,就应该要执行flush操作。一般是百分子70,50M的可用空间大小,只有35M的时候,就可以执行flush操作了
3.手动刷新,立马写入hfile

=================因此hfile的大小,很有可能是不一样的

多HFile的影响这里写图片描述
X:产生hfile的数量
Y:所需时间

总结:这里写图片描述
Compaction合并:
这里写图片描述
1.Compaction的主要目的,是为了减少同一个Region同一个ColumnFamily下面的小文件数目,从而提升读取的性能。
2. Compaction分为Minor、 Major两类:
3. Minor:小范围的Compaction。有最少和最大文件数目限制。通常会选择一些连续时间范围的小文件进行合并====小合并
4. Major:涉及该Region该ColumnFamily下面的所有的HFile文件。删除的数据。===大合并
5.Minor Compaction选取文件时,遵循一定的算法。
Memstore写出到hfile文件中,而hfile文件是在hdfs中,但是hdfs系统,不适合大量的小文件,而hbase的写入过程,会产生很多的小文件,比如手动flush和memstore的总内存大小比较小的时候,因此就会产生大量的小文件:hfile 因此。Hbase引入了合并机制,一是目的是为了节约存储空间,同时还有处理过期和被标记为删除的数据
需要删除的数据包含哪些数据?
1.ttl 带有有效期的数据,有效期过来之后,不能被访问,但是仍然存在
2.Put数据:时间戳版本数据数量大于vsrsion可存在的数量
3.需要删除的数据,将数据标记为删除
Major和minor合并的区别有哪些?
1.合并范围不同
小范围:在一定时间内,将多个小文件合并在一起,合并的是一部分发hfile
大范围:将所有的hfile合并
2.功能不同
小范围:只进行整理
大范围:删除只会在大合并的时候执行操作,

一般情况下,不会做大合并!
防止误区:开启大合并,整个hbase的所有的hfile要合并,但是并不是所有的hfile合并成一个hfile,而是一个列族当中的所有的hfile合并成一个hfile,所有的列族开始合并操作

很少做大合并,为什么?
工程量过大
如果一定要大合并呢?
对于某一张表的某些列族,手动执行大合并,不建议开启大合并!!!

为什么不建议开启大合并?
因为在执行大合并的时候,整个hbase的hfile都在参与合并,整个hbase会锁住,此时读数据和写数据都不行
为什么可以做到不执行大合并操作来达到增加空间呢?
因为hbase的底层是hdfs,如果空间不够,可以任意的增加硬盘,增加服务器
Split :这里写图片描述
1.当我们合并之后,region会变的很大,rowkey的范围变的很大,因此错split
2.在region分裂成两个region时,真正的数据没有移动,产生一个新的管理者的时间,比直接把需要移动的数据全部移动过去的时间会少很多,但是需要移动的数据,不可能永远在原region中,因为新region不可能永远的跨服务器去取数据,这样会严重影响我们的查询速度,
Master会做负载均衡操作,会将原region中需要移动的数据,移动到新的region中去,
切分时:A原来的数据,还是在A,只是为了B文件引用,B并没有拿到数据
什么时候给新region数据?
客户端所缓存的父Region的路由信息需要被更新之后,master做负载均衡:将原regionA中需要移动的数据,交给切后出的B 这里的数据是region数据,不是hdfs数据

数据本地化 减少网络连接,提高效率

原来的region,rowkey是空到空,切分了以后,A和B各自管理各自的数据,
新切出的B有数据, 当我们有多台主机的时候,hmaster将父regionA放到A主机中,将子regionB放到B主机中,有什么好处?
假如Aregion的数据存放在hdfs的A主机,在切分的时候,切成时hdfs的数据没有移动,也就是region信息由Bregion来管理,但是hdfs上的数据没有移动到B主机上去

其实,hbase的写分2个步骤:
寻regionserver的过程
Regionserver内部处理过程

猜你喜欢

转载自blog.csdn.net/qq_38025219/article/details/84956627