1. Hbase 简介
- Hadoop-Database根据 ’bigtable‘ 论文实现的
- 分布式 可扩展 的大数据存储技术
- 随机访问 实时读写 海量数据
- 存储数 ‘十亿行 百万列‘ 的数据
- 高可靠性、高性能、面向列、可伸缩 的分布式 存储系统
- hbase 的底层存储基于hdfs
- 利用 Zookeeper 作为协调工具
2. Hbase 是什么?
- 分布式开源数据库,基于 hadoop 分布式文件系统(HDFS)
- 模仿提供了 Google 文件系统的 BigTable 数据库所有功能
-
处理非常庞大的表
- 数十亿行 百万列
- 利用 mapreduce 计算数据,利用 zookeeper 协调资源
- HBase 是一款NoSQL
3. 行存储和列存储
-
行存储:mysql oracle 底层基于行存储数据的
- 查询数据需要全表扫描, 效率较低
- 对数据压缩支持不太好
-
列存储:hbase 底层基于列存储数据的
- 查询数据不需做全表扫描
- 支持较好的数据压缩
4. Hbase 的特点
- 可以分布式存储海量的数据
- 具有容错能力强,数据高可靠的特点
- HBase 是一个列式 NoSQL 数据库
- 数据存储的结构是按照列进行存储
5. Hbase 的安装部署
==安装 hbase 高可用集群之前首先要保证 zookeeper 和 hadoop 已经安装完成==
- 准备安装包
hbase-1.1.5-bin.tar.gz
-
集群的规划
- uplooking01: master
- uplooking02: master
- uplooking03: regionserver
- uplooking04: regionserver
- uplooking05: regionserver
-
解压安装包
[root@uplooking01: /soft]: tar -zxvf hbase-1.1.5-bin.tar.gz -C /opt/
-
重命名
[root@uplooking01: /opt]: mv hbase-1.1.5/ hbase
-
配置环境变量
[root@uplooking01: /opt]: #配置 HBASE 的环境变量 export HBASE_HOME=/opt/hbase export PATH=$PATH:$HBASE_HOME/bin
-
配置vim hbase-env.sh
[root@uplooking01: /opt/hbase/conf]: vim hbase-env.sh
export JAVA_HOME=/opt/jdk export HBASE_MANAGES_ZK=false #不使用 hbase 自带的 zookeeper export HBASE_CLASSPATH=/opt/hadoop/etc/hadoop
-
配置hbase-site.xml
[root@uplooking01: /opt/hbase/conf]: vim hbase-site.xml
<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://ns1/hbase</value> </property> <property> <name>hbase.tmp.dir</name> <value>/opt/hbase/tmp</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>uplooking03:2181,uplooking04:2181,uplooking05:2181</value> </property> </configuration>
-
配置 regionservers
[root@uplooking01: /opt/hbase/conf]: vim regionservers
uplooking03 uplooking04 uplooking05
-
分发文件
[root@uplooking01: /opt]: scp -r hbase uplooking02:/opt scp -r hbase uplooking03:/opt scp -r hbase uplooking04:/opt scp -r hbase uplooking05:/opt scp /etc/profile uplooking02:/etc/ scp /etc/profile uplooking03:/etc/ scp /etc/profile uplooking04:/etc/ scp /etc/profile uplooking05:/etc/
source /etc/profile(所有节点都做, 要使环境变量生效)
-
启动 hbase 集群
start-hbase.sh
-
单独启动 master
[root@uplooking02:/] hbase-daemon.sh start master
- 注意事项
==启动 hbase 集群一定要保证整个集群的时间一致==
-
== 附加(一般不会有这种情况)==
如果启动集群执行 start-hbase.sh,master 节点可以启动, 但是 regionserver 节点不能启动,但是单独启动 regionserver(hbase-daemon.sh start regionserver)是可以启动的, 也没有问题,name 就需要拷贝一个 jar 包,
将 HADOOP_HOME/share/hadoop/common/lib 下的 htrace-core-3.0.4.jar 复制到 $HBASE_HOME/lib 下
6. Hbase 的体系结构(模型)
6.1 逻辑结构(模型)
-
表(table)
- 划分数据集合的概念,和传统的 db 中的表的概念是一样的
-
行键(rowKey)
- 对应关系数据库中的主键,作用就是 唯一标示一行记录
- 获取 hbase 中的一个记录 (数据), 要通过 行键 来获取
- 行键是 字节数组, 任何字符串 都可以作为行键
- 表中的行根据行键 (row key) 进行 排序 , 数据按照 Row key 的 字节序 (byte order) 排序存储
-
列簇(列族)columnFamily
- 简单的认为是一系列“列”的集合
-
列限定符(column Qualifier)
- 或者叫 列
- 每个列簇都可以有多个列
-
时间戳(version)
- 在单元格中可以存放 多个版本 的数据
-
单元格(cell)
- 主要用来 存储数据
- 单元格的定位要通过 三级定位 才能定位到具体的单元格
-
三级定位
- 行键 +(列族: 列)+ 时间戳
6.2 物理结构(模型)
-
Zookeeper
- 分布式协调
-
Master
- HMaster 没有单点问题,HBase 中可以启动多个 HMaster
- 负责 Table 和 Region 的管理工作
- 管理用户对 Table 的增、删、改、查操作
- RegionServer 的负载均衡
- 调整 Region 分布 , 在 Region Split 后,负责新 Region 的分配
- 在 HRegionServer 停机后,负责失效 HRegionServer 上的 Regions 迁移
-
RegionServer
- RegionServer 主要负责响应用户 I / O 请求
- 向 HDFS 文件系统中读写数据,是 HBase 中最核心的模块
- HLog 部分和多个 Region 部分
-
Hlog
- HLog 保存着用户操作 hbase 的日志
- ==实现了 Write Ahead Log (WAL)预写日志==
- Hlog 会删除已存储到 StoreFile 中的数据
-
Region
- 区域
- 保存了 row-key 的固定区域范围的数据
- 一个 Hregion 对应一个 Region
- 一个 Hregion 对应多个 Hstore
-
Hstore
- 对应一个列簇(列族)
- 一个 Hstore 包含一个 MemStore(内存储) 和多个 StoreFile
-
MemStore
- 内存储
- 内存中的一块区域, 一个 Hstore 对应一个 MemStore
- 当 MemStore 中的内容存放不下了就会刷出到硬盘以一个个的 StoreFile 存储
-
StoreFile
- 其实就是数据的存储位置
- 对 HFile 的封装**
-
Hfile
- Hadoop File
- Hdfs 的一个文件对象
7. Hbase 读写数据的流程
-
zookeeper(寻找元数据信息)
- get /hbase/meta-region-server
- 找到提供元数据信息访问的 regionserver
- 找 ”hbase:meta” 表, 再去查找要请求哪个 regionser 来读写数据
8. Hbase 的 Shell 操作
-
列出所有的命名空间(相当于 mysql 中的 show databases)
- list_namespace
-
列出指定命名空间下的所有表
- list_namespace_tables ‘ns1’
-
创建命名空间
- create_namespace ‘ns1’
-
创建表
- create ‘ns1:t1′,’f1’
-
禁用表, 因为删除表之前首先需要禁用了
- disable ‘ns1:t1’
-
启用表
- enable ‘ns1:t1’
-
删除表
- drop ‘ns1:t1’
-
添加数据
- put ‘ns1:t1′,’row001′,’f1:name’,’xiaohua’
-
查询数据
- get ‘ns1:t1′,’row001′,{COLUMN=>’f1:name’}
-
删除数据
- delete ‘ns1:t1′,’row001′,’f1:name’
-
删除一行数据
- deleteall ‘ns1:t1′,’row001’
-
统计表的行数
- count ‘ns1:t1’
9. Hbase 中的版本数据
-
创建 Hbase 表时指定列族的显示版本数
- create ‘ns1:t1′,{NAME=>’f1’,VERSIONS=>3}
-
修改 Hbase 表中的列族的显示版本数
- alter ‘ns1:t1′,{NAME=>’f1’,VERSIONS=>5}
-
查询指定版本数的数据
- get ‘ns1:t1′,{COLUMN=>’f1:name’,VERSIONS=>3}
-
== 版本号的作用 ==
根据显示的版本数, 查询出来想要版本的时间戳, 根据时间戳找出具体值
10. Hbase 中 API 的基本操作
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hbase-version>1.1.5</hbase-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase-version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>${hbase-version}</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-hbase-handler</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
public class HbaseTest {
// 添加数据
@Test
public void testPut() throws IOException {Configuration conf = HBaseConfiguration.create();
// 指定 zk 的地址
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
Connection conn = ConnectionFactory.createConnection(conf);
Table table = conn.getTable(TableName.valueOf("ns1:t1"));
Put put = new Put(Bytes.toBytes("row001"));
put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("admin02"));
table.put(put);
}
// 删除数据
@Test
public void testDelete() throws IOException {Configuration conf = HBaseConfiguration.create();
// 指定 zk 的地址
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
Connection conn = ConnectionFactory.createConnection(conf);
Table table = conn.getTable(TableName.valueOf("ns1:t1"));
Delete delete = new Delete(Bytes.toBytes("row001"));
table.delete(delete);
}
// 查询数据
@Test
public void testGet() throws IOException {Configuration conf = HBaseConfiguration.create();
// 指定 zk 的地址
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
Connection conn = ConnectionFactory.createConnection(conf);
Table table = conn.getTable(TableName.valueOf("ns1:t1"));
Get get = new Get(Bytes.toBytes("row001"));
Result result = table.get(get);
String s = Bytes.toString(result.getValue(Bytes.toBytes("f1"),Bytes.toBytes("name")));
System.out.println(s);
}
}
11. Hbase 中的 API 的管理操作
public class HbaseAdminTest {
private Connection connection;
@Before
public void init() throws Exception {Configuration conf = new Configuration();
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
connection = ConnectionFactory.createConnection(conf);
}
/**
* 创建表
*
* @throws Exception
*/
@Test
public void testCreateTable() throws Exception {
// 获取管理对象
Admin admin = connection.getAdmin();
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("t2"));
HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes("f1"));
htd.addFamily(hcd);
admin.createTable(htd);
}
/**
* 列出所有的表
* @throws Exception
*/
@Test
public void testListTableNames() throws Exception {
// 获取管理对象
Admin admin = connection.getAdmin();
TableName[] tableNames = admin.listTableNames("ns1:.*");
for (TableName tableName : tableNames) {System.out.println(tableName);
}
}
}
12. Hbase 高级查询
// 查询数据
@Test
public void testScan() throws IOException {Configuration conf = HBaseConfiguration.create();
// 指定 zk 的地址
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
Connection conn = ConnectionFactory.createConnection(conf);
Table table = conn.getTable(TableName.valueOf("ns1:t1"));
Scan scan = new Scan();
byte[] cf = Bytes.toBytes("f1");
byte[] column = Bytes.toBytes("name");
Filter filter = new SingleColumnValueFilter(cf, column, CompareFilter.CompareOp.EQUAL, Bytes.toBytes("admin123"));
scan.setFilter(filter);
// 获取包含多行数据的对象
ResultScanner resultScanner = table.getScanner(scan);
for (Result result : resultScanner) {System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("f1"), Bytes.toBytes("age"))));
}
}
13. 百万数据的插入
13.1 mysql 百万数据写入
耗时约 20 分钟
自己测试 10 分钟
8800000ms,插入 15851742tiao 数据
13.2 hbase 百万数据的写入
/**
* 百万数据的插入
*/
public class HbaseMiTest {
private Connection connection;
@Before
public void init() throws Exception {Configuration conf = new Configuration();
conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
connection = ConnectionFactory.createConnection(conf);
}
@Test
public void test01() throws IOException {HTable table = (HTable) connection.getTable(TableName.valueOf("ns1:t1"));
// 不使用每个 put 操作都刷出一次
table.setAutoFlush(false);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {Put put = new Put(Bytes.toBytes("row" + i));
// 关闭预写日志, 但是不建议使用, 因为这样做不安全
put.setWriteToWAL(false);
put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("admin" + i));
table.put(put);
if (i % 100000 == 0) {table.flushCommits();
}
}
table.flushCommits();
long endTime = System.currentTimeMillis();
System.out.println("总耗时:" + (endTime - startTime) + "ms");
}
}
大约耗时 27s
自己测试,1 分 20 秒 590/80=7.4 倍
查询一行是 9 秒
97602ms, 插入 15851742tiao 数据 8800/175=50 倍
14. Hbase 中的手动切分 region
split ‘ns1:t1′,’row040’
15. Hbase 手动移动 region
move ‘f6e6164514db53d660c5414df1f3864e’,’uplooking05,1602
**0,1539222350164'**
16. Hbase 中 row-key 的设计
- 行健的热点问题
是由于行健相似、连续且数据量过大操作成单 region 的数据量过大,进而影响读写效率
行健应该尽量的随机、不要出现连续行健。
常见的行健设计就是,比如手机号码倒置 + 时间戳,比如随机前缀 + 关系型数据库中的主键
因为 hbase 提供的查询内容非常非常 low,但是所有关于 hbase 的查询只能通过 rowkey,所以
在设计行健的时候,应该考虑将尽量多的查询条件放到 rowkey 中去,形成的行健就成为复合键
列族的设计:
cf1—–>”columnFamily”
cf2—–>”cf”
建议 hbase 表是高表,不建议宽表,因为宽表拥有的列族很多,操作并跨越的文件 (HFile) 就很多,效率会有相应影响,
反之建议使用高表,列族不宜过多(列族一般使用一个)。
在设计表的时候,各个列 / 列族名称不宜过长,因为 hbase 需要对这些数据在内存中做缓存,做索引,进而影响内存容量,所以建议不易过长,以便能够在内存中容纳更多的数据。至于阅读性,有项目文档搞定。
17. Hbase 中客户端工具
HbaseExplorer