hbase
*时间同步
ntpdate cn.pool.ntp.org
*启动错误,日志查看
1.hdfs日志,hadoop安装目录下的logs目录
2.zookeeper日志
当没有特殊指定zookeeper的日志输出目录的话,zookeeper的日志是在执行zkServer.sh start指令所在的文件夹里
zookeeper日志的名称是:zookeeper.out
3.hbase日志
hbase的日志在hbase安装目录下面有logs目录
*zookeeper
分布式系统协调工具,高可用协调工具
zookeeper上的数据存在于每一个server节点上,每一个节点上的zookeeper节点上保存的数据都是全量数据
zookeeper上保存数据的方式和文件系统保存数据一样
*hbase的数据模型
sql: 在sql的数据库中包含两种元素:即模式(比较强的表结构)和元组(数据记录)
nosql: 在nosql里面一般更强调元组而弱化模式,有些nosql中没有模式,有些nosql有比较弱的模式,比方说有表而没有明确的字段,或者有表有更为广义上的字段组
hbase是nosql的一种,它的设计和使用都是反模式的。它里面不是完全没有模式,它的模式分为三层
1.namespace 类似于mysql的database
2.table 类似于mysql的table
3.column cluster(COLUMN FAMILIES)(列簇) 可以把它认为是mysql里面一个表的多个字段按照某个条件分成多组
一个hbase中可以创建若干个namespace,namespace一般用来做部门或者应用之间的数据隔离
一个namespace下可以创建若干个table,table做不同种类的数据之间的隔离
一个table下可以创建若干个列簇(column families),一般应用中列簇的数量不超过三个,最好只有一个
一个列簇下面可以若干个列成员,一个列成员包括两部分,列名称和列值。一个列簇下面最多可容纳上百万个列成员
hbase的列簇、列成员名称一般都是使用字符串的数据类型
hbase的列值可以是任意类型
hbase对其中所存储的数据不做任何类型上的限制
hbase在存储数据的位置处统一的把数据转换成字节数组类型来进行保存
namespace的基本操作
create_namespace 'bd20'
list_namespace -- 展示hbase有多少个namespace
list_namespace_tables 'bd20' -- 展示bd20数据库下有多少个表
drop_namespace 'bd20'
table的基本操作
-- 创建表
create 'bd20:table_name','c1'
describe 'bd20:table_name'
disable 'bd20:table_name'
drop 'bd20:table_name'
-- alter table 删除一个列簇
alter 'bd20:table1', NAME => 'c1', METHOD => 'delete'
-- alter table 新增一个列簇
alter 'bd20:table1',NAME=>'c2'
-- alter table 修改表的配置参数信息
create 'cms_link','primary_info','system_info'
mysql上所说的一条数据指的是一行数据
hbase中所说的一条数据指的是一行数据中的一个单元格
put 'cms_link','1','primary_info:category_id','19'
get 'cms_link','1'
scan 'cms_link'
*hbase的底层数据存储
hbase的底层数据是按照条来保存的,每一条数据在底层数据文件里面占据一个存储空间,每条数据的格式如下:
rowkey 列簇:列名称 timestamp(版本) 列值
1 primary_info:category_id 9433747838345 19
1 primary_info:title 9433747838345 JeeSite
。。。。
hbase的数据文件是把每条数据以kv的形式来存储的
rowkey+列簇:列名称+时间戳 ------》key
列值 ------》value
因为key上的大部分数据都是冗余的,凡是我们自己设计的key上的数据,尽可能的限定他们的长度
rowkey在设计时要设计的尽可能的短
列簇在设计上要尽可能的短:在尽可能表达列簇的内容意义的时候尽可能的短,一般只用一个字母i
列名称设计上要尽可能的短:要尽可能的表达列值的数据内容的意义,比方说姓名、年龄等:title\color\image
hbase中所有的数据存储都是有序的,首先按照rowkey,然后按照ColumnFamily,再然后column qualifier,最后是timestamp(降序)
*hbase的架构原理
hbase中的每一张表都是分布式存储的
hbase把一张表table划分成多个region,每个region可以散布在不同的regionserver上来对外提供服务。
hbase是根据行业划分region,也就是说hbase是根据rowkey来划分region的。
每个region都有自己的rowkey上下限,第一个region没下限,最后一个region没有上限,当一条记录需要保存在hbase中,hmaster会判断这条记录的rowkey应该分布在哪一个region上,然后转交给这个region所负责的regionserver来执行读写操作
hbase的region的大小会随着里面的数量的增加而增加,当一个region的体量超过256M时,这个region就会分裂(split),分裂的过程由hmaster主导,由hregionserver执行,在分裂的过程中,不对外提供读写服务。
hbase中如果在定义表时不对表进行预分区,那么整个hbase表就只有一个region。为了尽可能的避免分裂最好要对数据进行预分区
create 'stable1','i',SPLITS=>['100','200','300','400']
hbase根据rowkey查找一个表tableA数据的过程
根据root表来确定meta表的位置,root表存在于zookeeper中/hbase/meta-region-server
根据元数据定位tableA的位置,元数据保存在hbase的meta(hbase:meta)表中
定位tableA的位置,然后根据rowkey来确定要查找记录的准确region,根据region定位其所在regionserver,regionserver根据rowkey就检索数据文件中记录的位置从而获取数据。
Table (HBase table)
Region (Regions for the table)
Store (Store per ColumnFamily for each Region for the table)
MemStore (MemStore for each Store for each Region for the table)
StoreFile (StoreFiles for each Store for each Region for the table)
Block (Blocks within a StoreFile within a Store for each Region for the table)
/hbase
/<Table> (Tables in the cluster)
/<Region> (Regions for the table)
/<ColumnFamily> (ColumnFamilies for the Region for the table)
/<StoreFile> (StoreFiles for the ColumnFamily for the Regions for the table)
/hbase
/.logs
/<RegionServer> (RegionServers)
/<WAL> (WAL files for the RegionServer)
*hbase中数据的来源
1.来源自已有的数据文件(批量)
mapreduce
hive
spark
Bulk Loading
2.来源自业务系统不断增加的数据记录(增量)
java api
shell
其他语言+thrift服务
*hbase api操作
1.构建配置参数对象,使用HBaseConfiguration来创建
2.创建Connection对象,使用ConnectionFactory来创建
3.如果执行ddl操作的话需要Admin对象,通过Connection来获取
4.如果执行dml操作的话需要Table对象,通过Connection来获取
往hbase里插入数据,需要Put对象,一个Put对象代表一行数据(多个单元格)
*mapreduce读写hbase
TableInputFormat
TableOutputFormat
TableMapper
TableReducer
TableMapReduceUtil
写hbase需要在job上配置输出格式为TableOutputFormat,reduce的输出kv必须满足写入hbase表的kv类型
可以通过写reduce继承TableReducer来解决这个kv类型的限定
在job中还得设置目标表,可以通过调用TableMapReduceUtil的initTableReducerJob来设置目标表的参数
1.定义reduce类型继承自TableReducer类型
2.在job配置输出的时候使用TableMapReduceUtil的initTableReducerJob,来配置job把数据保存到hbase中的对接参数
mr读取hbase中的数据
1.定义map类型继承TableMapper类型
2.在job上配置输入的时候使用TableMapReduceUtil的initTableMapperJob方法,来配置job从hbase中读取数据的对接参数
作业:
写mapreduce从mysql中获取数据,然后把数据写入到hbase表中,只需要定义一个列簇
*hbase的rowkey设计原则
人员信息表
table:person_info
rowkey:唯一标识 + 姓名
i:name 姓名
i:age 年龄
。。。
1. rowkey长度原则
在满足其他特殊需求的设计许可范围内,rowkey应该设计的尽可能的短, rowkey的长度尽量限定在100字节以内
rowkey的长度最长是64K
rowkey的设计要尽可能的定长
长度尽可能是8字节的整数倍
定长上,如果是字符串类型,空余的字节可以在右边补:0x1F
如果是数值类型,空余的字节可以在左边补:0x00
0x1F是空白字符
常用的操作类:ByteBuffer
Bytes
2.散列原则
如果不散列而顺序的话,在hbase的读写上就会造成热点访问的问题
order 1 ---》hash散列 dlklkskdfsdfafeeww
0000000001 ---> 1000000000
0000000002 ---> 2000000000
0000000003 ---> 3000000000
1.散列的数据内容需要添加在hbase rowkey的高位上
2.散列的实现方式:对顺序的数据求hash、求md5值
生成uuid
对原顺序的数据进行定长逆向后作为散列值
3.唯一性原则
4.业务需求中最频繁的查询条件数据,最好放到rowkey中,这样的话就相当于把这个数据加入到索引中
如果根据列值来进行查询数据的话会触发全表扫描,效率极低,生产环境中尽可能避免这种情况
5.rowkey最好设计成字符串类型,因为rowkey的比较默认情况下是按照字典顺序来进行比较
*hbase的scan中rowkey的限定
在hbase中对rowkey添加startrowkey和stoprowkey,hbase对rowkey的比较过程是按照字节来进行比较的
-233223332
【0x00】【0x00】【0x32】【0x33】【0x33】【0x33】【0x33】【0x33】
1
【0x00】【0x00】【0x00】【0x00】【0x00】【0x00】【0x00】【0x01】
hbase的rowkey是按照字节的字典顺序来进行比较的,因此在限定范围时,要按照字节来限定,而不是某个数据类型的限定方式。
*hbase过滤器
在关系型数据库我们添加条件去查询数据时,通常在sql中添加where语句如:
select * from tableA where col1=123
select * from tableA where col1>123
hbase中的过滤器就等同于关系型sql中where语句
在过滤数据计算上需要做两件事情:
1.比较计算,比较规则
2.取数规则,过滤规则,比较的什么结果的数据会被过滤掉
在hbase上的比较过滤器里面,需要用户提供两个组件:
1.比较器
2.运算符
hbase的过滤器有两种类型:
1.比较过滤器
底层的过滤器,可以通过对hbase表扫数据时添加扫描限定条件从而获取想要的数据内容
2.专有过滤器
是对比较过滤器的封装,是比较过器的简写
1.比较器的类型
BinaryComparator 二进制比较器,用于按字典顺序比较 Byte 数据值 (> < =)
BinaryPrefixComparator 前缀二进制比较器,按前缀比较 (like 'xxx%')
NullComparator 判断给定的是否为空 (is null)
BitComparator 按位比较
RegexStringComparator 正则比较
SubstringComparator 子串比较
LongComparator
2.运算符的类型
LESS <
LESS_OR_EQUAL <=
EQUAL =
NOT_EQUAL <>
GREATER_OR_EQUAL >=
。。。
3.比较过滤器类型
RowFilter,对rowkey进行过滤的过滤器,满足条件的整行数据都会被提取
FamilyFilter,对表的列簇进行过滤,只有满足比较条件的family下的数据才会被提取
QualifierFilter,对满足列成员名称的数据提取出来,只有该列成员的列名称满足条件的数据会被提取
ValueFilter,对列值进行比较查询的过滤器,只有满足该条件的单元格数据才会被提取
如果相对数据的时间进行限制过滤查询的话可以使用:setTimeRange
4.专有过滤器
PrefixFilter,相当于,过滤器:RowFilter
比较器:BinaryPrefixComparator
操作符:EQUAL
ColumnPrefixFilter,相当于,过滤器:QualifierFilter
比较器:BinaryPrefixComparator
操作符:EQUAL
MultipleColumnPrefixFilter,多子列前缀过滤器,指定多个qualifier的过滤器
DependentColumnFilter,综合子列过滤器
FilterList 复合过滤器
*比较过滤器的使用步骤
1.定义比较器对象,对象描述表里的什么字段和什么值进行比较,怎样比较(按字节或按位比较或者包含)
2.使用比较器再加上运算符创建出过滤器对象
3.定义scan对象,然后把过滤器对象设置到scan对象上
4.获取table对象,调用table的getScanner方法,把scan作为参数,即可获取过滤扫描的结果
*二级索引
索引的基本特点
1.索引是一种数据
2.它是排序的
3.他要存储索引值和对应的数据快速定位的地址
hbase原生不支持二级索引,如果想用二级索引的话需要用户自己来创建二级索引机制
分词并索引:solr elisticsearch -----> lucene
案例:
原表:用户信息表(w_user)
二级索引表:用户姓名二级索引表(w_user_name_index)
1.索引表的数据怎么来
a.在原表有数据进入的时候,同时把相应的索引数据存储到索引表(实时更新)
b.如果原表已经有部分数据,则使用mapreduce对原数据进行批量提取,并以索引的形式导入到索引表(批量更新)
2.实时更新的实现方法
1.在所有操作原表的代码里面,添加操作索引表的代码
如:当要往原表插入一条记录的时候,在代码上同时往索引表也添加一条记录
这种方式hbase开发人员来说在代码上太复杂和冗余
因为hbase 只支持行级别的事务,不支持表级别和跨表级别的事务
使用:Tephra来解决hbase跨行跨表一致性问题
2.使用协处理器coprocessor
*协处理器
可以添加到hregionserver上也可以添加到hmaster上
添加到hregionserver的协处理器是可以被分布式的触发和被分布式rpc调用的
协处理器整体上可以分为两种类型:Observer观察者(触发器)和Endpoint终端(存储过程)
定义一个Observer的协处理器,它来监听w_user表,当这张表有数据被新增的时候,触发observer过程
这个过程往w_user_name_index中插入一条记录,rowkey是user表中的name,列名称是user表的rowkey
类型:RegionObserver
1.定义一个类,继承 BaseRegionObserver
重写其prePut方法
在prePut方法里面获取当前正在被put的数据
然后取出name值当做rowkey,取出rowkey当做列名称插入到w_user_name_index表中
2.把代码打成jar包,放入hbase的classpath中,或者放到hdfs上
3.通过表的属性把这个协处理器配置到hbase表上
alter 'bd20:w_user','coprocessor'=>'hdfs:///coprocessores/userindexcoprocess.jar|com.zhiyou.bd20.coprocessor.WUserIndexCorpocessor|1001|'
*phoenix
优点:
1.支持sql
2.支持二级索引
3.支持跨行和跨表的事务
4.支持表关联(join)
5.支持分页
phoenix的事务支持其实是使用的Tephra来实现的