Hbase架构以及应用介绍

来源:互联网 发布:社交网络 评论音轨 编辑:程序博客网 时间:2024/06/05 19:16

Hbase全称为Hadoop Database,即hbase是hadoop的数据库,是一个分布式的存储系统。Hbase利用Hadoop的HDFS作为其文件存储系统,利用Hadoop的MapReduce来处理Hbase中的海量数据。利用zookeeper作为其协调工具。 
本篇文章将重点介绍Hbase三个方面的内容:Hbase体系结构(架构)的介绍、Hbase shell的操作、Hbase的Java api的客户端操作。 
(一)Hbase的架构介绍 
这里写图片描述 
Hbase的体系结构是一个主从式的结构,主节点Hmaster在整个集群当中只有一个在运行,从节点HRegionServer有很 多个在运行,主节点Hmaster与从节点HRegionServer实际上指的是不同的物理机器,即有一个机器上面跑的进程是Hmaster,很多机器上面跑的进程是HRegionServer,Hmaster没有单点问题,Hbase集群当中可以启动多个Hmaster,但是通过zookeeper的事件处理机制保证整个集群当中只有一个Hmaster在运行。 
既然Hbase是数据库,那么数据库从根本上来说就是存储表table的,但是我们在这里必须注意一下,Hbase并非是传统的关系型数据库(例如:MySQL、Oracle),而是非关系型数据库,因为Hbase是一个面向列的分布式存储系统。下面我们有必要介绍一下Hbase中表table的数据模型,先给大家呈现一个hbase数据库的表users: 
这里写图片描述 
特别注意:表中的空白单元并不表示有这个单元存在,在传统的数据库中,空白单元表示该单元存在其值为空(null,这是因为传统数据库总是结构化的)。但在Hbase中,画成二维表只是在逻辑上便于理解,其本质完全是非结构化的。 
我在下面举例子的过程中用的也是这张users表。 
上面这个表就是一个典型的hbase table,与传统的关系型数据库具有很大的差别,下面我们详细介绍有关table的相关概念: 
RowKey(行健):table的主键,table中的记录默认按照RowKey升序排序。 
列族(Column Family):即表中的address、info。table在水平方向上有一个或者多个Column Family组成,一个Column Family中可以由任意多个Column(例如address中的province、city、country、town)组成,即列族支持动态扩展,无需预先定义Column的数量以及类型,所有Column均已二进制格式进行存储,用户需要自行进行类型转换。 
TimeStamp(时间戳):每次用户对数据进行操作对应的时间,可以看做是数据的Version number。例如在上面的表中,xiaoming所对应的company有两个数据信息(alibaba、baidu),而这两个单元格信息实际上是对应操作时间的,如下图所示: 
这里写图片描述 
既然Hbase可以将表中的数据进行分布式存储,那么它到底是以怎样的形式进行分布式存储的呢?我们自然而然想到了HDFS这个分布式文件管理系统是将海量数据切分成若干个block块进行存储的,同理Hbase也采取了类似的存储机制, 将一个table切分成若干个region进行存储,下面我们就介绍Region的相关概念: 
当Table随着记录数不断增加而变大后,Table在行的方向上会被切分成多个Region,一个Region由[startkey,endkey) 表示,每个Region会被Master分散到不同的HRegionServer上面进行存储,类似于我的block块会被分散到不同的DataNode节点上面进行存储。下面是Hbase表中的数据与HRegionServer的分布关系,如图所示: 
这里写图片描述 
接下来介绍在Hbase的体系结构中,Hmaster、HRegionServer、Zookeeper集群这三个角色的作用: 
这里写图片描述 
Hmaster节点的作用: 
①不负责存储表数据,负责管理RegionServer的负载均衡(即防止某些RegionServer存储数据量大,有些 
RegionServer存储数据量小),调整RegionServer上面Region的分布 
②管理RegionServer的状态,例如在HRegionServer宕机后,负责失效HRegionServer上Regions的迁移 
③在Region Split后,负责新Region的分配 
HRegionServer节点的作用: 
HRegionServer主要负责响应用户的I/O请求,即负责响应用户向表中的读写操作,是Hbase体系结构中最核心的模块。HRegionServer内部存储了很多的HRegion,就像DataNode节点中存储了很多的Block块一样,从上图Hbase完整的体系结构中我们可以看到,HRegion实际上是由很多个HStore组成的,所谓HStore就是表中的一个Column Family,可以看出每个Column Family其实就是一个集中的存储单元,这恰恰也帮助我们理解了为什么Hbase是NoSql系列的数据库,为什么是面向列的数据库,在Hbase的表设计中,我们最好将具备共同I/O特性的Column放在同一个列族中,这样读写才最高效,为了让大家更好的理解HRegionServer、HRegion、HStore、ColumnFamily四者之间的关系,我结合之前提到的users表画了一个四者关系的示意图: 
这里写图片描述 
简单来说:就是HRegionServer服务器中存储了很多的HRegion,每个HRegion是由很过个HStore组成的,每个ColumnFamily就是一个HSore。 
在此还要简单介绍一下HLog与MemStore这两个角色的作用: 
Hlog:Hlog中存储了用户对表数据的最新的一些操作日志记录。 
MemSore:HRegion会将大量的热数据、访问频次最高的数据存储到MemStore中,这样用户在读写数据的时候不需要从磁盘中进行操作,直接在内存中既可以读取到数据,正因为MemStore这个重要角色的存在,Hbase才能支持随机,高速读取的功能。 
Zookeeper集群的作用: 
①通过zk集群的事件处理机制,可以保证集群中只有一个运行的Hmater 
②Zookeeper集群中记录了-ROOT-表的位置 
在这里顺便介绍一下Hbase中两张特殊的表:-ROOT-表与.META.表 
-ROOT-表:记录了所有.META.表的元数据信息,-ROOT-表只有一个Region 
.META.表:记录了Hbase中所有用户表的HRegion的元数据信息,.META.表可以有多个Region 
③Zookeeper集群实时监控着HRegionServer这些服务器的状态,将HRegionServer的上线和下线信息实时通知给Hmaster节点,使得Hmaster节点可以随时感知各个HRegionServer的健康状态。 
在上面我们依次介绍了HMaster、HRegionServer、zookeeper集群的作用,Client使用Hbase的RPC机制与Hmaster与HRegionServer进行通信,对于管理类操作,Client与Hmaster进行RPC进行通信,对于数据(表)的读写类操作,Client与HRegionServer进行通信。注意:在用户对数据表的读写过程中,与Hmaster是没有任何关系的,Hmaster在这一点上不同于我们的NameNode节点,可以看出由于zookeeper集群的存在,Hmaster节点的作用被大大弱化了。 
在Hbase的架构介绍中在介绍最后一点:Hbase的寻址机制,即Hbase在海量的表数据中,是如何找到用户所需要的表数据的呢?——Hbase是通过索引的机制解决了这个问题。 
这里写图片描述 
Client访问用户数据之前需要首先访问zookeeper集群,通过zookeeper集群首先确定-ROOT-表在的位置,然后在通过访问-ROOT- 表确定相应.META.表的位置,最后根据.META.中存储的相应元数据信息找到用户数据的位置去访问。通过 这种索引机制解决了复杂了寻址问题。 
(二)Hbase中shell的相关操作 
前面讲的都是Hbase的理论知识,对于Hbase的操作分为两种方式:shell与java api的方式,既然是对数据库的操作,无非就是增删改查四中操作,下面我列出里几个常用的Hbase Shell操作,如下: 
这里写图片描述 
以之前的users表为例,我现在用shell命令进行相应操作: 
①创建users表 
create ‘users’, ‘address’,’info’ 
②向表中用put进行插入操作 
put ‘users’,’xiaoming’,’address:province’,’zhejiang’ 
put ‘users’,’xiaoming’,’address:city’,’hangzhou’ 
put ‘users’,’xiaoming’,’address:country’,’china’ 
put ‘users’,’xiaoming’,’info:age’,’24’ 
put ‘users’,’xiaoming’,’info:age’,’25’ 
put ‘users’,’xiaoming’,’info:birthday’,’1987/06/17’ 
put ‘users’,’xiaoming’,’info:company’,’alibaba’ 
put ‘users’,’xiaoming’,’info:company’,’baidu’ 
……………… 
③通过get命令获取表中的信息,例如: 
1、获取xiaoming的country单元格信息 
get ‘users’,’xiaoming’,’address:country’ 
2、获取小明两个版本的年龄信息 
get ‘users’,’xiaoming’,{COLUMN=>’info:age’,VERSIONS=>2} 
3、获取zhangyifei全部的信息 
get ‘users’,’zhangyifei’ 
4、获取zhangyifei的address列族的全部信息 
get ‘users’,’zhangyifei’,’address’ 
5、遍历表中的全部信息 
scan ‘users’ 
④用shell命令删除users表 
disable ‘users’ 
drop ‘users’ 
综上:Hbase的shell命令操作整体来说还是非常简单的,获取信息的方法主要是按照下面的主线进行: 
tablename———》rowkey———》Column Family:Colum———->Version信息——》获取信息! 
这里写图片描述 
这里写图片描述 
注:在Java api操作中,对遍历一条记录或者遍历所有记录所用的思想就是:key为{行健、类族、列名、版本号},而value为{具体数值},即一行记录本质上为包含很多键值对。 
(三)Hbase中Java api的相关操作 
Hbase中,可以通过shell命令进行增删改查四种操作,但是shell命令用起来比较麻烦,比如说用put一次只能查询一个单元格的信息等等。因此我们在日常工作中总是用Java api的方式对Hbase进行相应操作,在这里还是以上面的users举例,下面是完整的代码操作: 
这里写图片描述

package IT01;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hbase.HColumnDescriptor;import org.apache.hadoop.hbase.HTableDescriptor;import org.apache.hadoop.hbase.KeyValue;import org.apache.hadoop.hbase.client.Get;import org.apache.hadoop.hbase.client.HBaseAdmin;import org.apache.hadoop.hbase.client.HTable;import org.apache.hadoop.hbase.client.Put;import org.apache.hadoop.hbase.client.Result;import org.apache.hadoop.hbase.client.ResultScanner;import org.apache.hadoop.hbase.client.Scan;public class HbaseJavaapi{       public static String tablename = "users";       public static void main(String[]  args) throws Exception       {             Configuration conf = HBaseConfiguration.create();             /**下面这行代码必须有,指定Hbase所用的zookeeper集群信息****/             /*Configuration conf = new Configuration();这样写的话不会自动读取hbase-site.xml文件,所以别用这个*/             conf.set("hbase.zookeeper.quorum","hadoop80");             /*创建表-----用的Java api是HbaseAdmin**/            @SuppressWarnings("resource")            HBaseAdmin hBaseAdmin = new HBaseAdmin(conf);            if(hBaseAdmin.tableExists(tablename))            {                hBaseAdmin.disableTable(tablename);                hBaseAdmin.deleteTable(tablename);            }            HTableDescriptor desc = new HTableDescriptor(tablename);//指定创建表的名字users            HColumnDescriptor family1 = new HColumnDescriptor("address");            desc.addFamily(family1 );            HColumnDescriptor family2 = new HColumnDescriptor("info");//指定列族的名称            desc.addFamily(family2 );            hBaseAdmin.createTable(desc);            /*****插入记录------用的Java api是HTable****/            @SuppressWarnings("resource")            HTable hTable = new HTable(conf,tablename);  //一定要注意:HTable这个客户端只有在表已经存在的时候才有意义!!!!不然抛出异常!            Put put1 = new Put("xiaoming".getBytes());//插入记录时要指定行健            put1.add("address".getBytes(), "province".getBytes(), "zhejiang".getBytes());            put1.add("address".getBytes(), "city".getBytes(), "hangzhou".getBytes());            put1.add("address".getBytes(), "country".getBytes(), "china".getBytes());            put1.add("info".getBytes(),"age".getBytes(),"24".getBytes());            put1.add("info".getBytes(),"age".getBytes(),"25".getBytes());            put1.add("info".getBytes(),"birthday".getBytes(),"1987/06/17".getBytes());            put1.add("info".getBytes(),"company".getBytes(),"baidu".getBytes());            put1.add("info".getBytes(),"company".getBytes(),"alibaba".getBytes());            hTable.put(put1 );            Put put2 = new Put("zhangyifei".getBytes());//插入记录时要指定行健            put2.add("address".getBytes(), "province".getBytes(), "guangdong".getBytes());            put2.add("address".getBytes(), "city".getBytes(), "shenzhen".getBytes());            put2.add("address".getBytes(), "city".getBytes(), "nansha".getBytes());            put2.add("address".getBytes(), "country".getBytes(), "china".getBytes());            put2.add("address".getBytes(), "town".getBytes(), "xianqiao".getBytes());            put2.add("info".getBytes(),"age".getBytes(),"45".getBytes());            put2.add("info".getBytes(),"birthday".getBytes(),"1987/02/12".getBytes());            put2.add("info".getBytes(),"company".getBytes(),"tengxun".getBytes());            put2.add("address".getBytes(), "favorite".getBytes(), "movie".getBytes());            hTable.put(put2 );            /****查询记录--------------用的Java api是Htable***/            /**1------>获取小明的country单元格信息****/            Get get = new Get("xiaoming".getBytes());            Result result = hTable.get(get);            byte[] value = result.getValue("address".getBytes(), "country".getBytes());            System.out.println(new String(value));            System.out.println("**************************");            /**2------>获取zhangyifei的一行的记录****/            Get get2 = new Get("zhangyifei".getBytes());            Result result2 = hTable.get(get2);            for(KeyValue key  : result2.list())//一行的记录当中包含很多的键值对信息,依次遍历即可            {                 System.out.println(key.toString());                 System.out.println(new String(key.getValue()));                    }            System.out.println("**************************");            /**3------>遍历所有的记录****/            Scan scan = new Scan();            ResultScanner scanner = hTable.getScanner(scan);//scanner中包含很多条行记录            for (Result result3 : scanner)            {                for(KeyValue key  : result3.list())//一行的记录当中包含很多的键值对信息,依次遍历即可                {                     System.out.println(key.toString());                     System.out.println(new String(key.getValue()));                        }            }            System.out.println("**************************");            /**4------>仅仅获取每行的city信息****/            Scan scan1 =new Scan();            ResultScanner scanner1 = hTable.getScanner(scan1 );            for (Result result4 : scanner1)            {                  System.out.println(new String(result4.getRow()));                  System.out.println(new String(result4.getValue("address".getBytes(), "city".getBytes())));            }       }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

代码的运行结果如下: 
这里写图片描述 
这里写图片描述 
对于Hbase的Java api操作就简单的介绍到这里! 
另外对于上面Hbase的介绍,也就介绍到这里,如有问题,欢迎指正!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2岁幼儿头发稀少怎么办 小孩头发太少了怎么办 头发少盘丸子头怎么办 油头发掉的厉害怎么办 头顶头发长得慢怎么办 每次洗头发都掉很多头发怎么办 拔了头发不长怎么办 6岁儿童头发稀少怎么办 2岁宝宝胆子小怎么办 坐到小孩的头怎么办 托班幼儿不刷牙怎么办 两岁的宝宝蛀牙怎么办 小孩在学校被打怎么办 油画棒画在墙上怎么办 宝宝把蜡笔吃了怎么办 吃鸡更新了怎么办开始 数字画涂料干了怎么办 广告画颜料干了怎么办 宝宝断奶后瘦了怎么办 腿一个粗一个细怎么办 两条小腿不一样粗怎么办 两岁宝宝坐不了怎么办 q糖孩子吃多了怎么办 q糖孩子吃的太多怎么办 ps图层不能覆盖怎么办 孩子的字写的不好怎么办 孩子爱打人怎么办 6招 一岁宝宝爱打人怎么办 2岁小朋友爱打人怎么办 小朋友爱动手怎么办4岁 5,6岁爱动手打人怎么办 七个月宝宝大便干燥怎么办 两岁宝宝吐奶怎么办 2岁宝宝轻微蛀牙怎么办 2岁宝宝喝水都吐怎么办 2岁宝宝吐的厉害怎么办 两岁宝宝个子矮怎么办 宝宝吐了一天了怎么办 3岁宝宝吃饭呕吐怎么办 3岁宝宝突然呕吐怎么办 11个月婴儿呕吐怎么办