版权声明:本文为博主原创文章,未经博主允许不得转载。
一、Hbase 简介
HBase – Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。
HBase利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为协调工具。
上述附件为原生java代码操作Hbbase数据库的代码,可供下载学习。
JAR包: hbase-0.98.14-hadoop2-bin.tar.gz
虚拟环境:hadoop0(主机)
hadoop1(从节点)
hadoop2(从节点)
二、HBase(NoSQL)的数据模型
2.1 表(table),是存储管理数据的。
2.2 行键(row key),类似于MySQL中的主键。
行键是HBase表天然自带的。
2.3 列族(column family),列的集合。
HBase中列族是需要在定义表时指定的,列是在插入记录时动态增加的。
HBase表中的数据,每个列族单独一个文件。
2.4 时间戳(timestamp),列(也称作标签、修饰符)的一个属性。
行键和列确定的单元格,可以存储多个数据,每个数据含有时间戳属性,数据具有版本特性。
如果不指定时间戳或者版本,默认取最新的数据。
2.5 存储的数据都是字节数组。
2.6 表中的数据是按照行键的顺序物理存储的。
三、HBase的物理模型
3.1 HBase是适合海量数据(如20PB)的秒级简单查询的数据库。
3.2 HBase表中的记录,按照行键进行拆分, 拆分成一个个的region。
许多个region存储在region server(单独的物理机器)中的。
这样,对表的操作转化为对多台region server的并行查询。
四、HBase的体系结构
HBase是主从式结构,HMaster、HRegionServer
五、HBase伪分布安装
5.1 解压缩(tar -zxvf hbase-0.94.7-security.tar.gz)
重命名(mv hbase-0.94.7-security hbase)
设置环境变量(vi /etc/profile/ export HBASE_HOME=/usr/local/hbase :$HBASE_HOME/bin:
5.2 修改$HBASE_HOME/conf/hbase-env.sh
修改内容如下: 切换到 cd /usr/local/hbase/conf/ 然后ls
然后 vi hbase-env.sh
export JAVA_HOME=/usr/local/jdk
export HBASE_MANAGES_ZK=true
5.3 修改$HBASE_HOME/conf/hbase-site.xml,修改内容如下:切换到 cd /usr/local/hbase/conf/ 然后ls 然后 vi hbase-site.xml (把下面都复制到 configuration节点里)
<property> <name>hbase.rootdir</name> <value>hdfs://hadoop0:9000/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>hadoop0</value> </property> <property> <name>dfs.replication</name> <value>1</value> </property>
5.4 (可选)文件regionservers的内容为hadoop0
5.5 启动:执行命令start-hbase.sh (在hbase 的bin目录下执行此命令:cd /usr/local/hbase/bin)
停止:执行命令stop-hbase.sh
启动hbase之前,确保hadoop是运行正常的,并且可以写入文件*******
5.6 hbase启动验证:(1)执行jps,发现新增加了3个java进程,分别是HMaster、HRegionServer、HQuorumPeer
(2)使用浏览器访问http://hadoop0:60010 (可以看到系统表 和 hbase的服务节点,启动情况)
六、HBase表操作
总体概述:
hbase 提供了shell 编辑环境: cd /usr/local/hbase/bin/ 目录下 执行 hbase shell 进入 表操作环境
一、创建表 :create '表名称', '列族名称1','列族名称2','列族名称N'
二、添加记录 : put '表名称', '行名称', '列名称:', '值'
三、查看记录 :get '表名称', '行名称'
查看某个表某个列中所有数据:scan "表名称" , {COLUMNS=>'列族名称:列名称'}
查看表中的记录总数:count '表名称'
查看所有记录:scan "表名称"
五、删除记录 :delete '表名' ,'行名称' , '列名称'
删除一张表:先要屏蔽该表,才能对该表进行删除,第一步 disable '表名称' 第二步 drop '表名称'
六、更新记录 :就是重写一遍进行覆盖
1、创建表
>create 'users','user_id','address','info' (表users,有三个列族user_id,address,info) 无后缀不像mysql 带个 ; >list(回车,查看有哪些表) >describe 'users'(得到表的描述)
2、添加记录:
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'
3、查看记录
3.1、取得一个id的所有数据
>get 'users','xiaoming'
3.2、获取一个id,一个列族的所有数据
>get 'users','xiaoming','info'
3.3、获取一个id,一个列族中一个列的所有数据
>get 'users','xiaoming','info:age'
3.3、全表扫描(相当于:selcec * from users;)
>scan 'users' hbase(main):002:0> scan 'users' ROW COLUMN+CELL xiaoming column=address:city, timestamp=1419576122975, value=hangzhou xiaoming column=address:contry, timestamp=1419576122283, value=china xiaoming column=address:province, timestamp=1419576122856, value=zheji ang xiaoming column=info:age, timestamp=1419577073867, value=29 xiaoming column=info:birthday, timestamp=1419576122202, value=1987-06- 17 xiaoming column=info:company, timestamp=1419576122231, value=alibaba zhangyifei column=address:city, timestamp=1419576123290, value=jieyang zhangyifei column=address:contry, timestamp=1419576123232, value=china zhangyifei column=address:province, timestamp=1419576123262, value=guang dong zhangyifei column=address:town, timestamp=1419576123326, value=xianqiao zhangyifei column=info:birthday, timestamp=1419576123072, value=1987-4-1 7 zhangyifei column=info:company, timestamp=1419576123199, value=alibaba zhangyifei column=info:favorite, timestamp=1419576123144, value=movie
4、统计表的行数
>count 'users'
1 row(s) in 1.2560 seconds
5、删除表
>disable 'users' >drop 'users' >list(验证)
5.1、(动态删除不影响其它的列)
删除xiaoming值的'info:age'字段
>delete 'users','xiaoming','info:age' >get 'users','xiaoming' (验证没有age了)
5.2、删除整行
>deleteall 'users','xiaoming' >scan 'users'(验证)
5.3、清空表
>truncate 'users' >scan 'users'(验证)
6、更新记录:(更新操作)
6.1、通过 get 'users','xiaoming','info:age'
hbase(main):040:0> get 'users','xiaoming','info:age' COLUMN CELL info:age timestamp=1419576122162, value=24
6.2、更新操作:相当于覆盖
>put 'users','xiaoming','info:age' ,'29'
6.3、验证更新是否成功
>get 'users','xiaoming','info:age'
6.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}
6.5、获取单元格数据的某个版本数据
>get 'users','xiaoming',{COLUMN=>'info:age',TIMESTAMP=>1419576122162}
七、 java API 操作 HBase
7.1、hbase-0.94.7-security 添加jar包:hbase-0.94.7-security.jar 和lib 文件夹下的所有jar包
在eclipise 加入 hbase-0.94.7-security.tar.gz windows 解压之后 add floder 指定好的解压目录
7.2、简单的curd 例子代码: hadoop_2 的 hbase 里面HBaseApp
7.3、把hdfs 中的数据存到hbase 中 例子代码:hadoop_2 的 hbase 里面 的 BatchImport
首先在hbase 建立一张表:>create 'wlan_log', 'cf'
然后在hadoop0的 cd Downloads 目录下 执行:hadoop fs -put HTTP_20130313143750.dat /input 上传到hdfs的input目录
然后运行 hadoop_2 的 hbase 里面 的 BatchImport 类。
7.4 、在查看scan 'wlan_log'(验证) 里面就有数据了,并且查询很快
八、hbase 集群安装
8.1 集群结构,主节点(hmaster)是hadoop0,从节点(region server)是hadoop1和hadoop2
8.2 修改hadoop0上的hbase的几个文件 (cd /usr/local/hbase/conf)
(1)修改 vi hbase-env.sh的最后一行export HBASE_MANAGES_ZK=false (这个是设置是关闭自身自带的zookeeper使用外部的zookeeper)
(2)修改vi hbase-site.xml文件的hbase.zookeeper.quorum的值为hadoop0,hadoop1,hadoop2 (把外面的zookeeper节点 放入里面)
(3)修改vi regionservers文件(存放的region server的hostname),内容修改为hadoop1、hadoop2
8.3 复制hadoop0中的hbase文件夹到hadoop1(切换到 hadoop0的 cd /usr/local 下 执行 scp -r hbase hadoop1:/usr/local )、hadoop2(scp -r hbase hadoop2:/usr/local )中
复制hadoop0中的/etc/profile到hadoop1(scp /etc/profile hadoop1:/etc/profile)、hadoop2(scp /etc/profile hadoop2:/etc/profile)中,在hadoop1、hadoop2上执行source /etc/profile
8.4 首先启动hadoop(在hadoop0中执行jsp 保证hadoop开启的且可读写的),然后启动zookeeper集群(分别在hadoop0,1,2 上 执行: zkServer.sh start)(查看启动状态:zkServer.sh status)。
最后在hadoop0上启动hbase集群(执行命令:start-hbase.sh)。验证:http://hadoop0:60010
代表集群成功:
hadoop1: starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-root-regionserver-hadoop1.out hadoop2: starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-root-regionserver-hadoop2.out
8.5、 hadoop2 启动问题:
hadoop2: regionserver running as process 2447. Stop it first. 端口占用问题:在hadoop0上关闭stop-hbase.sh 然后重启 hadoop2:reboot 然后在haoop0 上重启hbase
在hadoop0 上执行 start-hbase.sh
8.6 、hbase核心概念:HBase并不是一个列式存储的数据库,HBase是以列式存储的格式在磁盘上存储数据。
8.7、hbase-site.xml 的hbase.rootdir 节点进行存储Hbase数据的路径
8.8、开启数据库集群:start-hbase.sh
8.9、进入hbase命令操作行:>hbase shell
8.10、>status //查看状态
8.11、创建简单的一个表
create '表名','列族名'
> create 'testtable','colfam1'
create 'hello1','colfam1'
8.12 、>list //查看表是否存在
8.13、存放几条数据
表名 行名 列族 :列名 值
>put 'testtable','myrow-1','colfam1:q1','value-1'
>put 'testtable','myrow-2','colfam1:q2','value-2'
>put 'testtable','myrow-2','colfam1:q3','value-3'
8.14、查询全表
>scan 'testtable'
8.15、获得单行数据 >get 'testtable','myrow-1'
8.16、删除一个单元格
>delete 'testtable','myrow-2','colfam1:q2'
查看删除单元格是否成功
> scan 'testtable'
8.17、删除一张表
>disable 'testtable'
>drop 'testtable'
查看删除表是否成功
> scan 'testtable'
8.18、关闭shell返回命令窗口
>exit
8.19、关闭Hbase系统
stop-hbase.sh
九、hbase设置与案例详解
9.1、DateNode 处理线程数,用户确保拥有Hadoop的配置文件hdfs-site.xml 且设置 xcievers 参数为 4096
9.2、交换区:jvm 不要设置太大 最大不可以接近物理内存
9.3、分布式配置
hbase-site.xml下
rootdir=HDFS NameNode的访问地址、 distributed=true
配置region服务器: 修改regionservers文件把 运行HRegionServer 守护进程的主机 ,添加进去,每个主机单独一行
hbase 集群的启动和关闭时会 按照文件中的主机逐一执行。
Zookeeper安装: 分布式的 HBase 依赖于Zookeeper集群。
hbase-env.sh关闭自身自带的zookeeper使用外部的zookeeper:HBASE_MANAGES_ZK=false
9.4、hbase 的webui 端口是 60010 查看 hbase 集群的状态。
9.5、>help //查看语法和帮助命令 (hbase的shell 命令是Ruby 实现的)
9.6、小例子: 创建一张表用Ruby 循环插入数据
>create 'testtable','colfam1' > for i in 'a'.. 'z' do for j in 'a'..'z' do put 'testtable',"row-#{i}#{j}", "colfam1:#{j}", "#{j}" end end
9.7、在root 目录的 hbase 下 create 'testtable','colfam1'
运行 Myeclipise 下的 Hadoop_2 的hbase 模块的PutExample类。
9.8、Hbase 特殊功能: 能为一个单元格存储多个版本的数据
例子 >create 'test' ,'cf1' // 在test表创建了名为cf1 的 列族。 > put 'test','row1','cf1','val1' //#1 > put 'test','row1','cf1','val2' //#2 > scan 'test' //#3 > scan 'test' ,{ VERSIONS =>3 } //#4
该例子:两个put 使用了相同的行键(row1)和列键(cf1) 但它们的值不同。但是#3的结果是只有val2,你或许认识是#2 覆盖了#1 的 结果 。
其实是HBase 中 默认是保留三个版本的数据。scan 和get 操作只会返回最新版本。
9.9 客户端的写缓冲区:
每一个put 操作实际都是一个RPC(远调) ,讲client上的数据传送到service然后返回。只适合小数据
Hbase 的API 配置了一个客户端的写缓冲区,负责收集put操作,然后通过RPC一次性讲put 送往服务器。
默认情况下,客户端缓冲区是禁用的通过:table.setAutoFlush(false);// 来激活缓冲区
缓冲区默认大小是2兆 ,给每个用户穿件HTable 创建缓冲区大小有点麻烦,用户可以在hbase-site.xml 设置 hbase.client.write.buffer
代码:Hadoop_2/hbase/UseClientWriteBuffer
如果不等于 Result:keyvalues=NONE 删掉表 11,重新新建 表5:
9.10、(客户端api 可以插入单个put实例也可以批量插入)put列表 ,批量处理 :Hadoop_2/hbase/ListPut。
9.11、在hbase表中插入一个 错误的列族:
就会报错
org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 1 action: org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException: Column family ztl does not exist in region testtable,,1424153922215.ec8e4b8f32e878c75b1b86530fefc032. in table 'testtable', {NAME => 'colfam1', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', MIN_VERSIONS => '0', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', ENCODE_ON_DISK => 'true', IN_MEMORY => 'false', BLOCKCACHE => 'true'} at org.apache.hadoop.hbase.regionserver.HRegionServer.multi(HRegionServer.java:3773) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.hadoop.hbase.ipc.WritableRpcEngine$Server.call(WritableRpcEngine.java:320) : 1 time, servers with issues: hadoop2:60020,
但是数据会成功的插入 等等
9.12 、原子性操作compare-end-set : 有一种特别的put调用,能保证自身操作的原子性:(check and put)
代码:Hadoop_2/hbase/CheckPut
9.13、从Hbase 中获取 数据的完整过程
示例代码:Hadoop_2/hbase/GetHtable
9.14、使用get 实例列表 从HBase中获取数据
**** HBase 是一个列式存储的数据库: 不存在没有列的行数据*****
getRowOrBefore()demo:demo Hadoop_2/hbase/ GetRowBefore // 使用getRowOrBefore 方法 查找用户之前使用 put 示例 存入的数据。 示例代码:Hadoop_2/hbase/GetListHtable
9.15、获取数据的相关方法: Boolean exists(Get get) //通过RPC 验证请求的数据是否存在,只返回一个布尔值 来表示这个结果。好处是避免了 网络数据的传输的开销。
Result getRowOrBefore(byte[] row,byte[] family) ) // 用户需要指定要查找的行键和列族
create testtable( pk VARCHAR primary key null, "colfam1"."qual1" VARCHAR null );
9.16、 创建删除的测试数据: > create 'testtable','colfam1','colfam2','colfam3'
>disable 'testtable'
>drop 'testtable'
put 'testtable','row2','colfam1:qual1','val1' put 'testtable','row2','colfam1:qual1','val2' put 'testtable','row2','colfam2:qual2','val1' put 'testtable','row2','colfam2:qual2','val2' put 'testtable','row2','colfam2:qual2','val3' put 'testtable','row3','colfam1:qual1','val1' put 'testtable','row3','colfam1:qual2','val2' put 'testtable','row3','colfam3:qual1','val1' put 'testtable','row3','colfam3:qual2','val2' put 'testtable','row3','colfam3:qual3','val3'
验证:>scan 'testtable' ,{VERSIONS=>50}
DEMO : Hadoop_2/hbase/DeleteHtable 、ListDeleteHtable
从hbase中删除错误的数据
十、Hbase 高级介绍
10.1、原子性操作hbase 表 检查 是否存在这个行和这个列,然后进行删除。
boolean checkAndDelete()
demo:Hadoop2/hbase/CheckDeleteHtable
> create 'testtable','colfam1','colfam2','colfam3' >disable 'testtable' >drop 'testtable'
插入测试:put 'testtable','row1','colfam1:qual1','val1' put 'testtable','row1','colfam1:qual3','val1' put 'testtable','row1','colfam2:qual3','val2' put 'testtable','row1','colfam3:qual3','val3' put 'testtable','row2','colfam1:qual3','val3'
10.2、查询操作:scan "testtable" , {COLUMNS=>'colfam2:qual3',VERSIONS => 3}
10.3、BatchProcess hbase 的批量处理(crud)
Hadoop_2/hbase/BatchProcess
10.4、(row-lock) 行锁 :保证 只有一个客户端能获取一行数据相应的锁,同时对该行进行修改。在实践中,大部分客户
应用端程序都没有提供显示的锁 ,而是使用 这个机制 来保障每个操作的独立性
****用户尽量避免使用行锁 容易造成死锁:两个客户端拥有对方要请求的锁,由同时请可以求多方拥有的锁 便会死锁****
默认的锁超时间是一分钟: 但是可以在hbase-site.xml 文件中添加一下配置项来修改这个默认值
每一个 排它锁 (unique lock): 都能保护这一行不被其它锁锁定,防止其它的并发修改
默认的锁超时时间是一分钟 可以在hbase.site.xml 中配置
***** hbase.regionserver.lease.period 1200000 *******
****put 修改 有必要加锁 get 没必要加锁有并发机制 **********
10.5、扫描器(Scan)
ResultScanner 类 ---》 把扫描操作转换为类似get 操作,他将每一行数据封装成Result实例,并把 所有的Result 实例放在一个迭代器中。ResultScanner 的一些方法如下:
next():客户端循环的调用next方法 (遍历时候执行next方法会单独生成很多rpc请求:单元格数据较小性能不好) and close().
一个扫描器实例 会占不少的服务器资源,占大量的堆空间,使用完之后要调用close方法。
切记 close 方法一定放到finall 块中,确保迭代数据过程中出现异常错误时候,仍然执行close
***** hbase.regionserver.lease.period 1200000 ******* 锁的租约和 扫描器的租约 是同一个,所以设置的时候谨慎。
Demo: UseScanGetHtableData
10.6、 缓存与批量处理:(Scanner caching:扫描缓存:默认情况下是关闭的) 设置表级的扫描缓存 Htable 里的 两个方法
void setScannerCaching(int scannerCaching)// 设置缓存大小
int getScannerCaching() // 返回当前缓存大小的值
也可以设置配置文件:hbase-site.xml 添加一个 hbase.client.scanner.caching
**缓存设置的较高会提高表的性能 但是每次next调用会消耗更长的时间 * *
在扫描中使用缓存和批量参数
demo:Hadoop_2/hbase/ InScanUseCacheP 类
RPC 请求的次数 = (行数 x 每行的列数)/ Min(每行的列数,批量大小) /扫描器缓存
10.7 、Htable 的实用方法: close 方法会隐式的调用 flushCache() 方法
获得表名:byte[] getTableName()
获得htable 实例中使用的配置: getConfiguration()
HtableDescriptor getDescriptor(); 访问表的底层结构定义
10.8、hbase.util.Bytes 把java 的类型的数据转换为 hadoop 的数据类型
10.9、过滤器:hbase 自带的过滤器(get 和scan) 和自定义过滤器
get 和scan 查询范围:通过行键(列族、列、时间戳、版本号) 来查询 ,但是还是缺少细粒度的筛选功能
比如:基于正则表达式对行键或值进行筛选
过滤器的最基本接口:Filter
所有的过滤器都在服务器端生效:可以保证没有过滤掉的数据传送到客户端
最好不要在客户端实现过滤(影响系统性能:因为服务端需要传输更多的数据到客户端)
******* 最好的过滤方式:客户端创建Scan 过滤器,通过RPC 发送到各大ResionServer 在服务器上处理 数据,完事在传给客户端*******----
过滤器层次架构: 最底层是 Filter 接口 和 FileterBase 抽象类 实现了过滤器的 空格和骨架避免重复代码
由于时间的问题,笔记就不记了,直接在 hbase 权威指南的 4.1 节
10.10、计数器:一些广告意见,pv (浏览量)次数,等可以用计数器做实时统计(有了这个就可以放弃,传统的延时较高的批量处理操作),hbase 中有一种机制可以将列 当作计数器,
shell 创建表:>create 'counters' ,'daily','weekly','monthly' >incr 'counters','20140101','daily:hits',1 >incr 'counters','20140101','daily:hits',1 >get_counter 'counters','20140101','daily:hits'
单计数器:第一种操作,只能操作一个计数器:用户需要自己设定列,方法由htable 提供, 两个
long incrementColumnValue(.....)
多计数器:Increment(){}
10.11、协处理器:hbase 允许 用户执行reion 级的操作
WAL: Write-Ahead Logging : 预写日志系统
所有的协处理器 都得实现 Coprocessor 接口
CoprocessorEnvironment
Coprpcess,rHost 这3个类形成了协处理器类的基础,基于这3个类能够实现更高级的功能,它们支持协处理器的
生命周期,管理协处理器的状态,提供了执行时的环境参数。
10.12 、协处理器的加载: 配置文件加载 hbase.coprocessor.region.classes coprocessor.xxxx ,coprocessor.xxxxx // reion 服务器
hbase.coprocessor.master.classes coprocessor.xxxx // master 服务器
hbase.coprocessor.wal.classes coprocessor.xxxx // reion 服务器
********* 配置文件中的配置项的顺序非常重要 **********
当一张表的region 被打开时,hbase.coprocessor.region.classes 定义的协处理器 会被加载,
注意:用户不能指定具体是哪张表活哪个region 加载这个类:默认的协处理器会被每张表和每个region加载。
从表描述符中加载:用户只能在region 相关的协处理器上使用这种方法,而不能在master 或 WAL 相关 的协处理器上使用
10.13、Observer : 与触发器类似:回调函数 也称钩子函数(hook)
RegionObserver 类(处理数据修改事件) 它属于 observer 协处理器:当一个特定饿region 级别的操作发生时,它们的钩子函数会被触发
MasterObserver(用来管理DDL类型的操作,这些是集群事件) 处理master 服务器的所有回调函数。
WALObServer:提供控制WAL 的钩子函数
obserer 提供了 一些设计好的回调函数,每个操作的在集群服务器端都可以被调用
10.14、endpoint: 通过添加一些远程过程调用来动态扩展RPC 协议。
它可以与observer 的实现组合 起来直接作用服务器端的状态
10.15、HTablePool :与其为客户端的每个请求创建一个HTable 实例,不如创建一个实例,然后不断的复用这个实例。
创建HTable 实例是一个非常耗时的操作。但是在多线程环境中重用HTable 实例会出现其它问题,
客户端可以通过这个类 HTablePool 类解决这个问题 。通过构造器 来创建词
HTablePool() ://默认构造器 HTablePool(Confiuration config,int maxSize) HTablePool(Confiuration config,int maxSize,HTableInterfaceFactory tableFactory)
默认构造器,使用classpath 中的配置创建一个表实例词,设定大小为无限。
Configuration conf = HBaseConfiguration.create() HTablePool pool = new HTablePool(conf,Integer.MAX_VALUE)
这两行代码相当与第一个构造函数
用完之后记得 pool.closeTablePool("testtable"); 关闭
10.16、连接管理:每个HTable 实例 都需要建立和远程主机的(连接)。
HBase 内部使用 键值映射 来存储连接。 当你创建很多HTable 实例时 ,如果你提供了相同的Configuration 引用,那么它们都共享同一个底层HConnection 实例。
细节:共享 ZooKeeper 连接:每个客户端 最终都需要ZK 连接来完成表的region 地址 的初始寻址。
缓存通用资源:通过ZK 查询到的 -ROOT- 和 .META. 的地址,以及region 的地址定位,都需要网络传输开销。
这些地址讲缓存在客户端来减少网络的调用次数,因此达到加速寻址的目的
这么写加快寻址的效率
Configuration conf = HBaseConfiguration.create(); HTable table1 = new HTable(conf,"table1"); HTable table2 = new HTable(conf,"table2"); .........
缺点:conf 共享连接一直存在 导致 zk 连接保持打开状态,耗尽内存且会产生IO 异常。
在上述情况下 建议不要用 htable.close
解决方案:有两个静态方法: static void deleteConnection(Configuration conf,boolean stopProxy);
static void deleteAllConnections(boolean stopProxy);
布尔类型参数 保证强制清除整个客户端的RPC栈,因此不需要远程连接服务器,应该把这个参数设置为true
10.17、表属性: 表提供了 getter 和setter 来设置表的属性
设置表名: getname() getNameAsString() setname();
(HTableDescriptor类) 列族的一些方法: void addFamily(HColumnDescriptor family); 添加列族
boolean hasFamily(byte[] c);// 通过列族名家产列族是否存在
HColumnDescriptor [] getColumnFamilies();// 获取存在的列族的列表
HColumnDescriptor getFamily(byte[] column);//获取某个列族描述符
HColumnDescriptor removeFamily(bute[] column);// 删除某个列族
设置表中region 的大小: long getMaxFileSize();
void setMaxFileSize(long maxFileSize);
当 region的 大小达到配置的大小时候,文件大小下限制会帮助HBase 拆分 region
region 参数默认值 是256MB ,看场景来设置,
用户将参数设置为10MB, 然后插入一行大小为 20MB 的值,由于 一行数据不能夸region 存储,因此系统不会拆分该行数据
10.18、只读: 默认所有的表都可写。设置只读: boolean isReadOnly(); void setReadOnly(boolean readOnly);
10.19、memstore 刷写大小
****HBase 内存中预留了写缓冲区,写操作会写入到缓冲区中,然后按照合适的条件顺序写入到磁盘的一个新存储文件中,这个过程叫做刷写 ***
long getMemStoreFlushSize();
void setMemStoreFlushSize(long memstoreFlushSize);
memstoreFlushSize 参数默认大小为64MB ,参数越大,可以生成存储文件越大,文件数量少,同时导致阻塞时间长, WAL 恢复数据也增加了,更新内存容易丢失
10.20、延迟日志刷写: 参数是布尔型,默认为false java api 实现
synchronized boolean isDeferrdLogFlush();
setDefrreLogFlush(boolean isDeferreLogFlush)
10.21、列族
列族的最大版本数: 所有列族都限定了每个值能够保留的最大版本数量
在删除过程中,hbase 会移除超过最大版本数的数据。 下面是getter 和setter 方法
int getMaxVersions(); void setMaxVersions(int maxVersions);
该参数默认为3,在不访问旧数据的情况下,用户可以设置为1.
压缩:hbase 支持插件式的压缩算法: NONE GZ LZO SNAPPY
默认是NONE
10.22、块大小:在hbase 中 所有的存储文件都被划分成了若干个小块,存在get 或scan 操作时候加载到内存里
这个块大小的参数 默认大小为 64kb
设置和获取 synchronized int getBlocksize() void setBlocksize(int s);
*********这个参数 用于指定Hbase 在一次读取过程中顺序读取多少到内存缓冲区********
重要的不同点: HDFS 的块 默认64MB 用来拆分大文件,用来分布式存储,且易于MapReduce 进行并行计算,
HBase 中 的 HFile 块大小默认是 64kb , 主要用于 高效加载和缓存数据 并不依赖Hdfs 的块大小。
且只用于hbase 内部,
10.23、缓存块:HBase 顺序的读取一个数据块到内存缓存中,且读取相邻的数据时就可以内存中读取而不需要从磁盘中再次读取,有效较少磁盘IO的次数。提高IO 效率
这个参数默认是true: 每次读取的块都会缓存到内存中。但是,如果用户要顺序读取某个特定列族,最好将这个属性设置为false,禁止使用块缓存。,
boolean isBlockCacheEnabled();
void setBlockCacheEnabled(boole an blockCacheEnabled)
10.24、生存期 TTL
HBase 不仅支持断言删除每个值能保存的版本数,也支持处理版本数据保存时间
生存期设置了基于时间戳的临界值,内部的管理会自动检查TTL值是否达到上限
在major 合并过程中时间戳被判定为超过TTL 的数据会被删除。 以下是 读写TTL 的 getter与setter 的API
int getTimeToLive(); void setTimeToLive(int timeToLive);
TTL 参数的单位是秒,默认值是Integer.MAX_VALUE 是等于 2147483647秒
********生产过程中的任意正数都永远 小于当前默认值 ************
10.25、小技巧:在内存中提高 ,连续访问的效率(高优先级)
在内存中的标志,默认值为false,
boolean isInMemory(); void setInMeomor(boolean inMemory);
******这个参数适合较小的列族,例如登录帐号和密码的用户表,将这个参数设置为true 有利于提升这个环节的处理速度 ********
10.26、布隆克隆器
它是 HBase 系统中的高级功能,他能减少特定访问模式的查询时间。但是,这种模式增加了内存和存储的负担
这个模式被默认为关闭状态
支持布隆过滤器类型: NONE(不使用布隆过滤器) ROW(行键过滤) ROWCOL(列键过滤)
设置布隆过滤器的两种方法: StoreFile.BloomType getBloomFilterType();
void setBloomFilterType();
10.27、复制范围
HBase 的另一个高级功能是复制。
********它提供了跨集群同步的功能 *********
复制范围默认参数为0 表示这个功能为关闭状态 下面两种方法可以改变参数
int getScope()
void setScope(int scope);
10.28、HBaseAdmin (客户端提供了API的模式来管理集群)
它 提供了 建表,创建列族,检查表是否存在,修改表结构和列族结构 和删除表功能,等。
a、首先实例化 HBaseAdmin
b、当前的api 通过zookeeper 来查找集群,
c、用完之后销毁 (他的生命 周期不宜过长)
HBaseAdmin 这个类实现了Abortable 接口 实现了abort方法,这个方法被隐式调用,在紧急的情况下,需要完整关机活重启,系统会调用此方法。
HBaseAdmin内置了master(主节点)所有的RPC接口代理的封装
HBaseAdmin 高级功能:在建表的时候进行预分区
获取表结构以及信息函数 getTalbeDescriptor
删除表:先禁用在删除 disableTable(表名)
不想删除了,开启表:enableTable(表名)
检查表的状态:boolean isTableEnabled(表明)
boolean isTableDisable(表明)
HBaseAdmin 修改表结构操作
修改表结构之前先禁用表
修改的方法有:void modifyTable(表名,htableDescriptor descriptor)
void addColumn(表名,htableDescriptor column)
void deleteColumn(表名,string 字段名)
10.29、HBase 提供了集群管理功能:
1、 允许用户查看当前集群状态,执行表级任务和管理region
2、 checkHBaseAvailable(conf给定的配置文件);这个方法是检查在给定的配置文件中的远程HBase 集群进行通信。如果失败会抛出异常。
3、 getClusterStatus() :获得集群状态的详细信息。
4、 关闭某个region 方法: void closeRegion(string regionname,string hostAndPort)
5、 通过ClusterStatus(克拉斯特 思 date s) 这个类获取,集群详细信息
10.30、hbase 批处理客户端
a、 MapReduce (处理pb级数据) 特点:高可用,目标明确
b 、Hive :允许用户查询半结构数据,最终查询会转化为MapReduce 作业
Hive 0.6 之后提供了了对Hbase的支持。用户可以直接定义将Hive表存储为HBase表
并按需要映射列值,在需要的时候行键可以作为独立的一列
10.31、hbase 的表分为两类: 高表 (列少行多)和宽表(列多行少) 因为HBase 只能按行分片
因此高表是效率最高的,所以用户查询方案的查询信息维度 存储在行键中,因为它筛选数据效率最高