1、请求流程
(1)当一个表过大时(默认配置是超过10G),HBase会将该表切分成多个region,每个region是由一个regionserver负责管理,当有读写请求时,无需联系master,直接联系相对应的regionserver进行处理。
(2)表的元数据是由"hbase:meta"表负责管理的,"hbase:meta"表的元数据信息由zookeeper负责管理,在"meta-region-server"节点上。
(3)基本工作流程:客户端先联系zk获取meta表的regionserver,同时向此regionserver发送请求,获得它所管理的meta表,然后通过meta表获取所需表的regionserver,最后通过所需表的regionserver发送这次请求,并缓存这次查询信息,以后只要知道了所需表的regions,客户端就可以通过缓存信息定位到region,不用再次查找meta表。
2、区域(region)详解
(1)meta表的ROW格式(区域名):名字空间:表名,起始key,时间戳.MD5码(即编码区域名).
(2)meta表的COLLUN+CELL格式:列族:列限定符,时间戳,value值
(3)split 'test:t1' 'row050' ====== 手动切分t1表
(4)balance ====== 平衡器,将region平均分给regionserver
(5)merge_region 'a','b' ====== 将region合并(a和b是两个region的MD5码)
(6)flush 'test:t1' ====== 将内存中的数据实例化到磁盘
3、写入过程(put)
(1)hbase在写入数据时,将数据写到WAL(write ahead log,预写日志),同时写入到memstore中
(2)WAL作用:当内存数据由于断电或内存溢出等方式导致数据丢失时,可通过WAL进行数据恢复
(3)memstore:hbase数据在内存中的体现,memstore有阈值,如果超出阈值,会被刷写到磁盘变为HFile(StoreFile),也可以通过flush将memstore数据实例化
(4)hbase hfile -h -p -v -f xxx ====== 查看hfile数据(xxx表示region的绝对路径),查看真实数据
(5)hbase wal xxx -j -p -r ====== 查看wal数据(xxx表示wal文件的绝对路径),查看用户在某一时期进行的一系列操作,类似编辑日志
4、文件结构
(1)根级文件
(1-1)WALs:存放预写日志,默认是一个小时滚动一次,在hbase-default.xml中可配置
<property>
<name>hbase.regionserver.logroll.period</name>
<value>3600000</value>
<description>控制预写日志的滚动周期,默认一小时</description>
</property>
(1-2)oldWALs:旧的预写日志,在预写日志超过一小时后,滚动到此目录,默认十分钟后删除,在hbase-default.xml中可配置
<property>
<name>hbase.master.logcleaner.ttl</name>
<value>600000</value>
<description>旧的预写日志被删除的时间,10分钟之后被删除</description>
</property>
(1-3)hbase.id和hbase.version:存放集群的唯一ID和文件格式版本信息
(1-4)data:存放表数据
(2)表级文件:
(2-1).tabledesc:存放.tableinfo文件,使用desc 'test:t1'命令查看
(2-2).tabletmp:table的临时文件
(2-3)xxx:存放区域级文件
(3)region级文件
(3-1)regioninfo:存储表名+起始key
(3-2)recovered.edits:存放区域名等信息,在WAL回放时,任何未提交的修改都会写入该文件中,用于数据的恢复
(3-3)f1:列族文件,存放真实数据,手动刷新一次,会产生一个文件,可以将许多小文件聚合成一个大文件
(3-4)major_compact 'test:t1' ====== 将t1表的小文件聚合,merge操作也可同时将小文件聚合
5、HFile详解
(1)HFile是有序的k-v对,k和v均为字节数组
(2)HFile的结构:在内存中读写压缩快的固定开销,压缩编解码器,k和v的缓存,HFile的索引(可配置,占用内存大小为:(56+AvgKeySize)*NumBlocks)
(3)优化建议:最小块大小,建议在8K-1M之间;顺序读取的话,块建议设置大一些,但对于随机访问效率极低(一个块一个索引,块设计较大,那么索引数会变少),小块比较适合随机访问,但是需要更多的内存((56+AvgKeySize)*NumBlocks);基于压缩编解码器的开销,块大小最小设置在20K-30K之间
(4)压缩编解码器:NONE,LZO,GZ
(5)split 'aaa' 'bbb' ====== 切分region(aaa表示区域名,bbb表示起始key)
(6)move 'aaa' 'bbb' ====== 移动region到指定server(aaa表示编码区域名,bbb表示ServerName(主机名,端口,启动码))
6、put优化
(1)先将多个put对象封装成一个集合,然后发送一个put对象的集合
(2)控制自动刷写:setAutoFlush(false)
(3)不写入预写日志:put.setDurability(Durability.SKIP_WAL)
7、表属性控制
(1)VERSIONS => '1'(版本数,最大建议不超过3)
(2)KEEP_DELETED_CELLS => 'FALSE'(是否保存删除的数据),设为TRUE后,重启hbase,专家模式仍可看到被删除的数据和type,设为FALSE则看不到数据只能看到type
(3)TTL => 'FOREVER'(存活时间(time to live)),超过该时间会删除版本到最小版本数
(4)COMPRESSION => 'NONE'(是否压缩)
(5)MIN_VERSIONS => '0' (最小版本数),经过TTL后的版本数
8、修改表的属性
(1)alter 'test:t1',NAME => 'f1',VERSIONS => 5 ====== 修改f1列族的版本数
(2)get 'test:t1','row1',{COLUMN => 'f1:name',VERSIONS => 4} ====== 获得四个版本的数据
(3)scan 'test:t1',{RAW => true,VERSIONS => 10} ====== 忽略版本数进行原生扫描(专家模式)
(4)alter 'test:t1',NAME => 'f1',TTL => 30 ====== 手动设置TTL为30秒,超过30秒版本数变为最小版本数
(5)alter 'test:t1',NAME => 'f1',COMPRESSION => 'gz' ====== 修改压缩编解码器(必须禁用表:disable 'test:t1')
9、hive和hbase的集成
(1)hbase不支持分析,hive支持
(2)hive映射到hbase已知表
create external table hbase(id string, name string, age string) stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties ("hbase.columns.mapping" = ":key,f1:names,f1:ids") tblproperties ("hbase.table.name" = "hive:user");
(3)hive创建hbase表
create table hbase2(id string, name string, age string) stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties ("hbase.columns.mapping" = ":key, f1:name, f1:age") tblproperties ("hbase.table.name" = "hive:user2");
10、hive支持事务的条件
(1)创建ORC格式表,添加事务支持属性,分桶表
create table user_tx(id int, name string, age int, province string, city string) clustered by (id) into 2 buckets stored as orc tblproperties('transactional' = 'true');
(2)设置支持事务的属性
SET hive.support.concurrency = true;
SET hive.enforce.bucketing = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
SET hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
SET hive.compactor.initiator.on = true;
SET hive.compactor.worker.threads = 1;
(3)插入数据
insert into user_tx select * from user_nopar;