文章目录
HBase
Hbase的引言
什么是HBase?
hbase是Apache 组织开源的顶级项目 distributed, scalable, big data store 产品
hbase是基于Hadoop的一个NoSQL产品 Column类型的NoSQL
hbase是Google BigTable的开源实现, 最初存储的是爬虫爬取的网页
hbase运行亿级数据查询时,效率可达到秒级,毫秒级 在线处理 实时的处理
NoSQL特点
1. 部分NoSQL In-Memory 内存型 (Redis)
2. Schema-Less NoSchema 弱格式 无格式
3. 杜绝表连接
4. 弱化事务,没有事务 (Redis有事务,MongoDB(4.x 没事务 4.x后有事务)
5. 搭建集群方便
NoSQL分类
1. key value 类型 redis
2. document 类型 mongodb
3. column 类型 HBase Cassandra
4. 图 类型 neo4j (金融 知识图谱)
Hbase存储的逻辑结构
mysql数据库 > t_user表
Hbase
多版本的好处:修改速度快,直接新增一条新数据,给旧数据标记墓碑
Hbase伪分布式环境的搭建
Hmaster Hregionserver
1. linux服务器 ip 主机名 主机映射 防火墙 selinux ssh免密 jdk
2. hadoop安装
2.1 解压缩
2.2 6个配置文件
2.3 格式化
2.4 启动进程
3. 安装zookeeper
3.1 解压缩
3.2 配置conf/zoo.cfg
3.3 创建临时目录 data ---> myid文件(集群)
3.4 启动服务
4. hbase的安装
4.1 解压缩hbase
4.2 hdfs上创建 /hbase文件夹
hbase_home/data/tmp文件夹
4.3 修改hbase相关的配置文件
env.sh
export HBASE_MANAGES_ZK=false
export JAVA_HOME=/usr/java/jdk1.7.0_71
hbase-site.xml
<!--创建的data/tmp文件的位置-->
<property >
<name>hbase.tmp.dir</name>
<value>/opt/install/hbase-0.98.6-hadoop2/data/tmp</value>
</property>
<!--hdfs的创建的hbase文件夹的位置-->
<property >
<name>hbase.rootdir</name>
<value>hdfs://CentOSA:8020/hbase</value>
</property>
<!--是否是分布式-->
<property >
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!--hbase有内置的zookeeper,但不使用,使用外面已经部署好的zookeeper-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>CentOSA</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/install/zookeeper-3.4.6</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
4.4 修改
regionservers文件
CentOSA #主机名
4.5 替换hbase相关hadoop的jar
因为jar的版本和hadoop的版本不对,如果zookeeper的jar包版本也不对的话,也替换掉
4.6 启动hbase
bin/hbase-daemon.sh start master
bin/hbase-daemon.sh start regionserver
4.7 网络访问
http://CentOS:16010
bin/hbase shell
Hbase的shell命令
help 帮助命令
1.help 命令列表
2.help '命令名字' 特定命令详情
Hbase namespace 命令
在HBase中,namespace命名空间指对一组表的逻辑分组,类似RDBMS中的database
。
HBase从0.98.0, 0.95.2两个版本号開始支持namespace级别的授权操作,HBase全局管理员能够创建、改动和回收namespace的授权。
1. hbase中数据库的概念
namespace
1.1 显示所有的数据库
list_namespace
default 默认,创建表时未指定命名空间的话默认挂在default下。
hbase
1.2 创建namespace
create_namespace 'test'
#创建namespace还可以携带一些说明信息
create_namespace "test02", {"author"=>"me", "create_time"=>"2018-11-4 17:51:53"}
1.3 查看namespace
describe_namespace 'test'
1.4 修改namespace
#修改name的说明信息author
alter_namespace "test02", {METHOD=>"set", "author"=>"you"}
#追加自己的联系方式
alter_namespace "test02", {METHOD=>"set", "email"=>"110@qq.com"}
#去掉email属性
alter_namespace "test02", {METHOD=>"unset", NAME=>"email"}
总结:
添加或修改属性:alter_namespace 'test02', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
删除属性: alter_namespace 'test02', {METHOD => 'unset', NAME=>'PROPERTY_NAME'}
1.5 删除namespace
#注意要删除的namespace必须是空的,其下没有表,否则会删除失败
drop_namespace 'test'
1.6 显示namespace中所有的表
list_namespace_tables 'test02'
Hbase table命令【重点】
1. 基本的建表方式 【默认default库中】
#未指定数据库时,表会创建到defalut库中
create 't1','cf1' 1个列簇
create 't1','cf1','cf2' 多个列簇,逗号隔开
create 'Student','StuInfo','Grades' 上图创建表命令
2. 指定表所属的数据库
#mysql,oracle,hive在数据库创建表时,都是用use database;
#但hbase不用,只需在创建表的表名前加上数据库的名字即可
create 'test:t1','cf1'
create 'test:Student','StuInfo','Grades' 上图表创建在test的namespace库中
3. 详细描述列簇的相关属性
#VERSIONS:表示此列簇下同一个rowkey下相同的列限定符允许同时存在几个版本,默认值为1
#VERSIONS=>2:同一个rowkey下相同的列限定符只能存在2个,存第三个时会进行覆盖操作
#2覆盖1,3覆盖2(相当于把最老的版本抛弃)
create 'test:t2',{NAME=>'cf1',VERSIONS=>2},{NAME=>'cf2'}
create 'test:Student',{NAME=>'StuInfo',VERSIONS=>2},{NAME=>'Grades'}
4. 描述表
#此时就会将列簇的属性全部查询出来,信息比较多
describe 't1'
describe 'test:t1' #查看namespace为test下的t1表
5. 修改表
#修改表的列簇的属性,这里将VERSIONS改为2
#修改多个列族的参数,形式与 create 命令类似。
alter 'test:t2',{NAME=>'cf2',VERSIONS=>2}
#增加列簇
alter 'test:t2', 'hobby'
alter 'Student', 'hobby'
#删除列簇,移除或者删除已有的列簇
#注意:HBase 表至少要包含一个列簇,因此当表中只有一个列族簇,无法将其删除。
alter 'Student', { NAME => 'hobby', METHOD => 'delete' }
alter 'Student', 'delete' => 'hobby'
6. 删除表
disable 'test:t2' #先禁用表
drop 'test:t2' #再删除表
7. 清空表
truncate 'namespace:tableName' #会把表分区也清除掉
truncate_preserve 'namespace:tableName' #只清除数据
8. 失效 生效表相关命令
enable disable #启用/禁用
enable_all disable_all #启用所有/禁用所有
is_enable is_disable #查看表是否启用/禁用
9. 判断表是否存在
exists 'test:t2' #判断namespace为test下是否存在t2表
10. 表的查找命令
list #列出HBase中已有的表
list 'namespace:t.*' #查询namespace下以t开头的表 .*都不能少,是正则表达式
Hbase table 数据操作【重点】
1. 插入数据(put)
put 'namespace:表','rowkey','列簇:限定符','值',[时间戳]
put 't1','rowkey','family:qualify','value',[时间戳]
例如:put 'Student', '0001', 'Stulnfo:Name', 'Tom Green', 1
第一个参数Student为表名;
第二个参数0001为行键的名称,为字符串类型;
第三个参数StuInfo:Name为列簇和列的名称,中间用冒号隔开。列簇名必须是已经创建的,
否则HBase会报错;列名是临时定义的,因此列簇里的列是可以随意扩展的;
第四个参数Tom Green为单元格的值。在HBase里,所有数据都是字符串的形式;
最后一个参数1为时间戳,如果不设置时间戳,则系统会自动插入当前时间为时间戳。
put 'namespace:t1','001','cf1:qf1','xiaohei' #不带时间戳,会自动插入当前时间
put 命令只能插入一个单元格的数据,所以student表中的一行数据需要通过以下几条命令一起完成:
put 'Student', '0001', 'StuInfo:Name', 'Tom Green', 1
put 'Student', '0001', 'StuInfo:Age', '18'
put 'Student', '0001', 'StuInfo:Sex', 'Male'
put 'Student', '0001', 'Grades:BigData', '80'
put 'Student', '0001', 'Grades:Computer', '90'
put 'Student', '0001', 'Grades:Math', '85'
2. 删除数据(delete)
delete 'namespace:t1' ,'rowkey','family:qualify',['timestamp']
delete 命令的最小粒度是单元格(Cell)
delete 'Student', '0002', 'Grades' #删除Student表中行键为0002的Grades列簇的所有数据
delete 'Student', '0001', 'Grades:Math', 2 #删除Student表中行键为0001,Grades列簇成员为 Math,时间戳小于等于2的数据
delete命令不能跨列族操作,如需删除表中所有列簇在某一行上的数据,即删除上表中一个逻辑行,
则需要使用 deleteall 命令
deleteall 'Student', '0001'
3. 全表扫描(scan) 使用时一定要慎重,避免由于扫描数据过大导致HBase集群出现响应延迟
scan '表名'
#查询时间范围内的数据
scan 'namespace:tb1', {TIMERANGE => [1573994102776, 1573994130600]}
#获取两个rowkey(有序)之间的数据,STARTROW:开始查询rowkey;STOPROW:结束查询rowkey,不包括stoprow的值
scan 'namespace:tb1', {STARTROW => '20170521_10001',STOPROW => '20170521_10003'}
scan 'test:user',{STARTROW=>'001',STOPROW=>'004'}
#从某个rowkey开始获取2条记录:
scan 'ns1:t1', {COLUMNS => 'f1:c1', LIMIT => 2, STARTROW => '001'}
4. 某条数据的查询(get)
get 后面可以跟table表名,rowkey,以及column,value
get 'namespace:table', 'rowkey' 例如:get 'test:user','001'
get命令比较多,如下:
get 'table', 'rowkey'
get 'table', 'rowkey', {TIMERANGE => [ts1, ts2]}
get 'table', 'rowkey', {COLUMN => 'cf1'}
get 'table', 'rowkey', {COLUMN => ['cf1', 'cf2', 'cf3']}
get 'table', 'rowkey', {COLUMN => 'cf1', TIMESTAMP => ts1}
get 'table', 'rowkey', {COLUMN => 'cf1', TIMERANGE => [ts1, ts2], VERSIONS => 4}
get 'table', 'rowkey', {COLUMN => 'cf1', TIMESTAMP => ts1, VERSIONS => 4}
get 'table', 'rowkey', {FILTER => "ValueFilter(=, 'binary:abc')"}
get 'table', 'rowkey', 'cf1' 例如:get 'Student','001','base:name'
get 'table', 'rowkey', 'cf1', 'cf2'
get 'table', 'rowkey', ['cf1', 'cf2']
get 'table', 'rowkey', {COLUMN => 'cf1', ATTRIBUTES => {'mykey'=>'myvalue'}}
get 'table', 'rowkey', {COLUMN => 'cf1', AUTHORIZATIONS => ['PRIVATE','SECRET']}
get 'table', 'rowkey', {CONSISTENCY => 'TIMELINE'}
get 'table', 'rowkey', {CONSISTENCY => 'TIMELINE', REGION_REPLICA_ID => 1}
HBase 集群搭建
1.时间同步集群
CentOS 作为时间同步服务器 主节点
1. yum install ntp 三台机器
2. service ntpd start 三台机器
chkconfig ntpd on
3. 服务器节点 主节点
ntpdate -u 202.112.10.36 #先手动就校准一次
#以后就通过配置文件校准了,其中192.168.111.0 是本地的网关,需要改为自己的
vi /etc/ntp.conf
#192.168.111.0:服务器网段
restrict 192.168.111.0 mask 255.255.255.0 nomodify notrap
# 中国这边最活跃的时间服务器 : http://www.pool.ntp.org/zone/cn
server 210.72.145.44 perfer # 中国国家受时中心
server 202.112.10.36 # 1.cn.pool.ntp.org
server 59.124.196.83 # 0.asia.pool.ntp.org
# 允许上层时间服务器主动修改本机时间
restrict 210.72.145.44 nomodify notrap noquery
restrict 202.112.10.36 nomodify notrap noquery
restrict 59.124.196.83 nomodify notrap noquery
# 外部时间服务器不可用时,以本地时间作为时间服务
server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10
service ntpd restart
4. 从节点配置文件修改,和主节点进行时间校验
vi /etc/ntp.conf
server 192.168.111.41 #这里指的是ntp服务主节点的ip
restrict 192.168.111.41 nomodify notrap noquery
server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10
5. 重启三台机器 service ntpd restart
6. 从节点同步主节点时间
ntpdate -u 192.168.111.41 #ntp服务主节点
7. date命令查看处理结果
2.Hadoop集群搭建
HDFS集群
Yarn集群
3.Zookeeper集群
1. 解压缩
2. 创建数据文件夹
zookeeper_home/data
3. 修改配置文件
conf/zoo.cfg
dataDir
server.0
4. 在data文件夹中创建 myid文件 0 1 2
5. 启动服务
4. HBase集群
1. 准备:hbase_home data/tmp logs目录中的内容清空
hdfs 上面 hbase目录清空
2. 修改hbase_home/conf/hbase-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_71
export HBASE_MANAGES_ZK=false
3. hbase-site.xml
<!--创建的data/tmp文件的位置-->
<property >
<name>hbase.tmp.dir</name>
<value>/opt/install/hbase-0.98.6-hadoop2/data/tmp</value>
</property>
<!--hdfs的创建的hbase文件夹的位置-->
<property >
<name>hbase.rootdir</name>
<value>hdfs://CentOSA:8020/hbase</value>
</property>
<!--是否是分布式-->
<property >
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!--zookeep集群-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>CentOSA,CentOSB,CentOSC</value>
</property>
<!--zookeep安装路径-->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/install/zookeeper-3.4.6</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
4. regionservers
CentOSA
CentOSB
CentOSC
5. 替换hbase相关hadoop的jar
因为jar的版本和hadoop的版本不对,如果zookeeper的jar包版本也不对的话,也替换掉
6. 启动hbase
bin/start-hbase.sh
7. 网络访问
http://CentOS:16010
bin/hbase shell
HBase JAVA API
# java访问HBase的核心API
Configruation HBase相关的配置
Htable HBase中的表
Put 插入数据
Get 查询数据
Scan 扫描数据
BytesUtil 字节处理
Maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-client -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>0.98.6-hadoop2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-server -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>0.98.6-hadoop2</version>
</dependency>
方法
对象 | 作用 | 基本用法 |
---|---|---|
Configruation | Hbase相关的配置文件 | conf.set(“key”,“value”); |
HTable | Hbase中的表 | 表相关的操作都是HTable完成 |
Put | HBase中插入数据 | Put put = new Put(rowkey) put.add HTable.put(put) |
Delete | HBase中的删除操作 | Delete delete = new Delete(rowkey) HTable.delete(delete) |
Get | HBase查询单条数据 | Get get = net Get(rowkey) HTable.get(get) —> Result |
Result | 单行数据 | Result – Cells — Cell — cloneFamily cloneQualify cloneValue |
Scan | 表的扫描 | ResultScanner —> Result |
HBase中的过滤器
1.行键相关的过滤器
1.比较行键值的大小
Filter filter1 = new RowFilter(CompareFilter.CompareOp.GREATER, new
BinaryComparator(Bytes.toBytes("0003")));
scan.setFilter(filter1);
2. 比较行键按照特定的规则设计
Filter filter1 = new PrefixFilter(Bytes.toBytes("000"));
scan.setFilter(filter1);
2.列簇相关的筛选
1.只要base列簇相关的数据
Filter filter1 = new FamilyFilter(CompareFilter.CompareOp.EQUAL, new
BinaryComparator(Bytes.toBytes("base")));
scan.setFilter(filter1);
3.限定符相关筛选
Filter filter1 = new QualifierFilter(CompareFilter.CompareOp.EQUAL, new
BinaryComparator(Bytes.toBytes("age")));
scan.setFilter(filter1);
4.值的筛选
Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("1") );
scan.setFilter(filter);
5.列簇中的数据进行筛选
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("base"),
Bytes.toBytes("sex"),
CompareFilter.CompareOp.EQUAL,
new SubstringComparator("male"));
filter.setFilterIfMissing(true);
//filter.setFilterIfMissing(false); //符合要求的数据 password=123456
//column 中不包含password限定符 查询出来
scan.setFilter(filter);
//同时要排除password 限定符
SingleColumnValueExcludeFilter filter = new SingleColumnValueExcludeFilter(
Bytes.toBytes("base"),
Bytes.toBytes("password"),
CompareFilter.CompareOp.NOT_EQUAL,
new SubstringComparator("66666"));
filter.setFilterIfMissing(true);
//filter.setFilterIfMissing(false); //符合要求的数据 password=123456
//column 中不包含password限定符 查询出来
scan.setFilter(filter);
6.FilterList
设置多个过滤器 同时生效
FilterList filterList = new FilterList();
Filter filter1 = new PrefixFilter(Bytes.toBytes("000"));
SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
Bytes.toBytes("base"),
Bytes.toBytes("password"),
CompareFilter.CompareOp.EQUAL,
new SubstringComparator("123456"));
filter2.setFilterIfMissing(true);
filterList.addFilter(filter1);
filterList.addFilter(filter2);
scan.setFilter(filterList);
HBase中列簇相关的属性
1. 创建HBase表
create 'table_name',{NAME=>'',VERSIONS=>''}
2. Hbase列簇的常见属性
# 列簇的名字
NAME='xxxxx'
# 列簇对应限定符 能存几个版本的数据
VERSIONS => '1'
# TTL Time To Live
指定的是cell中的数据,存储在HBase中的存活时间 默认值'FOREVER'
TTL => 100
# 指定HBase上存储的数据 是否 启动压缩
COMPRESSION => 'NONE' 默认值,不压缩
COMPRESSION => 'snappy' 压缩,值不是改为true,而是指定压缩算法,snappy是一种比较常用的压缩算法
# 列簇中的数据,存储在内存中,提高查询效率 (默认关闭)
IN_MEMORY => 'false’
# 缓存 列簇部分数据,从而提高查询效率
BLOCKCACHE => 'true'
# Block是列簇中存储数据的最小单位
BLOCKSIZE => '65536'
块调整大 顺序查询需求高
块调整小 随机查询需求高
# 提高查询效率
BLOOMFILTER 布隆过滤
HBase 中3大进程的作用
1.HMaster
1.管理用户对Table的CURD
2.管理RegionServer中Region的分布
3.在Region分裂后,负责新Region的分配
4.ReginServer死机后,迁移Region
2.RegionServer
1.管理region
2.负责响应用户的IO请求,从HDFS系统中读写数据
一张表的数据存在region中,region中一个store对应一个列簇,store又分为memStore和storeFile(可能存在多个),存数据时,会先写到hlog中(日志文件,若memStore中的数据未达到阈值,服务器挂了,可以有效防止数据丢失),然后写到数据的列簇对应的store,先写到memStore(内存),等到memStore达到阈值时,再溢写到storeFile中。
storeFile类型是hFile,就好比文本文件后缀是txt类型
hbase是依附于hdfs存储的,hdfs默认一个块大小是128M,hbase中的Block默认是64kb,那么hdfs中的一个块就对应的不止一个hbase的Block
有可能一张表对应的数据非常大,一个region存不下,那么就会发生region裂变(一个region变成2-n个region),见下面的图析
3.Zookeeper作用 【重点】
1. 管理HMaster的高可用
2. 存储了HBase中非常重要的信息 meta信息
rowkey 范围 ---- region ---- RegionServer(健康)
4.HBase compact 和 split(region的裂变)
storeFile默认达到3个时就会合并,然后根据设置的分割模式分割合并后的storeFile,同时会分割成两个region;若3个storeFIle合并后未达到分割算法,则会合并后继续等待后面进来的storeFile进行下一次合并
分割算法:
2^Region*memStoreFlush(默认128M) 和10G(默认设置)二者取最小值,合并后的storeFile达到了最小值就会分割
RowKey设计
1. HBase相关的查询操作,95%上都是对RowKey查询。
2. 设计过程
2.1 复合
2.2 查询内容作为rowkey组成
3. rowkey 64K 10--100字节唯一
4. rowkey结合自己的实际需求
4.1 区域查询多,建议 rowkey 连续
4.4 区域查询少,散列 hash ---> 加密、UUID
HBase优化策略
1. 解决热点效应
- 预分区
在创建表时,不按照默认的策略,为表只创建一个Region,而是根据需要,为一张表创建多个Region,从而避免热点效应- 预分区的依据 :基于Rowkey进行预分区
- 语法:
create ‘t1’, ‘f1’, SPLITS => [‘10’, ‘20’, ‘30’, ‘40’]
create ‘t1’, ‘f1’, SPLITS_FILE => ‘splits.txt’ //这里要写splits.txt的绝对路径
splits.txt内容
10
20
30
40
create ‘t2’, ‘f1’, {NUMREGIONS => 15, SPLITALGO => ‘HexStringSplit’} // 采用hbase的预分区逻辑- 根本上解决热点问题需要注意如下几点
1. 预分区
2. rowkey设置
综上2者尽量解决热点问题。
2. 如何提高检索效率
- rowkey 相对连续 那么检索效率一定高 (顺序查询 scan操作)
- 设置Memstore大小 , Block Cache大小
hbase-site.xml 设置
hbase.hregion.memstore.flush.size—>128M 每一个memstore达到128M flush
hbase.regionserver.global.memstore.size—>0.4 堆空间的40% (regionserver占用JVM 堆空间)
a.让数据尽可能多的放置在内存中,提高检索效率
b.避免flush memstore 阻塞client操作
hbase.regionserver.global.memstore.size.lower.limit 默认当全局flush到 memstore用量达95%不在flush;比如100M时溢写,写到storeFile中95M时,剩余5M就不会继续写了,还是放在memStore中
hfile.block.cache.size 0.4
3. hbase内部的块数据索引,布隆过滤器
3.JVM参数配置
hbase-env.sh 指定内存和垃圾回收器
exportHBASE_REGIONSERVER_OPTS
=”-Xmx8g -Xms8G -Xmn128m -XX:UseParNewGC -XX:UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc: H B A S E H O M E / l o g s / g c − HBASE_HOME/logs/gc- HBASEHOME/logs/gc−{hostname}-hbase.log”
4. mslab
防止内存碎片,内存碎片过多,内存泄露,发生FullGC,导致STW.
hbase.hregion.memstore.mslab.enabled true
hbase.hregion.memstore.mslab.chunksize 默认值2M --> 改为4M、5M、6M都可以,
5.自动化合并storeFile变成手工处理
#查看合并storeFile命令
help 'split' #有几个命令可以使用,主要是基于table、table中的某个region……
将来可以将命令写到一个文件中,然后定时去执行即可
/opt/install/hbase-0.98.6-hadoop2/bin/hbase shell /root/hbase/test
注意:root/hbase/test是指命令文件的路径 hbase shell后是可以跟shell脚本文件的路径的
HBase与MapReduce的集成
- Hbase为什么需要和MR集成?
HBase数据的迁移。
- hadoop中缺少hbase的jar包,无法执行mapReduce
1.直接将hbase中的jar包复制一份到hadoop
2.在hadoop的配置文件中直接引入hbase的jar包
hadoop-env.sh
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/opt/install/hbase-0.98.6-hadoop/lib/*