HBase存储架构

作者: yannhuang | 来源:发表于2017-11-27 14:36 被阅读93次
    HBase存储架构

    上图是HBase的存储架构图。

    由上图可以知道,客户端是通过Zookeeper找到HMaster,然后再与具体的Hregionserver进行沟通读写数据的。

    具体到物理实现,细节包括以下这些:

    1、客户端在zookeeper中找到存储了-ROOT-表的RegionServer
    2、在-ROOT-中找到.META.表的位置
    3、在.META.表中找到存储了指定rowkey的HRegionServer位置
    4、客户端连接该机器进行数据读写

    首先要清楚HBase在hdfs中的存储路径,以及各个目录的作用。在hbase-site.xml 文件中,配置项 <name> hbase.rootdir</name> 默认 “/hbase”,就是hbase在hdfs中的存储根路径。以下是hbase0.96版本的个路径作用。1.0以后的版本请参考这里: https://blog.bcmeng.com/post/hbase-hdfs.html

    hbase在hdfs中的存储路径

    1、/hbase/.archive
    HBase 在做 Split或者 compact 操作完成之后,会将 HFile 移到.archive 目录中,然后将之前的 hfile 删除掉,该目录由 HMaster 上的一个定时任务定期去清理。

    2、/hbase/.corrupt
    存储HBase损坏的日志文件,一般都是为空的。

    3、/hbase/.hbck
    HBase 运维过程中偶尔会遇到元数据不一致的情况,这时候会用到提供的 hbck 工具去修复,修复过程中会使用该目录作为临时过度缓冲。

    4、/hbase/logs
    HBase 是支持 WAL(Write Ahead Log) 的,HBase 会在第一次启动之初会给每一台 RegionServer 在.log 下创建一个目录,若客户端如果开启WAL 模式,会先将数据写入一份到.log 下,当 RegionServer crash 或者目录达到一定大小,会开启 replay 模式,类似 MySQL 的 binlog。

    5、/hbase/oldlogs
    当.logs 文件夹中的 HLog 没用之后会 move 到.oldlogs 中,HMaster 会定期去清理。

    6、/hbase/.snapshot
    hbase若开启了 snapshot 功能之后,对某一个用户表建立一个 snapshot 之后,snapshot 都存储在该目录下,如对表test 做了一个 名为sp_test 的snapshot,就会在/hbase/.snapshot/目录下创建一个sp_test 文件夹,snapshot 之后的所有写入都是记录在这个 snapshot 之上。

    7、/hbase/.tmp
    当对表做创建或者删除操作的时候,会将表move 到该 tmp 目录下,然后再去做处理操作。

    8、/hbase/hbase.id
    它是一个文件,存储集群唯一的 cluster id 号,是一个 uuid。

    9、/hbase/hbase.version
    同样也是一个文件,存储集群的版本号,貌似是加密的,看不到,只能通过web-ui 才能正确显示出来

    10、-ROOT-
    该表是一张的HBase表,只是它存储的是.META.表的信息。通过HFile文件的解析脚本 hbase org.apache.hadoop.hbase.io.hfile.HFile -e -p -f 可以查看其存储的内容,如下所示:

    hbase org.apache.hadoop.hbase.io.hfile.HFile -e -p -f   /hbase/-ROOT-/70236052/info/604443e666684d8ca2b3f81d662df6c3
    
    解析内容如下:
    
    K: .META.,,1/info:server/1504514627434/Put/vlen=14/ts=0 V: dchbase2:60020
    K: .META.,,1/info:serverstartcode/1504514627434/Put/vlen=8/ts=0 V: \x00\x00\x01]\xA0\xAA\x04A
    

    以上可以看出,-ROOT-表记录的.META.表的所在机器是dchbase2,与web界面看到的一致:


    META表信息

    11、.META.
    通过以上表能找到.META.表的信息,该表也是一张hbase表,通过以上命令,解析其中一个region:

    hbase org.apache.hadoop.hbase.io.hfile.HFile -e -p -f /hbase/.META./1028785192/info/2de4d44c7a2e4d86928f3a075ad8471b
    
    解析内容如下:
    
    K: adt_app_channel,,1439437512159.cd311ca186e08ee5aeaa4cc188121ba3./info:server/1498474805942/Put/vlen=14/ts=0 V: dchbase3:60020
    K: dc_debug_log,EAA47BA32FD980D20E2DB2D19050A51D|2|638069812,1509447378983.3642c1134e2dcd810f48a0b0409f60b3./info:server/1509531353681/Put/vlen=14/ts=0 V: dckafka1:60020
    K: dc_debug_log,EAA47BA32FD980D20E2DB2D19050A51D|2|638069812,1509447378983.3642c1134e2dcd810f48a0b0409f60b3./info:server/1509447380418/Put/vlen=14/ts=0 V: dckafka2:60020
    

    以上可以看出,adt_app_channel表的数据记录在dchbase3这台reginserver上,也与界面一致,如果有多个region,则会在表名后面加上rowkey的范围:


    普通表信息

    通过以上描述,只要找到-ROOT-表的信息,就能根据rowkey找到对应的数据,那-ROOT-在哪里找呢?从本文一开始的图中可以知道,就是在zookeeper中找的。进入zookeeper命令行界面:

    ./hbase zkcli -server dcnamenode1:2181(hbase自带zk)
    
    [zk: dcnamenode1:2181(CONNECTED) 3] get /hbase/root-region-server
    12439@dchbase3dchbase3,60020,1498474547671   ###注意该行信息
    cZxid = 0x2f0001c2c0
    ctime = Mon Jun 26 19:00:04 CST 2017
    mZxid = 0x2f0001c2c0
    mtime = Mon Jun 26 19:00:04 CST 2017
    pZxid = 0x2f0001c2c0
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 47
    numChildren = 0
    [zk: dcnamenode1:2181(CONNECTED) 4]
    

    可以看出-ROOT-表存储在 dchbase3 机器中,对应界面如下:


    ROOT表信息

    以上就是HBase客户端根据指定的rowkey从zookeeper开始找到对应的数据的过程。

    那在Region下HBase是如何存储数据的呢?

    以下就具体操作一张表,查询对应的HFile文件,看HBase的数据存储过程。

    在HBase创建一张表 test7,并插入一些数据,如下命令:

    create 'test7','info'  #创建表
    
    put 'test7','100',info:name','yann'
    put 'test7','100',info:age','12'
    put 'test7','200',info:name','yann'
    put 'test7','200',info:age','15'
    

    查看wal日志,通过 hbase org.apache.hadoop.hbase.regionserver.wal.HLog --dump -p 命令可以解析HLog文件,内容如下:

    hbase org.apache.hadoop.hbase.regionserver.wal.HLog --dump -p /hbase/.logs/server1,60020,1511338186832/server1%2C60020%2C1511338186832.1511593793118
    
    Sequence 68663206 from region 1028785192 in table .META.
      Action:
        row: test7,,1511593978551.33ba34be458d2b18f97d7b7ccc89468e.
        column: info:regioninfo
        at time: Sat Nov 25 15:12:58 CST 2017
        value: \x01\x00\x00\x00\x00\x01_\xF2\x05\xAA\xB76test7,,1511593978551.33ba34be458d2b18f97d7b7ccc89468e.\x00\x00\x05test7$\xB2\xBEV
    Sequence 68663207 from region 1028785192 in table .META.
      Action:
        row: test7,,1511593978551.33ba34be458d2b18f97d7b7ccc89468e.
        column: info:server
        at time: Sat Nov 25 15:12:58 CST 2017
        value: server1:60020
      Action:
        row: test7,,1511593978551.33ba34be458d2b18f97d7b7ccc89468e.
        column: info:serverstartcode
        at time: Sat Nov 25 15:12:58 CST 2017
        value: \x00\x00\x01_\xE2\xC6\x98P
    Sequence 68663208 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: 100
        column: info:name
        at time: Sat Nov 25 15:13:33 CST 2017
        value: yann
    Sequence 68663209 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: 100
        column: info:age
        at time: Sat Nov 25 15:13:41 CST 2017
        value: 12
    Sequence 68663210 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: 200
        column: info:name
        at time: Sat Nov 25 15:13:47 CST 2017
        value: yann
    Sequence 68663211 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: 200
        column: info:age
        at time: Sat Nov 25 15:13:51 CST 2017
        value: 12
    Sequence 68663212 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: METAROW
        column: METAFAMILY:
        at time: Sat Nov 25 15:14:19 CST 2017
        value: HBASE::CACHEFLUSH
    Sequence 68663213 from region 33ba34be458d2b18f97d7b7ccc89468e in table test7
      Action:
        row: 200
        column: info:age
        at time: Sat Nov 25 15:15:19 CST 2017
        value: 15
    

    查看HFile文件,内容如下:

    hbase org.apache.hadoop.hbase.io.hfile.HFile -e -p -f /hbase_1/test7/33ba34be458d2b18f97d7b7ccc89468e/info/caeaaf25659242c19e5f4f983c5206ee
    
    K: 100/info:age/1511594021359/Put/vlen=2/ts=0 V: 12
    K: 100/info:name/1511594013569/Put/vlen=4/ts=0 V: yann
    K: 200/info:age/1511594031440/Put/vlen=2/ts=0 V: 12
    K: 200/info:name/1511594027562/Put/vlen=4/ts=0 V: yann
    

    由此可见,HFile文件就是存储HBase的KV对,其中Key的各个字段包含了的信息如下:

    100/info:age/1511594021359/Put/vlen=2/ts=0
    rowkey / columnFamily:column / timestamp / Option / len / ts

    由于hbase把cf和column都存储在HFile中,所以在设计的时候,这两个字段应该尽量短,以减少存储空间。

    但删除一条记录的时候,HBase会怎么操作呢?执行以下命令:

    deleteall 'test7','200'
    

    删除了rowkey为200的记录,查看hdfs,原来的HFile并没有改变,而是生成了一个新的HFile,内容如下:

    K: 100/info:/1511594203116/DeleteFamily/vlen=0/ts=0 V: 
    

    所以在HBase中,删除一条记录并不是修改HFile里面的内容,而是写新的文件,待HBase做合并的时候,把这些文件合并成一个HFile,用时间比较新的文件覆盖旧的文件。HBase这样做的根本原因是,HDFS不支持修改文件。

    相关文章

      网友评论

        本文标题:HBase存储架构

        本文链接:https://www.haomeiwen.com/subject/pqurbxtx.html