HBase物理结构有哪些

本篇内容介绍了“HBase物理结构有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

创新互联建站服务项目包括回民网站建设、回民网站制作、回民网页制作以及回民网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,回民网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到回民省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

逻辑结构

RowKey第一位
  ColumnFamily
    ColumnQuiauer
      value(TimeStamps)
      Cell

物理结构

HMaster    ----->NameNode
管理节点,用于管理HBase中的Table和Region的结构操作,比如用户增、删、修改表的操作。
在HBase集群中,可以启动多个HMaster,但是只能有一个HMaster属于Active的状态,通过ZooKeeper和其它standby状态的HMaster进程完成,一个状态的切换,或者选举。
我们可以使用HMaster的shutdown放关闭整个集群,在关闭整个集群的时候,需要向通知HRegionServer进行关闭,并反馈给HMaster,HMaster才自行关闭。
HRegionServer----->DataNode
存放Region的服务器,需要在HMaster进行注册,如此才能在HMaster中对其进行管理,在HBase集群中,可以部署多个HRegionServer
Region
存储的是一张表的一个特定的Region数据,包含了一部分行的所有的列,region通过table和对应行健rowkey来定义,在region级别
添加一个锁的唯一的目的,就是挡在执行其它操作的时候,阻止region被关闭,以及split。每一行的操作,都需要在执行过程中获得一个row所和region的读锁。
HRegion
存放hbase中数据的一个概念,可以简单的理解为表的一个分区,存放一张表中的一部分数据,当该region中的数据超过一定量的时候,会自动进行分裂,
分裂成两个region(一分为二),从这个角度上而言,Region是对hbase中表的一个横向的划分。
每一个HRegion有多个HStore组成,每一个HRegion是一张表中所有的列做成部分数据(也就是说部分记录),每一个region都有一个startKey和endKey

一些配置参数说明:


    hbase.hregion.max.filesize
    10737418240
    
        Maximum HStoreFile size. If any one of a column families' HStoreFiles has
        grown to exceed this value, the hosting HRegion is split in two.


hregion最大的大小,当一个region中的storeFile增长到10G的时候,split一分为二
手动将一个表今次那个region的切分,使用命令split 'table'/'region', 'splitKey'
startKey和endKey
假设,我一张表里面有100条记录,我要把它分别存放到10个region里面,又因为存放在hbase里面的数据都是有序的,是能够进行一个高速随机读写的,
也就是说有序能够保证我的快读,就需要能够通过rowkey,快速的定位到当前记录在哪一个region里面,然后当定位到region之后,再去扫描当前region,获取数据,
为了满足于此,我们就对这些region进行划分,编号,也是为了方便管理。这里每一个region的范围:[startKey, endKey),需要注意一定最后一个region的endkey是需要被包含进去的。

region 0    [null, 10)
region 1    [10, 20)
region 2    [20, 30)
region ...  ...
region 9    [90, null]
将HRegion数据从memstore中手动刷新到磁盘中,使用命令flush 'table'/'region'
手动将一个表今次那个region的切分,使用命令split 'table'/'region', 'splitKey'
HStore
每一个HRegion由多一个HStore来组成,一个HStore对应HRegion中的一个列族,一个HStore有一个MemStore和一个系列StoreFiles组成。
HStore级别不会持有锁,以及事务,锁和事务在更高一个级别或者说HRegion持有的,
HStore最核心的一个service就是合并memstore刷新到到磁盘里面的storefiles,
把多个storefiles合并成为一个storefile,写到hdfs里面,写到hdfs里面的文件称之为hfile。

在写的过程中,唯一设计到hlog的部分就是关于hlog日志的重建的过程,当hstore将用户提交的数据最终写到了hdfs之后,会反馈给hlog,
将hlog里面冗余的数据删除掉。

hbase.hstore.compactionThreshold=3,当hstore个数超过3个之后就要开启hstore合并的工作
Compaction:
  minor compaction(小合并):
    就是将多个HFile合并成为一个大的HFile,然后对之前的HFile做清除处理。
    常见的会在执行删除数据的动作、以及达到hbase.hstore.compactionThreshold触发条件的时候发生,
    删除数据:不会立即删除,做一个标记(标记删除),等到执行合并操作的时候,才进行数据的处理。
  major compaction(大合并):
    将一个列族中的所有的HFile合并成为一个HFile,然后对之前的HFile做清除处理。
    大合并非常消耗性能,非常耗时,不建议操作,当然是直接可以在shell执行操作的。

一些配置属性的说明如下:


    hbase.hstore.compactionThreshold
    3
    
    If more than this number of HStoreFiles in any one HStore
    (one HStoreFile is written per flush of memstore) then a compaction
    is run to rewrite all HStoreFiles files as one.  Larger numbers
    put off compaction but when it runs, it takes longer to complete.
    
       

    hbase.server.compactchecker.interval.multiplier
    1000
    The number that determines how often we scan to see if compaction is necessary.
      Normally, compactions are done after some events (such as memstore flush), but if
      region didn't receive a lot of writes for some time, or due to different compaction
      policies, it may be necessary to check it periodically. The interval between checks is
      hbase.server.compactchecker.interval.multiplier multiplied by
      hbase.server.thread.wakefrequency.
    
       

  hbase.hregion.majorcompaction
  604800000 7天
  The time (in miliseconds) between 'major' compactions of all
  HStoreFiles in a region.  Default: Set to 7 days.  Major compactions tend to
  happen exactly when you need them least so enable them such that they run at
  off-peak for your deploy; or, since this setting is on a periodicity that is
  unlikely to match your loading, run the compactions via an external
  invocation out of a cron job or some such.
     

  hbase.hstore.blockingStoreFiles
  10
  
  If more than this number of StoreFiles in any one Store
  (one StoreFile is written per flush of MemStore) then updates are
  blocked for this HRegion until a compaction is completed, or
  until hbase.hstore.blockingWaitTime has been exceeded.
 

    hbase.hstore.compaction.max
    10
    Max number of HStoreFiles to compact per 'minor' compaction.       
MemStore
注意:在memstore写的过程中,必须不能是多线程的(并行)调用的,hstore在调用的过程中必须持有一个读锁和写锁
在写的过程中,预先数据在memstore中进行排序,因为数据最终是有序存放,当memstore中的数据量超过阈值之后就会刷新到磁盘文件storefile中。

配置参数如下:


    hbase.hregion.memstore.flush.size
    134217728
    
        Memstore will be flushed to disk if size of the memstore
        exceeds this number of bytes.  Value is checked by a thread that runs
        every hbase.server.thread.wakefrequency.
StoreFile
最终保存HStore数据的文件,数据是由MemStore不断向磁盘刷新过程中产生的,当storefile达到一定量的时候,会将这些storefile组成一个storefiles。
这个storefiles有可能持有其他store里面的storefile。
HFile
在hdfs上存放数据之前的一个物理结构,用于接收从客户端提交过来的数据。
HFile中的数据都Key-Value键值对儿的方式存储,并且key和value都是字节数组。并且因为数据已经在memstore中排序过了,在hfile中也是有序的。
hfile同时是由一个个的block来组成的,最终k-v实际上是在这一个个的block中的,block的推荐的大小在8k~1M之间,默认大小65536byte-->16kb。
每一个block都有索引,没有hfile有由索引

官方建议:
blocksize在8k~1M之间,默认是64k
如果执行顺序读的操作,建议将blocksize调大一点点,这个会影响随机访问的效率
如果执行随机读的操作,建议将blocksize调小一点点,用默认就可以了

在扫描全表数据的时候,一定要指定start key和end key,不然容易操作OOM异常
总结
  HRegionServer
  |---一个HLog
  |---多个HRegion(一张表对应多个HRegion,是对hbase表的一个横向的划分)
    |---多个HStore(一个HStore对应一个列族,反之一个列族对应多个HStore,列族是对HBase表的纵向的划分)
      |--一个MemStore
      |--多个StoreFile
        HFile
          |---多个data block

HBase如何做到高速随机读?
    rowkey---->region
          先到memstore中去找,如果有,则直接取出>>>
          如果没有,则就去在hfile中找,通过索引定位到具体的block,然后遍历该block块,找到相应的数据
--------------------------------------------------------------------------
把在想memstore写数据的过程中,同时向hlog中写数据的这种解决问题的方式称之为SLM-Tree(Structure Log merge tree)
这种数据结构和B-Tree有些类似,也是引自于Google BigTable

行健的设计问题

行健的热点问题
是由于行健相似、连续且数据量过大操作成单region的数据量过大,进而影响读写效率

行健应该尽量的随机、不要出现连续行健。
常见的行健设计就是,比如手机号码倒置+时间戳,比如随机前缀+关系型数据库中的主键(以存放在mr中电信日志案例为例)

因为hbase提供的查询内容非常非常low,但是所有关于hbase的查询只能通过rowkey,所以
在设计行健的时候,应该考虑将尽量多的查询条件放到rowkey中去,形成的行健就成为复合键
列族的设计
cf1----->"maxRowLength"
cf2----->"mrl"
建议hbase表是高表,不建议宽表,因为宽表拥有的列族很多,操作并跨越的文件(HFile)就很多,效率会有相应影响,
反之建议使用高表,列族不宜过多。
在设计表的时候,各个列/列族名称不宜过长,因为hbase需要对这些数据在内存中做缓存,做索引,进而影响内存容量,
所以建议不易过长,以便能够在内存中容纳更多的数据。至于阅读性,有项目文档搞定。

Hive整合HBase

启动hive,进入hive的终端:
/home/uplooking/app/hive/bin/hive --auxpath /home/uplooking/app/hive/lib/hive-hbase-handler-2.1.0.jar,/home/uplooking/app/hive/lib/zookeeper-3.4.6.jar --hiveconf hbase.master=uplooking01:16010 --hiveconf hbase.zookeeper.quorum=uplooking01,uplooking02,uplooking03
在Hive里面操作HBase

创建一张表:

hbase不存在该表的情况

如果hbase中不存在该表我们只能在hive中使用创建内部表的方式,来创建一张表,同会在hbase中也会创建相关的表。

eg.
    create table h3hb_1(
     id int,
     name string,
     age int
    )row format delimited
     fields terminated by ','
     stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties (
     "hbase.columns.mapping" = ":key,cf:name,cf:age",
     "hbase.table.name" = "t"
    );

在hive中创建了一张表h3hb_1,有三列内容id, name,age,同时映射到hbase中的表t,其中id对应行健
name对应hbase中列族cf中的name,age同理

尝试向表中导入数据,会报下面的错误:

hive (mydb1)> load data local inpath 'stu.txt' into table h3hb_1;
FAILED: SemanticException [Error 10101]: A non-native table cannot be used as target for LOAD

所以创建了一张临时表并导入数据:

hive (mydb1)> create temporary table tmp(
            > id int,
            > name string,
            > age int)row format delimited
            > fields terminated by ',';
OK
Time taken: 0.104 seconds
hive (mydb1)> load data local inpath 'stu.txt' into table tmp;
Loading data to table mydb1.tmp
OK
Time taken: 0.408 seconds

最后通过查询的方式向其插入数据:

hive (mydb1)> insert into h3hb_1 select * from tmp;
...
2018-03-24 01:09:47,267 Stage-0 map = 0%,  reduce = 0%
2018-03-24 01:09:59,883 Stage-0 map = 100%,  reduce = 0%, Cumulative CPU ...
Time taken: 32.315 seconds

可以看到会启动一个MR的任务。

hbase存在该表的情况

如果使用上述建表语句创建的时候,则会报错,因为在hbase中已经存在了一张表为t,所以这时只能创建外部表去映射hbase中的一张表。

create external table h3hb_2
(id int,
 name string,
 age int
)row format delimited
 fields terminated by ','
 stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties (
 "hbase.columns.mapping" = ":key,cf:name,cf:age",
 "hbase.table.name" = "t"
);

Phoenix整合HBase

安装Phoenix
约定安装到/home/uplooking/app目录下面
解压:
    [uplooking@uplooking01 ~]$ tar -zxvf soft/phoenix-4.7.0-HBase-1.1-bin.tar.gz -C app/
重命名 [uplooking@uplooking01 ~]$ mv app/phoenix-4.7.0-HBase-1.1-bin/ app/phoenix
拷贝lib目录下面jar包到regionserver机器的lib($HBASE_HOME/lib)目录
     [uplooking@uplooking01 phoenix]$ scp *.jar uplooking@uplooking02:/home/uplooking/app/hbase/lib/
     [uplooking@uplooking01 phoenix]$ scp *.jar uplooking@uplooking03:/home/uplooking/app/hbase/lib/
重启regionserver
    hbase-daemon.sh stop regionserver
    hbase-daemon.sh start regionserver
将phoenix中的client拷贝到hbase的client中,重启master
    p[uplooking@uplooking01 phoenix]$ cp phoenix-4.7.0-HBase-1.1-client.jar /home/uplooking/app/hbase/lib/
    hbase-daemon.sh stop master
    hbase-daemon.sh start master
官网测试案例:
http://phoenix.apache.org/Phoenix-in-15-minutes-or-less.html
    ./psql.py uplooking01:2181 us_population.sql us_population.csv us_population_queries.sql
在cli中使用Phoenix
./sqlline.py uplooking01:2181:/hbase

查询操作:

0: jdbc:phoenix:uplooking01:2181:/hbase> !tables
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
| TABLE_CAT  | TABLE_SCHEM  |   TABLE_NAME   |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
|            | SYSTEM       | CATALOG        | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | FUNCTION       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | SEQUENCE       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | STATS          | SYSTEM TABLE  |          |            |                           |
|            |              | US_POPULATION  | TABLE         |          |            |                           |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
0: jdbc:phoenix:uplooking01:2181:/hbase> select * from US_POPULATION;
+--------+---------------+-------------+
| STATE  |     CITY      | POPULATION  |
+--------+---------------+-------------+
| AZ     | Phoenix       | 1461575     |
| CA     | Los Angeles   | 3844829     |
| CA     | San Diego     | 1255540     |
| CA     | San Jose      | 912332      |
| IL     | Chicago       | 2842518     |
| NY     | New York      | 8143197     |
| PA     | Philadelphia  | 1463281     |
| TX     | Dallas        | 1213825     |
| TX     | Houston       | 2016582     |
| TX     | San Antonio   | 1256509     |
+--------+---------------+-------------+
10 rows selected (0.138 seconds)

创建表与插入数据:

0: jdbc:phoenix:uplooking01:2181:/hbase> create table p1(id integer not null primary key, name varchar(20), age integer);
No rows affected (2.351 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> !tables
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
| TABLE_CAT  | TABLE_SCHEM  |   TABLE_NAME   |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
|            | SYSTEM       | CATALOG        | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | FUNCTION       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | SEQUENCE       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | STATS          | SYSTEM TABLE  |          |            |                           |
|            |              | P1             | TABLE         |          |            |                           |
|            |              | US_POPULATION  | TABLE         |          |            |                           |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
0: jdbc:phoenix:uplooking01:2181:/hbase> !describe p1;
+------------+--------------+-------------+--------------+------------+------------+--------------+--------------+
| TABLE_CAT  | TABLE_SCHEM  | TABLE_NAME  | COLUMN_NAME  | DATA_TYPE  | TYPE_NAME  | COLUMN_SIZE  | BUFFER_LENGT |
+------------+--------------+-------------+--------------+------------+------------+--------------+--------------+
|            |              | P1          | ID           | 4          | INTEGER    | null         | null         |
|            |              | P1          | NAME         | 12         | VARCHAR    | 20           | null         |
|            |              | P1          | AGE          | 4          | INTEGER    | null         | null         |
+------------+--------------+-------------+--------------+------------+------------+--------------+--------------+
0: jdbc:phoenix:uplooking01:2181:/hbase> upsert into p1 values(1, 'zhangsan',13);
1 row affected (0.13 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> upsert into p1 values(2, 'lisi',14);
1 row affected (0.019 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> select * from p1;
+-----+-----------+------+
| ID  |   NAME    | AGE  |
+-----+-----------+------+
| 1   | zhangsan  | 13   |
| 2   | lisi      | 14   |
+-----+-----------+------+
2 rows selected (0.066 seconds)

可以看到,我们创建的表p1,在实际创建时,会变成大写的P1,在hbase中查看:

hbase(main):004:0> scan 'P1'
ROW                           COLUMN+CELL                                                                         
 \x80\x00\x00\x01             column=0:AGE, timestamp=1521827542938, value=\x80\x00\x00\x0D                       
 \x80\x00\x00\x01             column=0:NAME, timestamp=1521827542938, value=zhangsan                              
 \x80\x00\x00\x01             column=0:_0, timestamp=1521827542938, value=x                                       
 \x80\x00\x00\x02             column=0:AGE, timestamp=1521827553065, value=\x80\x00\x00\x0E                       
 \x80\x00\x00\x02             column=0:NAME, timestamp=1521827553065, value=lisi                                  
 \x80\x00\x00\x02             column=0:_0, timestamp=1521827553065, value=x                                       
2 row(s) in 0.0410 seconds

可以看到列族也默认为0,可以尝试下面的方式来创建表:

0: jdbc:phoenix:uplooking01:2181:/hbase> create table "p2"(id varchar(100000) primary key, "cf"."name" varchar(20), "cf"."age" varchar(100));
No rows affected (1.288 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> !tables
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
| TABLE_CAT  | TABLE_SCHEM  |   TABLE_NAME   |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
|            | SYSTEM       | CATALOG        | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | FUNCTION       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | SEQUENCE       | SYSTEM TABLE  |          |            |                           |
|            | SYSTEM       | STATS          | SYSTEM TABLE  |          |            |                           |
|            |              | P1             | TABLE         |          |            |                           |
|            |              | US_POPULATION  | TABLE         |          |            |                           |
|            |              | p2             | TABLE         |          |            |                           |
+------------+--------------+----------------+---------------+----------+------------+---------------------------+
0: jdbc:phoenix:uplooking01:2181:/hbase> upsert into "p2" values('1','zhangsan','13');
1 row affected (0.061 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> upsert into "p2" values('2','lisi','14');
1 row affected (0.015 seconds)
0: jdbc:phoenix:uplooking01:2181:/hbase> select * from "p2";
+-----+-----------+------+
| ID  |   name    | age  |
+-----+-----------+------+
| 1   | zhangsan  | 13   |
| 2   | lisi      | 14   |
+-----+-----------+------+
2 rows selected (0.055 seconds)

这样创建的表就为小写的了,同时在hbase中查看也可以看到列族:

hbase(main):006:0> scan 'p2'
ROW                           COLUMN+CELL                                                                         
 1                            column=cf:_0, timestamp=1521827723448, value=x                                      
 1                            column=cf:age, timestamp=1521827723448, value=13                                    
 1                            column=cf:name, timestamp=1521827723448, value=zhangsan                             
 2                            column=cf:_0, timestamp=1521827735556, value=x                                      
 2                            column=cf:age, timestamp=1521827735556, value=14                                    
 2                            column=cf:name, timestamp=1521827735556, value=lisi                                 
2 row(s) in 0.0390 seconds
Phoenix客户端工具操作
安装squirrel-sql-3.7-standard.jar
java -jar squirrel-sql-3.7-standard.jar

然后就可以进行安装。

添加HBase驱动

使用squirrel-sql添加一个驱动,其属性值可为如下:

Name:hbase
Example URL:jdbc:phoenix:uplooking01,uplooking02,uplooking03:2181
Class Name:org.apache.phoenix.jdbc.PhoenixDriver

驱动可以到phoenix目录下找到:phoenix-4.7.0-HBase-1.1-client.jar,然后添加即可
创建连接

选择驱动为前面创建的驱动,然后用户名和密码都为uplooking
这样之后就可以像使用navicat管理MySQL数据库一样,比较方便。

“HBase物理结构有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


标题名称:HBase物理结构有哪些
分享网址:http://ybzwz.com/article/jijsep.html