Skip to content

Latest commit

 

History

History
518 lines (339 loc) · 14.7 KB

HBase基础知识.md

File metadata and controls

518 lines (339 loc) · 14.7 KB

HBase基础知识

一、HBase简介

  • HBase – Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。HBase利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为协调工具。

  • 思考:如何存储物流信息

    运单号:625311858890
    
    2018-01-07 10:09:25	上海			已发货
    2018-01-07 18:27:32	上海航空部		已收件
    2018-01-07 20:25:38	快件离开上海航空部	已发往北京
    2018-01-09 08:27:14	北京回龙观		派件中
    2018-01-09 12:37:37	北京回龙观		已签收
    

二、HBase三要素

  • 1、主键:Row Key (主键是用来检索记录的主键,访问hbase table中的行,只有三种方式:)

    • 通过单个row key访问

    • 通过row key的range

    • 全表扫描(scan)

  • 2、列族:Column Family

    • 列族在创建表的时候声明,一个列族可以包含多个列,列中的数据都是以二进制形式存在,没有数据类型。
  • 3、时间戳:timestamp

    • HBase中通过row和columns确定的为一个存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引

三、HBASE基础知识

  • 1、物理存储

    • able 在行的方向上分割为多个HRegion,一个region由[startkey,endkey)表示,每个HRegion分散在不同的RegionServer中
  • 2、架构体系

  • Client 包含访问hbase 的接口,client 维护着一些cache 来加快对hbase 的访问,比如regione 的位置信息

  • Zookeeper

    • 保证任何时候,集群中只有一个running master

    • 存贮所有Region 的寻址入口

    • 实时监控Region Server 的状态,将Region server 的上线和下线信息,实时通知给Master

    • 存储Hbase 的schema,包括有哪些table,每个table 有哪些column family

  • Master 可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行

    • 为Region server 分配region

    • 负责region server 的负载均衡

    • 发现失效的region server 并重新分配其上的region

  • 3、HBase的逻辑梳理

    • HBase中有两张特殊的Table,-ROOT-(hbase:namespace)和.META.(hbase:meta)

      • -ROOT-(hbase:namespace) :记录了.META.(hbase:meta)表的Region信息,-ROOT-(hbase:namespace)只有一个region

      • .META.(hbase:meta) :记录了用户创建的表的Region信息,.META.(hbase:meta)可以有多个regoin

    • Zookeeper中记录了-ROOT-(hbase:namespace)表的location

    • Client访问用户数据之前需要首先访问zookeeper,然后访问-ROOT-(hbase:namespace)表,接着访问.META.(hbase:meta)表,最后才能找到用户数据的位置去访问

四、Region Server

  • 维护Master 分配给它的region,处理对这些region 的IO 请求

  • 负责切分在运行过程中变得过大的region

可以看出,client 访问hbase 上数据的过程并不需要master 参与,寻址访问先zookeeper再regionserver,数据读写访问regioneserver。HRegionServer主要负责响应用户I/O请求,向HDFS文件系统中读写数据,是HBase中最核心的模块。 

五、系统架构

六、HBASE与相关软件

  • hadoop-2.2.0

  • hbase-0.96.2-hadoop2

  • JDK7

  • RHEL6.3

  • 前提条件:本机或集群环境下hadoop.1.1.2已经安装成功

七、HBase Shell

  • hbase提供了一个shell的终端给用户交互(#$HBASE_HOME/bin/hbase shell )
名称 命令表达式
创建表 create '表名称', '列族名称1','列族名称2','列族名称N'
添加记录 put '表名称', '行名称', '列名称:', '值'
查看记录 get '表名称', '行名称'
查看表中的记录总数 count '表名称'
删除记录 delete '表名' ,'行名称' , '列名称'
删除一张表 先要屏蔽该表,才能对该表进行删除,第一步 disable '表名称' 第二步 drop '表名称'
查看所有记录 scan "表名称"
查看某个表某个列中所有数据 scan "表名称" , {COLUMNS=>'列族名称:列名称'}
更新记录 就是重写一遍进行覆盖

八、HBASE Shell的DDL操作(数据库操作语言))

  • 1、创建表

      >create 'users','user_id','address','info'
      表users,有三个列族user_id,address,info
    
  • 2、列出全部表

      >list 
    
  • 3、得到表的描述

      >describe 'users'
    
  • 4、创建表

      >create 'users_tmp','user_id','address','info'
    
  • 5、删除表

      >disable 'users_tmp'
      >drop 'users_tmp'
    

-------------------------------其他操作----------------------------------

  • 其他操作

      #$HBASE_HOME/bin/hbase shell
      …… 
      >quit 
    
      >exists 'users'
      >is_enabled 'users'
      >is_disabled 'users
    

九、HBASE Shell的DML操作(数据操作语言)

  • 1、添加记录

      put 'users','xiaoming','info:age','24';
      put 'users','xiaoming','info:birthday','1987-06-17';
      put 'users','xiaoming','info:company','alibaba';
      put 'users','xiaoming','address:contry','china';
      put 'users','xiaoming','address:province','zhejiang';
      put 'users','xiaoming','address:city','hangzhou';
      put 'users','zhangyifei','info:birthday','1987-4-17';
      put 'users','zhangyifei','info:favorite','movie';
      put 'users','zhangyifei','info:company','alibaba';
      put 'users','zhangyifei','address:contry','china';
      put 'users','zhangyifei','address:province','guangdong';
      put 'users','zhangyifei','address:city','jieyang';
      put 'users','zhangyifei','address:town','xianqiao';
    
  • 2、获取一条记录

    • 1.取得一个id的所有数据

        >get 'users','xiaoming'
      
    • 2.获取一个id,一个列族的所有数据

        >get 'users','xiaoming','info'
      
    • 3.获取一个id,一个列族中一个列的所有数据

        get 'users','xiaoming','info:age'
      
  • 3、更新记录

      >put 'users','xiaoming','info:age' ,'29'
      >get 'users','xiaoming','info:age'
      >put 'users','xiaoming','info:age' ,'30'
      >get 'users','xiaoming','info:age'
    
  • 4、获取单元格数据的版本数据

      >get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>1}
      >get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>2}
      >get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>3}
    
  • 5、获取单元格数据的某个版本数据

      〉get 'users','xiaoming',{COLUMN=>'info:age',TIMESTAMP=>1364874937056}
    
  • 6、全表扫描

      >scan 'users'
    
  • 7、删除xiaoming值的'info:age'字段

      >delete 'users','xiaoming','info:age'
      >get 'users','xiaoming'
    
  • 8、删除整行

      >deleteall 'users','xiaoming'
    
  • 9、统计表的行数

      >count 'users'
    
  • 10、清空表

      >truncate 'users'
    

十、HBASE的Java_API

  • hbase操作必备

      //hbase操作必备
      private static Configuration getConfiguration() {
      	Configuration conf = HBaseConfiguration.create();
      	conf.set("hbase.rootdir", "hdfs://hadoop0:9000/hbase");
      	//使用eclipse时必须添加这个,否则无法定位
      	conf.set("hbase.zookeeper.quorum", "hadoop0");
      	return conf;
      }
    
  • 创建一张表

      //创建一张表
      public static void create(String tableName, String columnFamily) throws IOException{
      	HBaseAdmin admin = new HBaseAdmin(getConfiguration());
      	if (admin.tableExists(tableName)) {
      		System.out.println("table exists!");
      	}else{
      		HTableDescriptor tableDesc = new HTableDescriptor(tableName);
      		tableDesc.addFamily(new HColumnDescriptor(columnFamily));
      		admin.createTable(tableDesc);
      		System.out.println("create table success!");
      	}
      }
    
  • 添加一条记录

      //添加一条记录
      public static void put(String tableName, String row, String columnFamily, 
      			String column, String data) throws IOException{
      	HTable table = new HTable(getConfiguration(), tableName);
      	Put p1 = new Put(Bytes.toBytes(row));
      	p1.add(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(data));
      	table.put(p1);
      	System.out.println("put'"+row+"',"+columnFamily+":"+column+"','"+data+"'");
      }
    
  • 读取一条记录

      //读取一条记录
      public static void get(String tableName, String row) throws IOException{
      	HTable table = new HTable(getConfiguration(), tableName);
      	Get get = new Get(Bytes.toBytes(row));
      	Result result = table.get(get);
      	System.out.println("Get: "+result);
      }
    
  • 显示所有数据

      //显示所有数据
      public static void scan(String tableName) throws IOException{
      	HTable table = new HTable(getConfiguration(), tableName);
      	Scan scan = new Scan();
      	ResultScanner scanner = table.getScanner(scan);
      	for (Result result : scanner) {
      		System.out.println("Scan: "+result);
      	}
      }
    
  • 删除表

      //删除表
      public static void delete(String tableName) throws IOException{
      	HBaseAdmin admin = new HBaseAdmin(getConfiguration());
      	if(admin.tableExists(tableName)){
      		try {
      		  admin.disableTable(tableName);
      		  admin.deleteTable(tableName);
      		} catch (IOException e) {
      		  e.printStackTrace();
      		  System.out.println("Delete "+tableName+" 失败");
      		}
      	}
      	System.out.println("Delete "+tableName+" 成功");
      }
    
  • 主函数

      public static void main(String[] args) throws IOException {
      	String tableName="hbase_tb";
      	String columnFamily="cf";
    
      	HBaseTestCase.create(tableName, columnFamily);
      	HBaseTestCase.put(tableName, "row1", columnFamily, "cl1", "data");
      	HBaseTestCase.get(tableName, "row1");
      	HBaseTestCase.scan(tableName);
      	HBaseTestCase.delete(tableName);
      }
    

十一、练习——详单入库

  • 1、题目要求(一)

    • HBASE表定义为:

        >create 'wlan_log', 'cf'
      
    • 源文件数据增加一个字段rowkey

        RowKey设计:
        msisdn:日期时间串(yyyyMMddHHmmss)
      
  • 2、解题方法

    • 1>HBASE结合MapReduce批量导入

      static class BatchImportMapper extends Mapper<LongWritable, Text, LongWritable, Text>{ SimpleDateFormat dateformat1=new SimpleDateFormat("yyyyMMddHHmmss"); Text v2 = new Text();

       protected void map(LongWritable key, Text value, Context context) throws 
       java.io.IOException ,InterruptedException {
       	final String[] splited = value.toString().split("\t");
       	try {
       		final Date date = new Date(Long.parseLong(splited[0].trim()));
       		final String dateFormat = dateformat1.format(date);
       		String rowKey = splited[1]+":"+dateFormat;
       		v2.set(rowKey+"\t"+value.toString());
       		context.write(key, v2);
       	} catch (NumberFormatException e) {
       		final Counter counter = context.getCounter("BatchImport", "ErrorFormat");
       		counter.increment(1L);
       		System.out.println("出错了"+splited[0]+" "+e.getMessage());
       	}
       };
      

      }

      static class BatchImportReducer extends TableReducer<LongWritable, Text, NullWritable>{ protected void reduce(LongWritable key, java.lang.Iterable values, Context context) throws java.io.IOException ,InterruptedException { for (Text text : values) { final String[] splited = text.toString().split("\t");

       		final Put put = new Put(Bytes.toBytes(splited[0]));
       		put.add(Bytes.toBytes("cf"), Bytes.toBytes("date"), Bytes.toBytes(splited[1]));
       		//省略其他字段,调用put.add(....)即可
       		context.write(NullWritable.get(), put);
       	}
       };
      

      }

      public static void main(String[] args) throws Exception { final Configuration configuration = new Configuration(); //设置zookeeper configuration.set("hbase.zookeeper.quorum", "hadoop0"); //设置hbase表名称 configuration.set(TableOutputFormat.OUTPUT_TABLE, "wlan_log"); //将该值改大,防止hbase超时退出 configuration.set("dfs.socket.timeout", "180000");

       final Job job = new Job(configuration, "HBaseBatchImport");
      
       job.setMapperClass(BatchImportMapper.class);
       job.setReducerClass(BatchImportReducer.class);
       //设置map的输出,不设置reduce的输出类型
       job.setMapOutputKeyClass(LongWritable.class);
       job.setMapOutputValueClass(Text.class);
      
       job.setInputFormatClass(TextInputFormat.class);
       //不再设置输出路径,而是设置输出格式类型
       job.setOutputFormatClass(TableOutputFormat.class);
      
       FileInputFormat.setInputPaths(job, "hdfs://hadoop0:9000/input");
      
       job.waitForCompletion(true);
      

      }

  • 3、查询

      (1)按RowKey查询
      (2)按手机号码查询
      (3)按手机号码的区域查询
    
    • 查询手机13450456688的所有上网记录

        查询手机13450456688的所有上网记录
        public static void scan(String tableName) throws IOException{
        	HTable table = new HTable(getConfiguration(), tableName);
        	Scan scan = new Scan();
        	scan.setStartRow(Bytes.toBytes("13450456688:/"));
        	scan.setStopRow(Bytes.toBytes("13450456688::"));
        	ResultScanner scanner = table.getScanner(scan);
        	int i=0;
        	for (Result result : scanner) {
        		System.out.println("Scan: "+i+++" "+result);
        	}
        }
      
    • 查询134号段的所有上网记录

        查询134号段的所有上网记录
        public static void scanPeriod(String tableName) throws IOException{
        		HTable table = new HTable(getConfiguration(), tableName);
        		Scan scan = new Scan();
        		scan.setStartRow(Bytes.toBytes("134/"));
        		scan.setStopRow( Bytes.toBytes("134:"));
        		scan.setMaxVersions(1);
        		ResultScanner scanner = table.getScanner(scan);
        		int i=0;
        		for (Result result : scanner) {
        			System.out.println("Scan: "+i+++" "+result);
        		}
        }
      

十二、思考

  • HBASE是什么数据库,与普通RDBMS有什么区别

  • HBASE的结构

  • HBASE的常用命令