hbase回顾

1、Hbase简介

1、是什么?

Hbase是分布式的存储海量数据的NoSql数据库

2、场景: 实时场景

3、Hbase数据模型:

Table: 数据存储的形式

列簇: Hbase的表结构,一般在创建表的时候指定

rowkey:数据的主键,数据在hbase中是按照rowkey字典序进行排序

列限定符: 类似mysql的字段

region: table的一个分段

store: store是region的分段,store的个数和列簇的个数一样

Namespace: 命名空间,类似mysql的库

Column: 列簇:列限定符表示Column

Cell: rowkey+列簇:列限定符+时间戳

hbase中数据是保存在Table中,要想创建一个Table必须指定表结构[列簇]

Table要想分布式存储,是划分为region保存在不同的机器上。

region中根据列簇划分为不同的store

hbase的表时保存在Namespace下

4、架构:

Master:

职责:

1、负责表的增删改操作

2、负责region的负载均衡,监听regionserver的状态,一旦regionserver宕机,会将宕机的regionserver上的region分配到其他的regionserver上

RegionServer:

职责:

1、负责数据的增删改查

2、负责region的split、storeFile的compact

region: table的一个分段

Store: 一个列簇一个store

memstore: 是一个内存区域。memstore当达到一定阈值或者一定的时间之后就会flush,每次flush都会生成storefile文件

storeFile: 数据存储单元,由memstore flush生成。最终是以HFile这种文件格式保存在HDFS

HLog: 预写日志,数据在写入memstore之前必须先写入HLOG中,主要是为了防止regionserver宕机导致memstore的数据丢失。一个regionserver有一个HLOG

2、Hbase安装和shell使用

1、namespace方面

1、创建namespace: create_namespace '命名空间名称'

2、查看所有的namespace: list_namespace

3、查看某个namespace的所有表: list_namespace_tables '命名空间名称'

4、删除某个namespace: drop_namespace '命名空间名称'

删除namespace之前必须删除namespace下所有的表

5、查看namespace的详情: describe_namespace '命名空间名称'

2、table方面

1、创建表: create '表名','列簇名1','列簇名2',..

2、修改表: alter '表名',{COLUMN=>'列簇名',VERSIONS=>'版本数'}

3、删除表:

1、禁用表: disable '表名'

2、删除: drop '表名'

3、数据方面

1、插入数据: put '表名','rowkey','列簇:列限定符','值'

2、查询:

1、根据rowkey查询数据:

1、查询整行数据: get '表名','rowkey'

2、查询某个列簇的数据: get '表名','rowkey','列簇名'

3、查询某个列的数据: get '表名','rowkey','列簇名:列限定符'

4、查询多个版本的数据: get '表名','rowkey',{COLUMN=>'列簇名:列限定符',VERSIONS=>'版本数'}

2、扫描:

1、查询整个表所有数据: scan '表名'

2、查询某个列簇的数据: scan '表名',{COLUMN=>'列簇名'}

3、查询某个列的数据: scan '表名',{COLUMN=>'列簇名:列限定符'}

4、查询多个版本数据: scan '表名',{COLUMN=>'列簇名:列限定符',VERSIONS=>'版本数'}

5、查询某一段rowkey范围的数据:scan '表名',{STARROW=>'起始rowkey[包含]',STOPROW=>'结束rowkey[不包含]'}

3、修改: put '表名','rowkey','列簇:列限定符','值'

4、删除数据:

1、只删除Cell:

1、delete '表名','rowkey','列簇:列限定符'

2、deleteall '表名','rowkey','列簇:列限定符'

2、删除整行数据: deleteall '表名','rowkey'

5、清空整表数据: truncate '表名'

6、统计表的行数: count '表名'

3、原理

1、架构: 看上面的架构

2、写流程:

1、client向zookeeper请求获取元数据[hbase:meta]表所在的regionserver

2、zookeeper向client返回元数据所在的regionserver

3、client向元数据所在regionserver发起获取元数据的请求

4、元数据所在的regionserver向client返回元数据。client会缓存元数据,后续在查询的时候就可以不用在获取元数据直接从缓存获取

5、client通过元数据得知数据应该写往哪个region,该region处于哪个regionserver,向regionserver发起数据写入请求

6、client先将数据写入HLOG,便于数据的恢复

7、再将数据写入memstore中

8、向client返回消息告知写入完成

3、memstore flush[ flush的单位是region ]

触发条件:

1、达到一定的阈值

1、region中某个memstore的大小达到128M,当前该region的所有memstore都会flush

2、当处于读写高峰期的时候,第一个flush可以延迟,延迟到region中所有memstore的总大小达到128*4的大小会阻塞client的写入,优先flush

3、regionserver中所有的region所有的memstore的总大小达到 java_heap * hbase.regionserver.global.memstore.size * hbase.regionserver.global.memstore.size.lower.limit 大小会进行flush,在flush的时候会按照region中memstore占用的空间大小进行排序,优先flush占用空间大的region

4、当处于读写高峰期的时候,第三个flush可以适当延迟,延迟到regionserver中所有的region的所有的memstore的总大小达到java_heap * hbase.regionserver.global.memstore.size 大小会阻塞client的写入,按照region中memstore占用的空间大小进行排序,优先flush占用空间大的region,一直flush到regionserver所有的memstore占用的总空间的大小小于java_heap * hbase.regionserver.global.memstore.size * hbase.regionserver.global.memstore.size.lower.limit停止flush

5、hlog的文件数达到32的时候,会flush

2、达到一定的时间: 一个小时触发一次flush

3、手动flush: flush '表名'

4、读取数据的流程

1、client向zookeeper请求获取元数据[hbase:meta]表所在的regionserver

2、zookeeper向client返回元数据所在的regionserver

3、client向元数据所在regionserver发起获取元数据的请求

4、元数据所在的regionserver向client返回元数据。client会缓存元数据,后续在查询的时候就可以不用在获取元数据直接从缓存获取

5、client通过元数据得知数据应该写往哪个region,该region处于哪个regionserver,向regionserver发起数据读取请求

6、首先从block cache中获取数据

7、然后从memstore中获取数据

8、最后从storeFile中获取数据

通过布隆过滤器[特点: 如果判断存在则不一定存在,如果判断不存在则一定不存在]判断哪些storeFile中可能存在数据

然后通过StoreFile中HFile文件格式里面的数据索引来找到数据

9、将数据返回给client

5、storeFile compact

原因: memstore每次flush都会生成一个storefile文件,文件数越来越多会影响查询性能,所以需要对进行进行合并

minor compact:

结果: 尽可能的将小文件合并成大文件

过程: 单纯的合并小文件的内容,不会清除无效数据[无效version数据,删除数据..]

触发条件: 小文件[小于128M]数达到3个就会触发

major compact:

结果: 将store中所有的storefile文件合并成一个文件

过程: 在合并的过程中会清除掉无效数据[无效version数据,删除数据..]

触发条件: 默认7天触发一次[一般禁用,采用手动的方式 major_compact '表名']

6、region split

原因: 当region越来越大,后续客户端的读写请求,很大可能都是落在该大region上,对regionserver压力相对比较大,所有为了负载均衡,需要对大region进行split。

0.94版本之前split策略:

当region中某个store的大小达到10G的时候,region就会split

0.94-2.0版本split策略:

regioncounts == 0 || regioncounts>100 ? 10G : Min(10G,2 * 128 * regioncounts * regioncounts * regioncounts)

regioncounts: region所属表在当前regionserver上的region个数

2.0版本之后split策略:

regioncounts == 1 ? 2 * 128M :10G

regioncounts: region所属表在当前regionserver上的region个数

4、API

5、Hbase优化:

1、预分区: [创建表的时候预先分配好region]

1、shell:

1、create '表名','列簇名1',..,SPLITS=>['rowkey1','rowkey2',..]

2、create '表名','列簇名1',..,SPLITS_FILE=>'分割rowkey所处文件路径'

2、api:

admin.createTable(tableDescriber,splitKeys)

2、rowkey设计:

遵循原则:

1、长度原则: hbase的rowkey不能太长,太长之后会多占用存储空间,rowkey太长还会影响client缓存的元数据的条数

工作中,rowkey的长度一般保持在16字节以下

2、唯一性: hbase的两条数据不能rowkey一样

3、hash原则: 让hbase的数据尽可能的均匀分配

热点问题解决方案:

1、加盐[加随机数]

2、字符串反转

3、hash、拼接字符串

3、内存优化: 服务器分配给hbase regionserver/master的内存一般设置为16-48G

4、基础优化:

1、允许hdfs文件追加:hbase数据写入是采用追加的方式,所以需要hdfs支持追加[hdfs默认就是允许追加]

2、增大HDFS最大文件打开数:

如果hbase处于读写高峰期的时候,可能同时打开的文件数比较多,所以此时需要进行调整

3、增加超时时间

如果网络不够好,可能造成读写请求超时,遇到这种情况可以适当的调整超时时间

4、优化写入效率[压缩写入]

写入的时候如果采用压缩写入,速度相对比较快

5、调整client的缓存

调整client的缓存,如果调大能够更多的缓存元数据,减少与hbase的交互次数

6、调整RPC的监听数

如果同一个时间有很多client发起读写请求,就会造成hbase中用来处理client请求的线程数不够用,此时需要进行调整

7、调整hstore的文件大小

调整hstore的大小,能够更好的进行region的split,优化的读写的负载均衡

8、flush、split的参数调整

6、phoenix

1、是什么?

hbase的sql皮肤,主要用来建二级索引

2、phoenix基本应用

1、查看phoenix所有表: !tables

2、创建表

1、hbase中存在表[其实就是phoenix与hbase的已经存在的表建立映射关系]

create table 表名(

字段名 字段类型 primary key, //主键,主键对应Hbase表的rowkey

"列簇名"."列限定符名" 字段类型,

...

)COLUMN_ENCODED_BYTES=0

2、hbase中不存表[phoenix建表的时候会在hbase中同步创建表]:

create table 表名(

字段名 字段类型 primary key, //主键,主键对应Hbase表的rowkey

字段名 字段类型,

...

)COLUMN_ENCODED_BYTES=0 //COLUMN_ENCODED_BYTES=0 表示列名在hbase中不用编码存储

phoenix在建表的时候,会默认将表名、字段名转成大写,如果想要保持小写,需要用""将表名或者字段名括起来

3、查询: select * from ..

4、插入数据: upsert into 表名 values(值,...)

5、修改数据: upsert into 表名 values(值,...)

6、删除数据: delete from 表名 where ...

7、phoenix如果想要映射命名空间的表

1、需要在hbase conf目录配置hbase-site.xml,还需要在客户端配置hbase-site.xml

2、创建schema[创建的schema必须要与命名空间的名称一致]: create schema 命名空间名称

3、使用schema: use 命名空间的名称

4、映射表:

create table 表名(

字段名 字段类型 primary key, //主键,主键对应Hbase表的rowkey

"列簇名"."列限定符名" 字段类型,

...

)COLUMN_ENCODED_BYTES=0

3、二级索引

原因:

hbase中通过rowkey查询数据是可以通过meta元数据表得知rowkey对应的数据在哪个region、哪个regionserver,

但是如果根据value值查询数据的时候,这时候不能够根据meta表得知数据处于哪个region,此时查询是全表扫描,速度比较慢,所以一般都是将需要查询的字段建索引,提高查询性能

全局二级索引:

1、原理: 新建一个hbase的表,将建立索引字段的值与原来的rowkey作为新表的rowkey,后续查询的时候直接查询新表,如果新表查不到再全表扫描原表

2、建立索引的语法: create index 索引名 on 表名(字段名) [include(字段名2,..)]

1、表名大小,字段名也大写的情况:create index p_index on person(name)

2、映射表:create index p_index on "person"("列簇名"."列限定符")

3、删除索引: drop index 索引名 on 表名

本地二级索引:

1、原理:

在原表中插入索引数据,索引的数据的rowkey=__索引字段value值_原来的rowkey,后续根据索引字段的值查询的时候,先查索引数据得到原来的rowkey,在根据原来的rowkey查询原来的详情数据[工作中一般采用此种方式]

2、语法:create local index 索引名 on 表名(字段名)

1、表名大小,字段名也大写的情况:create local index p_index on person(name)

2、映射表:create local index p_index on "person"("列簇名"."列限定符")

3、删除索引:drop index 索引名 on 表名

4、协处理器

协处理器其实类似触发器,就是hbase在执行某些操作[put、get、scan、flush..]的时候触发我们指定的操作逻辑。

phoenix的二级索引其实就是通过协处理器完成的

自定义协处理器:

1、实现两个接口[RegionObserver、RegionCoprocessor ]:

2、重新一个方法

  @Override

  public Optional getRegionObserver() {

return Optional.of(this);

  }

3、定义指定动作触发的方法

prePut: pre开头的方法是在指定动作执行之前执行

postPut: post开头的方法是在指定动作执行之后执行

4、打包上传HDFS

5、禁用表: disable '表名'

6、修改表,添加协处理器

alter '表名', METHOD => 'table_att', 'Coprocessor'=>'hdfs打包上传jar路径|自定义协处理器的全类名|优先级|参数'

7、启动表:enable '表名'

5、hive与hbase的整合

通过hive整合hbase,后续就可以在hive上写sql语句操作hbase的数据,进行统计分析

内部表:

创建表: hive建内部表的时候,hbase的表不能够存在,如果存在则报错

删除表: 内部删除的时候会同步删除Hbase的表

语法:

CREATE TABLE hive表名(hive字段名1 类型, hive字段名2 类型,..)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' //指定hive的数据存储在hbase中

WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,列簇名:列限定符名,列簇名:列限定符名,..") //hbase.columns.mapping将hive的字段与hbase表的列簇、列限定符建立映射,:key代表rowkey

TBLPROPERTIES("hbase.table.name" = "hbase表名");

外部表:

创建表: 其实将hive表与hbase已经存在的表建立一个映射关系,如果hbase的表不存在,则报错

删除表: 内部删除的时候不会同步删除Hbase的表

语法:

CREATE EXTERNAL TABLE hive表名(hive字段名1 类型, hive字段名2 类型,..)

STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' //指定hive的数据存储在hbase中

WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,列簇名:列限定符名,列簇名:列限定符名,..") //hbase.columns.mapping将hive的字段与hbase表的列簇、列限定符建立映射,:key代表rowkey

TBLPROPERTIES("hbase.table.name" = "hbase表名");

你可能感兴趣的:(hbase回顾)