HBase

一、HBase简介

1、Hbase是什么?
	Hbase是分布式存储海量数据的Nosql数据库
2、Hbase的应用场景: 实时 
3、数据模型
	1、Table: 数据存储形式
	2、Region: table的一个分段,region保存在regionserver上面
	3、Store: store的个数与列簇的个数一致
	4、rowkey: hbase的数据的主键。
		数据在hbase中是有序的,按照rowkey的字典序进行排序
	5、列簇: hbase的表结构的一部分[相当于mysql的字段]
	6、列限定符: hbase数据的一部分
	7、Column: 列簇:列限定符
	8、Cell: rowkey+列簇+列限定符+时间戳
	9、Namespace: 命名空间,相当于mysql的库
4、架构
	1、Master
		职责:
			1、负责监控Regionserver,一旦regionserver宕机,会迁移数据到其他活着的regionserver上面
			2、负责表结构的变更
	2、RegionServer
		职责:
			1、负责数据的操作[增删改查]
			2、负责region的split、compact
		Region: 表的一个分段
			Store: store的个数与列簇的个数一致
				memstore: 是一块内存区域,数据在写入hbase的时候是写入memstore中,memstore达到一定的阈值之后会进行flush,每次flush都会生成一个storeFile
				storeFile: memstore flush生成
					storeFile最终是以Hfile这种文件格式保存在HDFS
		HLOG: 每个regionserver只有一个HLOG,数据在写入memstore之前会先写入HLOG,当memstore进行flush的时候,HLOG会删除预写日志中该memstore的数据
	3、zookeeper: 保存元数据的位置,master监听regionserver也是借助zookeeper

二、Hbase安装以及shell使用

1、Namespace相关
	1、创建Namespace: create_namespace '命名空间名称'
	2、删除Namespace: drop_namespace '命名空间名称'
		删除命名空间的时候,必须先删除命名空间下所有表
	3、查看命名空间下所有表: list_namespace_tables '命名空间名称'
	4、查看所有的命名空间: list_namespace
2、Table相关
	1、创建表: create '表名','列簇名1',...
	2、删除表:
		1、禁用表: disable '表名'
		2、删除表: drop '表名'
	3、查看所有表: list
	4、查看表的详情信息: describe '表名'
	5、创建表的时候指定VERSION:
		create '表名',{NAME=>'列簇名',VERSIONS=>'版本数'}
3、数据相关
	1、插入数据: put '表名',rowkey,'列簇:列限定符','值'
	2、查看数据
		1、根据rowkey查询数据
			1、查询整行数据:get '表名',rowkey
			2、查询某个列簇的数据: get '表名',rowkey,'列簇'
			3、查询某个列的数据: get '表名',rowkey,'列簇:列限定符'
		2、扫描
			1、查询整表数据: scan '表名'
			2、查询某个列簇的数据: scan '表名',{COLUMNS=>'列簇'}
			3、查询某个列的数据: scan '表名',{COLUMNS=>'列簇:列限定符'}
			4、查询某几个版本的数据: scan '表名',{COLUMNS=>'列簇:列限定符',VERSIONS=>'版本数'}
	3、清空表数据: truncate '表名'
	4、统计表条数: count '表名'

三、原理

1、写入流程
	1、client向zookeeper发起获取元数据位置的请求
	2、zookeeper向client返回元数据所处的位置信息
	3、client向元数据所在的regionserver发起获取元数据的请求
	4、元数据所在的regionserver给client返回元数据,client会缓存元数据
	5、client根据元数据信息知道当前数据应该插入到哪个region,region处于哪个regionserver
	6、client向数据所在regionserver发起写入请求
	7、首先将数据写入HLOG中
	8、HLOG写入成功之后,再将数据写入memstore中
	9、向client返回写入完成信息
2、flush触发条件
	flush的时候是对整个region进行flush
	1、region中某一个memstore的大小达到128M的时候会进行flush
	2、当处于写高峰的时候,第一个触发条件可以适当延迟,延迟到region中所有的memstore的大小达到4*128M的时候会阻塞client的写入,优先flush
	3、regionserver中所有的region的所有的memstore的大小达到java_heap * hbase.regionserver.global.memstore.size * hbase.regionserver.global.memstore.size.lower.limit的时候会进行flush
	4、当处于写高峰的时候,第三个触发条件可以适当延迟,延迟到regionserver中所有的memstore的大小达到java_heap * hbase.regionserver.global.memstore.size,会阻塞client的写入,优先flush
	4、当预写日志的个数达到32,会触发flush
	5、当某个region中memstore的最后一次flush的时间与当前时间相比达到一个小时,会进行flush
	6、手动flush: flush '表名'
3、读流程
	1、client向zookeeper发起获取元数据位置的请求
	2、zookeeper向client返回元数据所处的位置信息
	3、client向元数据所在的regionserver发起获取元数据的请求
	4、元数据所在的regionserver给client返回元数据,client会缓存元数据
	5、client根据元数据信息知道当前数据应该插入到哪个region,region处于哪个regionserver
	6、client向数据所在regionserver发起读取请求
	7、首先从block cache中读取数据
	8、然后从memstore中读取数据
	9、从storeFile中读取数据
		store中storeFile个数可能比较多,如何快速找到数据处于哪个storeFile?
			1、通过布隆过滤器,判断数据可能存在哪些storeFile
				布隆过滤器特点: 如果判断存在,则不一定存在,如果判断不存在,则一定不存在
			2、通过HFile这种文件格式中的数据索引找到数据所在的位置
				HFile文件: Hfile中包含数据信息,数据的索引信息,数据元数据信息
	10、将数据返回给client
4、compact
	原因: 当memstore flush会生成一个storeFile文件,随着时间的流逝,storeFIle文件会越来越多,会影响查询性能,所以hbase提供文件的合并机制
	1、minor compact:
		触发条件: 当小文件[小于128M]数据达到3个的时候会触发
		合并过程: 只是单纯的合并文件的内存,不会清除过期数据或者无效数据
		合并结果: 将小文件合并成大文件
	2、major compact:
		触发条件: 7天一次
		合并过程: 在合并的过程中,会清除清除过期数据或者无效数据
		合并结果: 将store中是所有文件合并成一个文件
5、split
	原因: 当数据写入region,时间过长之后,region越来越大,后续请求大部分可能都会落在该region上,导致数据的读写请求负载不均衡
	0.94版本之前: 当region中某个store的大小达到10G,该region就会进行split
	0.9-2.0版本: 会根据region所属表在当前regionserver上有几个region[N]
		N==0 || N>100 ? 10G : Min(10G,2* 128M *N^3)
	2.0版本之后: 会根据region所属表在当前regionserver上有几个region[N]
		N==1 ? 2*128M : 10G

四、Hbase优化

1、预分区[在创建表的的时候多创建几个region]:
	原因: 默认情况下,创建表的时候只有一个region,前期所有的请求都会落在这一个region上,会对region所在的regionserver造成请求压力
	1、shell
		1、create '表名','列簇名',SPLITS=>['rowkey1','rowkey2',..]
			create 'person','f1',SPLITS=>['10','11'] 
			此时会创建三个region。
			第一个region的起始rowkey是'',结束rowkey是'10'
			第二个region的起始rowkey是'10',结束rowkey是'11'
			第三个region的起始rowkey是'11',结束rowkey是''
		2、create '表名','列簇名',SPLITS_FILE=>'文件路径'
	2、api
		admin.createTable(TableDescribetor,splitKeys)
2、rowkey的设计
	rowkey的原则:
		1、长度原则: rowkey的长度不要太长
			rowkey太长会占用过多的磁盘空间
			rowkey过长会导致client端缓存的元数据会比较少
		2、唯一原则: 每条数据的rowkey必须唯一
		3、hash原则: 让数据不会产生倾斜
	热点问题的解决方案:
		1、字符串的反转
		2、hash
		3、加盐-加随机数
3、内存优化:hbase分配的内存不要太多,16-40G比较合适
4、基础优化
	1、让HDFS能够追加
	2、调整监听client的PRC的个数
	3、超时时间的配置
	4、flush的时候10G配置的调整
	5、flush、compact、split的参数配置
	6、最大文件打开数
	7、客户端缓存
	8、写入效率-压缩

五、phoenix

1、phoenix shell操作
	1、查看所有表: !tables
	2、创建表:
		1、Hbase中没有表[会在hbase中同步创建表]
			create table 表名(
				字段名 字段类型 primary key,
				字段名 字段类型,
				字段名 字段类型,
				....
				[constraint 主键名称 on(字段1,字段2)] //组合主键,是上面没有指定primary key的时候使用
			)COLUMN_ENCODED_BYTES=0
			COLUMN_ENCODED_BYTES=0:代表不对字段进行编码
			在创建表的时候,会同步的在hbase中创建表
			表名会自动的转成大写,如果想要保持小写,需要通过""括起来
		2、Hase中有表[在phoenix中建表建立映射]
			create table 表名(
				字段名 字段类型 primary key,
				"列簇"."字段名" 字段类型, //如果hbase中列簇与列限定符为小写,需要用""括起来
				字段名 字段类型,
				)COLUMN_ENCODED_BYTES=0
	3、创建视图[视图只能查看数据,不能修改/删除/插入数据]
			create view 视图名(
				字段名 字段类型 primary key,
				"列簇"."字段名" 字段类型, //如果hbase中列簇与列限定符为小写,需要用""括起来
				字段名 字段类型,
				)COLUMN_ENCODED_BYTES=0
	4、删除表与视图
		1、删除表: drop table 表名
		删除表的时候会同步删除hbase的表
		2、删除视图: drop view 视图名
		删除视图的时候不会删除hbase的表
	5、插入数据: upsert into 表名 values(值,...)
	6、查询数据: select * from 表名
2、jdbc
3、协处理器
	用途: 在向hbase表插入/删除/查询之前或者之后自动干什么事情
	1、编程class实现RegionObserver、RegionCoprocessor 
	2、重写方法:
	  @Override
	  public Optional<RegionObserver> getRegionObserver() {
		return Optional.of(this);
	  }
	3、重新动作方法[在put/get/scan/delete之前[prePut/Get/Delete]或者put/get/scan/delete之后做操作[postPut/Get/Delete]]
	4、打包上传HDFS
	5、禁用表
	6、修改表,给表加载协处理器
		alter '表名', METHOD => 'table_att', 'Coprocessor'=>'jar所处HDFS路径| 协处理器所在的全类名|优先级|参数'
	7、启动表: enable
	8、通过动作[put/get/scan/delete]查看协处理器是否正常
4、二级索引
	二级索引的实现主要是通过协处理器完成
	原因: 
		hbase中查询速度快主要是因为可以用待查询数据的rowkey通过meta元数据找到rowkey处于哪个region,
		region处于regionserver.但是如果想要根据value值查询的是,没办法通过meta元数据找到数据处于哪个region,哪个regionserver,所以只能全部扫描,效率低
	1、全局二级索引
		1、原理: 将建立索引的字段的值与原来的rowkey组成新的rowkey,将include中包含的字段名作为列限定符,将include中包含的字段值作为新值,将新rowkey、列限定符、新值放入新创建的索引表中。
				查询的时候优先查询索引表,如果索引表不满足,则继续查找原表[全部扫描]
		2、创建: create index 索引名 on 命名空间名称.表名(字段名,..) [include(字段名,..)]
		//如果表是映射表,则字段名必须用: 列簇名.列名
		3、删除: drop index 索引名 on 命名空间名称.表名
	2、本地二级索引
		1、原理: 
			在原表中插入数据,插入的数据rowkey=__索引字段值_.._原来的rowkey
			后续根据字段值查询的时候,首先查新rowkey,得到原来的rowkey,再通过原来的rowkey查询原始数据
		2、创建: create local index 索引名 on 命名空间名称.表名(字段名,..)
		3、删除: drop index 索引名 on 命名空间名称.表名
5、hbase与hive整合
	1、内部表[在hive建表的时候,会同步在hbase创建表,如果hbase的表已经存在,则报错]
	CREATE TABLE hive_hbase_emp_table(
		字段名 字段类型,
		....)
		STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
		WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,列簇名:列名,...")
		TBLPROPERTIES ("hbase.table.name" = "hbase表名");

	2、外部表[在hive建表的时候,不会同步在hbase创建表,如果hbase的表不存在,则报错]
		CREATE EXTERNAL TABLE hive_hbase_emp_table(
		字段名 字段类型,
		....)
		STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
		WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,列簇名:列名,...")
		TBLPROPERTIES ("hbase.table.name" = "hbase表名");
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值