- Hbase是大数据NoSQL领域里非常重要的分布式KV数据库,是一个实时、高可靠、高性能、高伸缩的分布式存储系统,运行依赖于Hadoop HDFS、zk
- 因为是key-value结构的数据库,所以curd操作都是通过key去操作value。与redis不同的是Hbase的key有点复杂。
- Key则是由Rowkey、Column Family : Column Qualifier、Timestamp、Type等几个维度组成。rowkey是Hbase的行键;column family(列族)与qualifier(列限定符即列名)共同组成了Hbase的列;timestamp表示的就是数据写入时的时间戳,主要用于标识Hbase数据的版本号;type代表Put/Delete的操作类型
- 客户端连接hbase依赖于zookeeper,hbase存储依赖于hadoop
- 查数据时,携带key值,先连接集群的zk,然后访问zk的元数据信息找到对应的hbase,hbase集群通过机制查找到key对应的value。
- 更多原理 点此处
-
容量大:Hbase单表可以很庞大,加上其分布式、高伸缩性的特点,使得Hbase特别适合海量数据的永久性存储。
-
高性能:Hbase具有非常高的读写性能,基于LSM-Tree的数据结构使得Hbase写入数据性能强劲,另外得益于Hbase读路径上的各种设计及优化,Hbase读数据的性能也可以保持在毫秒级。
-
高可靠:因为数据写路径上是先写WAL日志,防止缓存数据的丢失,加上Hbase底层数据的多副本机制,保证了数据的可靠性。
-
原始支持Hadoop:Hbase底层存储基于HDFS,也原生集成了MapReduce做离线计算。Hbase这种架构体系也使得Hbase非常易于扩展。
-
无模式:Hbase的表是schema-free的,无需提前定义schema,只会在数据写入时才会增加列。
-
稀疏性:Hbase是表具有稀疏性,null值的列并不占用任何存储空,这一点和关系库不同,大大节省了存储空间。因为hbase是列式存储
-
多版本:Hbase支持多版本,每一个单元格包含timestamp时间戳,标识着数据的版本号。
-
数据分析能力弱:数据分析是Hbase的弱项,比如聚合运算、多维度复杂查询、多表关联查询等。所以,我们一般在Hbase之上架设Phoenix或Spark等组件,增强Hbase数据分析处理的能力。
-
原生不支持二级索引:默认Hbase只对rowkey做了单列索引,因此正常情况下对非rowkey列做查询比较慢。所以,我们一般会选择一个Hbase二级索引解决方案,目前比较成熟的解决方案是Phoenix,此外还可以选择Elasticsearch/Solr等搜索引擎自己设计实现。
-
原生不支持SQL:SQL查询也是Hbase的一个弱项,好在这块可以通过引入Phoenix解决,Phoenix是专为Hbase设计的SQL层。
-
引入hbase的client依赖包
org.apache.hbase hbase-client 2.0.1 org.slf4j slf4j-api log4j log4j org.slf4j slf4j-log4j12 -
配置hbase集群信息
#配置集群的ip地址 hbase.zookeeper.quorum= 192.168.130.115,192.168.130.116 #zk的端口号 连接hbase实际上是通过zk连接的 hbase.zookeeper.property.clientPort= 2181
- 添加配置类并创建Hbase连接实例
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HbaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import java.io.IOException;
@org.springframework.context.annotation.Configuration
public class ServiceHbase {
@Value("${hbase.zookeeper.quorum}")
private String zookeeperQuorum;
@Value("${hbase.zookeeper.property.clientPort}")
private String clientPort;
@Bean("myConnection")
public Connection getCon(){
Configuration entries = HbaseConfiguration.create();
entries.set("hbase.zookeeper.quorum",zookeeperQuorum);
entries.set("hbase.zookeeper.property.clientPort",clientPort);
try {
return ConnectionFactory.createConnection(entries);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
- 增删改查
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service("myHbaseService")
public class SerDemo {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
@Qualifier("myConnection")
private Connection hbaseConnection;
String tableName = "hello_ssx_tab";
String familyName = "family1";
public boolean addTab(){
try {
// logger.info("获取hbaseAdmin对象用于操作表");
Admin hbaseConnectionAdmin = hbaseConnection.getAdmin();
//判断表是否存在
TableName tableName1 = TableName.valueOf(this.tableName);
boolean tableExists = hbaseConnectionAdmin.tableExists(tableName1);
logger.info("表是否存在"+tableName+":"+tableExists);
//如果表不存在就新建
if (!tableExists){
//表不存在
//表 描述建造者
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName1);
//列族 描述建造者
ColumnFamilyDescriptorBuilder cfdb = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(familyName));
//设置最大版本号 其实就是记录的轨迹信息,设置为3可以查询追溯到前1个版本前2个版本前三个版本,此功能相当于数据库的flashback闪回。默认1
cfdb.setMaxVersions(3);
//创建列族 描述
ColumnFamilyDescriptor familyDescriptor = cfdb.build();
//将列族加入到表描述中
builder.setColumnFamily(familyDescriptor);
//创建表 描述
TableDescriptor tableDescriptor = builder.build();
//创建表
hbaseConnectionAdmin.createTable(tableDescriptor);
logger.info("表创建成功"+tableName);
}else {
logger.warn("表已经存在:"+tableName);
}
return hbaseConnectionAdmin.tableExists(tableName1);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public boolean setValue(String value,String colName,String rowKey){
//指定表名
TableName tableName1 = TableName.valueOf(this.tableName);
try {
//获取表对象
Table table = hbaseConnection.getTable(tableName1);
//设置行键值
Put row001 = new Put(Bytes.toBytes(rowKey));
//设置列族,列,值
row001.addColumn(Bytes.toBytes(familyName),
Bytes.toBytes(colName),Bytes.toBytes(value));
//添加记录
table.put(row001);
// logger.info("成功hbase添加数据信息:目标表:"+tableName+",目标行键:"+rowKey+",目标列族:"+familyName+",目标列:"+ colName +",目标值:"+value);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public String getValue(String rowKey){
//指定表名
TableName tableName1 = TableName.valueOf(this.tableName);
try {
//设置表
Table table = hbaseConnection.getTable(tableName1);
//指定要查询的行键
Get get = new Get(Bytes.toBytes(rowKey));
//查询返回结果
Result result = table.get(get);
//获取结果集合
Cell[] cells = result.rawCells();
//遍历结果集
StringBuilder returnData = new StringBuilder();
for (Cell cell:cells){
byte[] bytes = CellUtil.cloneRow(cell);
String s = Bytes.toString(bytes);
logger.info("查询hbase数据信息:目标表:"+tableName+",目标行键:"+rowKey+",查询出的信息: 行键:"+s);
returnData.append(s).append('n');
String s1 = Bytes.toString(CellUtil.cloneFamily(cell));
logger.info("查询hbase数据信息:目标表:"+tableName+",目标行键:"+rowKey+",查询出的信息: 列族:"+s1);
returnData.append(s1).append('n');
String s2 = Bytes.toString(CellUtil.cloneQualifier(cell));
logger.info("查询hbase数据信息:目标表:"+tableName+",目标行键:"+rowKey+",查询出的信息: 列名:"+s2);
returnData.append(s2).append('n');
String s3 = Bytes.toString(CellUtil.clonevalue(cell));
logger.info("查询hbase数据信息:目标表:"+tableName+",目标行键:"+rowKey+",查询出的信息: 值:"+s3);
returnData.append(s3).append('n');
}
return returnData.toString();
} catch (IOException e) {
e.printStackTrace();
}
return "查询失败";
}
}
- 如果启动报错 UnknownHostException 的话 就在"C:WindowsSystem32driversetchosts"配置下 设置域名/host和IP的关系
- 以上就是简单的实例了,如果报错请 百度一下
- 本项目Gitee源码
- 如果是在windows系统开发环境搭建的话,windows本地电脑需要安装hadoop软件,并且配置环境变量,还要安装一个winutils-master软件。不然项目启动会报错找不到hadoop——home环境变量。
- 下载hadoop2压缩包,解压,然后配置window系统环境变量HADOOP_HOME和Path
- 下载winutils的windows版本,解压,选择一个和hadoop软件相近的版本,打开winutils的bin文件整体粘贴到hadoop软件下。
- hadoop文件bin文件夹下的hadoop.dll拷贝到C:WindowsSystem32目录下
- 可能需要重启IDEA或者电脑,完成
- 参考文章:https://www.jianshu.com/p/a65a95108620



