Hbase读写流程简要分析

Hbase基本概念:

HBase使用LSM(Log-Structured Merge Tree日志结构合并树)树,用于为那些长期具有很高记录更新(插入或删除)频率的文件提供低成本的索引机制。LSM-Tree通过使用某种算法对索引变更进行延迟及批量处理,并通过一种类似于归并排序的方式联合使用一个基于内存的组件和一个或多个磁盘组件。

与传统访问方式(比如B+树)相比,该算法大大减少了磁盘磁臂的移动次数,同时还会提高那些使用传统访问方式进行插入时,磁盘磁臂开销(寻道+转动)远大于存储空间花费的情况的性价比。但是,对于那些需要立即响应的查找操作来说,某些情况下,它也会损失一些IO效率,因此LSM-Tree最适用于那些索引插入比查找操作更常见的情况。比如,对于历史记录表和日志文件来说,就属于这种情况。

 B+树与LSM-Tree树本质区别

    他们本质不同点在于他们使用现代硬盘的方式,尤其是磁盘。从磁盘使用方面讲,有两种不同的数据库范式:一种是寻道,另一种是传输。RDBMS是寻道型,它需要随机读写数据。

    LSM-Tree则属于传输型,它的原理是把一颗大树拆分成N棵小树, 它首先写入到内存中(内存没有寻道速度的问题,随机写的性能得到大幅提升),在内存中构建一颗有序小树,随着小树越来越大,内存的小树会flush到磁盘上。当读时,由于不知道数据在哪棵小树上,因此必须遍历所有的小树,但在每颗小树内部数据是有序的。

    LSM-Tree工作在磁盘传输速率的级别上,因为它会使用日志文件和一个内存存储结构把随机写操作转换为顺序写。读操作与写操作是独立的,这样这两种操作之间就不会产生竞争。

以上就是LSM树最本质的原理,有了原理,再看具体的技术就很简单了。

1)首先说说为什么要有WAL(Write Ahead Log),很简单,因为数据是先写到内存中,如果断电,内存中的数据会丢失,因此为了保护内存中的数据,需要在磁盘上先记录logfile,当内存中的数据flush到磁盘上时,就可以抛弃相应的Logfile(对于存储系统,最简单的就是把记录直接写到记录文件的末尾,这样的做法写效率是最高的WAL日志是以append形式插入,所以速度非常快)。

2)什么是memstore, storefile?很简单,上面说过,LSM树就是一堆小树,在内存中的小树即memstore,每次flush,内存中的memstore变成磁盘上一个新的storefile。

3)为什么会有compact?很简单,随着小树越来越多,读的性能会越来越差,因此需要在适当的时候,对磁盘中的小树进行merge,多棵小树变成一颗大树。

Hbase基本角色:

客户端Client:

     1.是整个Hbase的集群访问入口;

     2.使用Hbase RPC机制与HMaster和HRegionServer通信;

     3.与HMaster通信进行管理表操作;

    4.与RegionServer进行数据读写操作;

    5.寻址访问Zookeeper,数据读写访问RegionServer

 Zookeeper:

    1.保证任何时候,仅有一个HMaster;

    2.实时监控HRegion Server的上线和下线信息,并实时通知HMaster,让HMaster知道哪些HRegionServere是活的及HRegionServer所在位置,然后管理HRegionServer;

    3.存储Hbase的table元数据;

HMaster:

    1.HMaster没有单点问题,可以启多个HMaster,同Zookeeper的MasterElection机制保证总有一个Master在运行,主要负责Table和Region的管理工作;

    2.管理用户对表的创建、删除等操作;

    3.管理HRegionServer的负载均衡,调整Region分布;

    4.Region split,负载重新分配Region;

HMaster仅仅维护table和region的元数据信息,负载很低;

HRegionServer:

    1.维护Region,处理这些HRegion的IO请求,向HDFS文件系统写数据;

    2.过大的Region,执行spilt操作;

    3.Client访问hbase上的数据过程,不需要master参与;

Hbase读流程:

  1. 首选,客户端访问zookeeper获取meta表(主要记录表的元信息)所在的region,然后从meta中获取想要操作的region位置,并将meta缓存在客户端,用于后续的操作(当一个RegionServer宕机后,客户端需要重新获取meta信息进行缓存);
  2. 向对应的RegionServer建了连接并发起读取数据请求;
  3. 此时,RegionServer会先到MemStore中查数据(为了提高查询效率),如果查不到就会到BlockCache中查,再查不到就会访问磁盘中HFile读取数据;

Scanner在server结构:

  1. 请求RegionServer构建RegionScanner;
  2. 一个RegionScanner管理一堆ColumnFamily,构造StoreScanner,一个StoreScanner对应了这个store上的memstore和Hfile;
  3. StoreScanner管理一堆HFile,构造HFileScanner,这个是实际读取数据的地方(获取数据的HFile是不能处于compaction状态,正在处于compaction的HFile是无法检索的);

scanner.next的关键步骤:

  1. Scan是一行一行获取的,获取完一行之后再获取下一行;
  2. 一般查找的顺序是先memstore,然后blockcache,最后到HFile;
  3. 每次拿一次数据都要判断下是否有stopRow,如果有可以停在搜索返回;
  4. 最终返回的Listresults要封装成Result[]格式返回

Hbase写流程:

  1. 客户端想RegionServer发送写入数据请求;
  2. zookeeper中存储了meta表的region信息,从meta表获取相应region信息,然后找到meta表的数据;
  3. 根据namespace、表名和rowkey根据meta表的数据找到写入数据对应的region信息,找到对应的regionserver;
  4. RegionServer把数据分别写到HLog和MemStore上一份。先将数据写入HLog,即WAL,再讲数据写入MemStore;这里稍作展开,hbase的写是顺序读写,相对于关系型数据库的随机读写,减少了寻道时间,有一定的提高;具体体现在数据首先写到memstore中,这个是在内存中,并对写入数据在内存中进行了排序;
  5. 当MemStore中的数据达到阈值的时候,会将数据Flush到硬盘中,这个时候每个flush会形成一个StoreFile,这个HFile是局部有序,整体无序并同时清空内存和HLog中的历史数据(如果MemStore中有数据丢失,可以用HLog恢复);
  6. 将硬盘中数据通过HFile来序列化,再讲数据传输到HDFS进行存储。并对HLog进行一次标记;
  7. 当StoreFile数量到达一定值的时候,会进行compact操作,合并成一个大的StoreFile(同时进行版本合并和数据删除),这里会消耗一定的服务器性能,因为需要对每个小StoreFile进行排序整理,重新写到一个大的StoreFile中;
  8. 如果一个region大小超过阈值时,会进行split操作,并将拆分后的子region重新分配的不同的RegionServer进行管理;
  9. HLog,即WAL记录数据的所有变更,可以用来做数据恢复
  10. HFile是Hbase中KeyValue数据存储格式,Hfile是Hadoop的二进制格式文件,StoreHFile就是对HFile进行了封装,底层就是HFile;
  11. hdfs对应的目录结构为
    namespace->table->列簇->列->单元
  12. 写入流程中涉及到MVCC多版本协议控制协议,主要是hbase解决读写一致性的解决方案。MVCC变量是region级别的,每个region之间的mvcc是相互独立的。写如过程中的MVCC的作用:

Hbase读写流程简要分析_第1张图片

Hbase每次Put都会指定一个唯一ID,该ID是Region级递增的。每个Region得MVCC维护两个point:

  1. readpoint指向已经写入完成的ID;
  2. writepoint指向正在写入的ID

没有数据写入的时候,二者的位置是一样的,当有数据写入的时候,readpoint要比writepoint小,只有readpoint之前的数据能够读取到(只要成功写入HLog和Memstore的数据能够读取到,无序写入HFile中)

Nonce机制:

在网络不稳定的情况下,当客户端发送rpc请求给regionserver服务器的时候,如果服务器处理时间过长导致超时,会出现服务器处理完毕,而无法及时通知客户端,导致客户端重新发送写入请求,即多次发送append,会造成数据多次添加。为了防止类似的现象,Hbase引入了Nonce机制,ServerNonceManager负责管理该RegionServer的nonce。

客户端每次申请以及重复申请会使用同一个nonce,发送到服务端之后,服务端会判断该nonce是否存在,如果不存在则可以放心执行,否则会根据当前的nonce进行相应的回调处理:

  1. 如果nonce处于WAIT状态,表示该nonce所对应的操作正在执行中,需要等待其执行结束,根据其执行结果进行下一步操作;
  2. 如果nonce处于PROCEED状态,则表明该nonce所对应的操作已经执行过了,只不过是已失败告终,可以重新执行;
  3. 如果noce处于DONT_PROCEED状态,无需做处理。因此,当nonce进入DONT_PROCEED状态以后,所有通过它来执行的操作都会被忽视掉,从而防止操作冗余的发生。

Hbase底层存储结构:

所有数据一般都保存在hadoop分布式系统上,用户通过访问region服务获取数据,一个物理节点一般只能运行一个region服务器,主要组成部分为:HLog(WAL)和多个region;一个HStore包含:一个MemStore和多个HFile

 

Hbase底层存储的架构图

Hbase读写流程简要分析_第2张图片

Hbase的数据最终是以HFile的形式存储在HDFS中的,HBase中HFile有着对应格式。一次memstore的flush会产生一个StoreFile,一次Compact会导致多个StoreFile合并成一个。Hbase提供的读/写StoreFile的reader和writer工厂类,可以直接从StoreFile文件读取数据,从而绕过Hbase提供Scan、Get、Put等api

StoreFile以Hfile格式保存在HDFS上 ,内容是由一个个block组成的,按照block类型可分为:

1.   datablock存放的key-value数据,一般一个datablock大小默认为64kb;

2.   data index block,其中存放的是datablock的index,索引可以是多级索引,中间索引,叶子索引一般分布在HFile文件当中;

3.   bloom filter block,保持了bloom过滤的值;

4.   meta data block,meta data block有多个,且连续分布;

5.   meta data index 顾名思义

6.   file-info block,其中记录了关于文件的一些信息:HFile中最大的key,平均Key长度,HFile创建时间戳,data block使用的编码方式等;

7.   trailer block,每个HFile文件都会有的,对于不同版本的HFile的trailer长度可能不一样,但是同一版本的所有的HFile trailer的长度都是一样长的

HFile里面的每个KeyValue对就是一个简单的byte数组:

1)KeyLength和ValueLength:两个固定的长度,分别代表着Key和Value的长度;

2)Key部分:RowLength是固定长度的数值,表示Rowkey的长度,Row就是RowKey,ColumnFamilyLength是固定长度的数值,表示Family的长度,接着就是ColumnFamily,再接着是Qualifier,然后是两个固定长度的数值,表示TimeStamp 和KeyType(Put/Delete)

3)Value 部分就没有这么复杂结构,是纯粹的二进制数组 

HFile读写,都可以通过org.apache.hadoop.hbase.io.hfile.HFile这类类提供的一些静态方法来实现

Hbase宕机处理:

  1. Zookeeper会监控RegionServer的上下线情况,当ZK发现某个RegionServer宕机之后,会通知HMaster;
  2. 该RegionServer会停止对外提供服务,即该Region服务器下的region对外都无法访问;
  3. HMaster会将该RegionServer所负责的region转移到其他RegionServer上,并且会对RegionServer上存在MemStore中未持久化到硬盘的数据进行恢复;
  4. 这个恢复操作工作由读取WAL文件完成:
    1. 宕机发生时,读取该RegionServer所对应的路径下的WAL文件,然后根据不同的region切分成不同的recover.edits;
    2. 当region被分配到其他RegionServer时,RegionServer读取region时会进行是否存在recover.edits,如果有则进行恢复。

参考链接:https://blog.csdn.net/nuisthou/article/details/49250435

                  https://www.jianshu.com/p/e2bbf23f1ba2

你可能感兴趣的:(hbase)