文章目录
一、HBase简介
HBase是一个分布式的、面向列的开源数据库。
- HBase的运行有三种模式
- 单机模式
在一台计算机上,安装和使用HBase,不涉及数据的分布式存储。 - 伪分布式模式
在一台计算机上,模拟一个小的集群 - 分布式模式
在多台计算机上,实现物理意义上的分布式存储。
- 单机模式
二、HBase安装和配置
Hadoop与HBase的最新版本兼容性
环境:
Ubuntu16.04(14.04-18.04都可)
HBase 2.2.2(bin版本已经编译好(推荐),src未编译)
1.安装
- 下载
官网
传到虚拟机可使用FileZilla(具体实现可在moli博客中检索) - 解压
把安装包hbase-2.2.2-bin.tar.gz解压到/usr/local中
cd ~
sudo tar -zxf ~/Downloads/hbase-2.2.2-bin.tar.gz -C /usr/local
- 改文件名,方便后续使用
cd /usr/local
sudo mv ./hbase-2.2.2 ./hbase
- 把hbase目录权限赋给hadoop用户
cd /usr/local
sudo chown -R hadoop ./hbase
- 配置环境变量
把hbase下的bin目录添加到path中
⇨启动hbase无需到/usr/local/hbase目录下,便于hbase的使用。
下述教程还是切换到了/usr/local/hbase目录操作,有助于萌新理解,熟练后可不必切换
- 编辑~/.bashrc
vim ~/.bashrc
若没有引入PATH需要在~/.bashrc文件尾行添加export PATH=$PATH:/usr/local/hbase/bin
若已经引入PATH在export PATH这行追加/usr/local/hbase/bin
,此处的":"是分隔符。
编辑完成后,再执行source命令使上述配置在当前终端立即生效。
source ~/.bashrc
- 添加HBase权限
cd /usr/local
sudo chown -R hadoop ./hbase #把hbase下的所有文件的所有者改为hadoop,hadoop是当前用户的用户名
- 查看HBase版本,以确定hbase安装成功
/usr/local/hbase/bin/hbase version
若输出版本信息,则HBase安装成功~
遇到的问题&解决:vim非正常退出
2.配置
保证以下三者已经安装(若无则点开主页搜索相关教程配置):
- jdk
- Hadoop( 单机模式不需要,伪分布式模式和分布式模式需要)
- SSH(免密码登陆的SSH协议)
2.1单机模式配置
- 配置/usr/local/hbase/conf/hbase-env.sh。
打开并编辑hbase-env.sh
vim /usr/local/hbase/conf/hbase-env.sh
默认已经安装了JDK1.8。JDK的安装目录为/usr/lib/jvm/jdk1.8.0_162,则JAVA_HOME=jdk的安装目录;配置HBASE_MANAGES_ZK为true(表示hbase自己管理zookeeper,不需要单独的zookeeper)。hbase-env.sh中本就存在这些变量的配置,只需要删除前面的#并修改配置内容即可(#表示注释)
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162
export HBASE_MANAGES_ZK=true
修改后保存退出
- 配置/usr/local/hbase/conf/hbase-site.xml
打开并编辑hbase-site.xml
vim /usr/local/hbase/conf/hbase-site.xml
在启动HBase前,需要设置属性hbase.rootdir,用于指定HBase数据的存储位置,因为如果不设置的话,hbase.rootdir默认为/tmp/hbase-${user.name},这意味着每次重启系统都会丢失数据。
此处设置为HBase安装目录下的hbase-tmp文件夹,即/usr/local/hbase/hbase-tmp。添加配置为:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///usr/local/hbase/hbase-tmp</value>
</property>
</configuration>
- 测试运行。
先切换目录到HBase安装目录/sur/local/hbase;再启动HBase
cd /usr/local/hbase
bin/start-hbase.sh # 启动HBase
bin/hbase shell # 打开shell命令行模式
停止HBase运行
bin/stop-hbase.sh
若操作HBase的过程中发生错误,可以通过{HBASE_HOME}目录(/usr/local/hbase)下的logs子目录中的日志文件查看错误原因
2.2伪分布式模式配置
- 配置/usr/local/hbase/conf/hbase-env.sh
vim /usr/local/hbase/conf/hbase-env.sh
配置JAVA_HOME,HBASE_CLASSPATH.HBASE_MANAGES_ZK.HBASE_CLASSPATH设置为本机HBase安装目录下的conf目录(即/usr/local/hbase/conf)
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162
export HBASE_CLASSPATH=/usr/local/hbase/conf
export HBASE_MANAGES_ZK=true
- 配置/usr/local/hbase/conf/hbase-site.xml
打开并编辑hbase-site.xml
vim /usr/local/hbase/conf/hbase-site.xml
修改hbase.rootdir,指定HBase数据在HDFS上的存储路径;把属性hbase.cluter.distributed设置为true。假设当前Hadoop集群运行在伪分布式模式下,在本机上运行,且NameNode运行在9000端口。
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>
hbase.rootdir指定HBase的存储目录;hbase.cluster.distributed设置集群处于分布式模式.
另外,上面配置文件中,hbase.unsafe.stream.capability.enforce这个属性的设置,是为了避免出现启动错误。也就是说,如果没有设置hbase.unsafe.stream.capability.enforce为false,那么,在启动HBase以后,会出现无法找到HMaster进程的错误,启动后查看系统启动日志(/usr/local/hbase/logs/hbase-hadoop-master-ubuntu.log),会发现如下错误:2020-01-25 15:04:56,916 ERROR [master/localhost:16000:becomeActiveMaster] master.HMaster: Failed to become active master java.lang.IllegalStateException: The procedure WAL relies on the ability to hsync for proper operation during component failures, but the underlying filesystem does not support doing so. Please check the config value of 'hbase.procedure.store.wal.use.hsync' to set the desired level of robustness and ensure the config value of 'hbase.wal.dir' points to a FileSystem mount that can provide it.
测试运行HBase
- 先登录ssh(之前设置了无密码登录)
- 再切换到目录到/usr/local/hadoop
- 再启动hadoop(如果没有启动的话)
ssh localhost
cd /usr/local/hadoop
./sbin/start-dfs.sh
- 切换目录到/usr/local/hbase,再启动HBase
cd /usr/local/hbase
bin/start-hbase.sh
输入命令jps,看到以下界面说明成功启动
- 进入到shell界面
bin/hbase shell
- 停止运行HBase
bin/stop-hbase.sh
注意:如果在操作HBase的过程中发生错误,可以通过{HBASE_HOME}目录(/usr/local/hbase)下的logs子目录中的日志文件查看错误原因。
这里启动关闭Hadoop和HBase的顺序一定是:
启动Hadoop—>启动HBase—>关闭HBase—>关闭Hadoop
三、编程实践
先打开hadoop和hbase
3.1HBase常用shell命令
3.1.1HBase中创建表
创建一个"student"表,属性有Sname,Ssex,Sage,Sdept,course。因为HBase的表中会有一个系统默认的属性作为行键,所以无需自行创建,默认为put命令操作中表名后第一个数据。
create 'student','Sname','Ssex','Sage','Sdept','course'
可通过describe命令查看“student”表中的基本信息。
3.1.2HBase数据库基本操作
主要介绍HBase的增删改查。
在添加数据时,HBase会自动为添加的数据添加一个时间戳,故需要在修改数据时,只需直接添加数据,HBase即会生成一个新的版本,从而完成“改操作”,旧的版本依旧保留,系统会定时回收垃圾数据,只留下最新的几个版本,保存的版本数可以在创建表的时候指定。
- 添加数据
用put
命令添加数据。
notice:一次只能为一个表的一行数据的一个列,即一个单元格添加一个数据。
⇨直接用shell命令插入数据效率很低,故在实际应用中,一般都是利用编程操作数据。
在student表添加了学号为24,名字为Harder的一行数据,行键为24
put 'student','24','Sname','Harder'
- 删除数据
在HBase中用delete和deleteall命令进行删除数据操作。delete
删除一个数据,是put的反向操作
delete 'student','24','Ssex'
* deleteall
删除一行数据
deleteall 'student','24'
- 查看数据
HBase中有两个用于查看数据的命令- get命令
用于查看表的某一行数据
- get命令
get 'student','24' # 返回的是'student'表中'24'行的数据
* scan命令
用于查看某个表的全部数据
scan 'student'
- 删除表
有两步:- 先让表不可用
- 再删除表
disable 'student'
drop 'student'
依次退出shell⇀关闭hbase⇀关闭hadoop
3.1.3查询表历史数据
查询表的历史版本,需要两步:
- 在创建表时,指定保存的版本数(本例中指定为5)
create 'teacher',{NAME=>'username',VERSIONS=>5}
- 插入数据,然后更新数据,使其产生历史版本数据(这里插入数据和更新数据都用put命令)
put 'teacher','202301','username','Mary'
put 'teacher','202301','username','Mary1'
put 'teacher','202301','username','Mary2'
put 'teacher','202301','username','Mary3'
put 'teacher','202301','username','Mary4'
put 'teacher','202301','username','Mary5'
- 查询时,指定查询的历史版本数。默认会查询出最新的数据(有效值为1~5)
get 'teacher','202301',{COLUMN=>'username',VERSIONS=>5}
3.1.4退出HBase数据库表操作
输入exit
命令即可。
!注意,这里退出HBase数据库是退出对数据库表的操作,而不是停止启动HBase数据库后台运行。
3.2HBase Java API编程实践
- 准备工作,启动hadoop,启动hbase,打开shell
启动eclipse,在启动界面上点击右下角的launch创建按钮。
在程序开发界面中,file⇀new⇀Java Project⇀’project name’可为"HBaseExample"。在"JRE"选项卡中选中第二项"Use a project specific JRE"⇀next。
横向目录中,选择’libraries’⇀引入外部jar包
- “/usr/local/hbase/lib”目录中的所有jar包(ctrl+a全选,crtl反选文件夹,以选中所有jar包,点OK)
- “/usr/local/hbase/lib/client-facing-thirdparty”下的所有jar包
点击finish。
HBaseExample⇀new⇀class,类名可为"ExampleForHBase"⇀finish
代码内容为
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
public class ExampleForHBase {
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
public static void main(String[] args)throws IOException{
init();
createTable("student",new String[]{"score"});
insertData("student","zhangsan","score","English","69");
insertData("student","zhangsan","score","Math","86");
insertData("student","zhangsan","score","Computer","77");
getData("student", "zhangsan", "score","English");
close();
}
public static void init(){
configuration = HBaseConfiguration.create();
configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
try{
connection = ConnectionFactory.createConnection(configuration);
admin = connection.getAdmin();
}catch (IOException e){
e.printStackTrace();
}
}
public static void close(){
try{
if(admin != null){
admin.close();
}
if(null != connection){
connection.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
public static void createTable(String myTableName,String[] colFamily) throws IOException {
TableName tableName = TableName.valueOf(myTableName);
if(admin.tableExists(tableName)){
System.out.println("talbe is exists!");
}else {
TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(tableName);
for(String str:colFamily){
ColumnFamilyDescriptor family =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(str)).build();
tableDescriptor.setColumnFamily(family);
}
admin.createTable(tableDescriptor.build());
}
}
public static void insertData(String tableName,String rowKey,String colFamily,String col,String val) throws IOException {
Table table = connection.getTable(TableName.valueOf(tableName));
Put put = new Put(rowKey.getBytes());
put.addColumn(colFamily.getBytes(),col.getBytes(), val.getBytes());
table.put(put);
table.close();
}
public static void getData(String tableName,String rowKey,String colFamily, String col)throws IOException{
Table table = connection.getTable(TableName.valueOf(tableName));
Get get = new Get(rowKey.getBytes());
get.addColumn(colFamily.getBytes(),col.getBytes());
Result result = table.get(get);
System.out.println(new String(result.getValue(colFamily.getBytes(),col==null?null:col.getBytes())));
table.close();
}
}
注意程序运行前,需要启动HDFS和HBase.
运行, 程序运行成功以后,如下图所示,会在运行结果中出现“69”。
这时,可以到HBase Shell交互式环境中,使用如下命令查看student表是否创建成功:
再在HBase Shell交互式环境中,使用如下命令查看student表中的数据: