IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> HBase -> 正文阅读

[大数据]HBase

1 HBase引言

1.1 HBase简介

HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的子项目来开发维护,用于支持结构化的数据存储。

官方网站:http://hbase.apache.org

民间中文文档:https://hbase.apachecn.org/#/

  • 2006年Google发表BigTable白皮书
  • 2006年开始开发HBase
  • 2008年北京成功开奥运会,程序员默默地将HBase弄成了Hadoop的子项目
  • 2010年HBase成为Apache顶级项目
  • 现在很多公司基于HBase开发出了定制版,比如阿里云HBase

总结:HBase是构建在HDFS之上的分布式、面向列的存储系统,在需要实时读写、随机访问的超大规模数据集时,可以使用HBase。

1.2 HBase解决问题

# 海量数据存储
	一个表百亿行 百万列;(MySQL实战最大值500万行,30列)
# 实时查询
	1秒内查询得到结果。

1.3 HBase特点

# 1. 容量大
	HBase单表百亿行,百万列。
# 2. 面向列
	HBase存储是面向列,可以在数据存在以后动态增加新列和数据,并支持列数据的独立操作。
# 3. 多版本
	HBase每个数据,可以同时保存多个版本,按照时间去标记。
# 4. 稀疏性
	HBase每条数据的增删,并不是要操作所有的列,列可以动态增加,可以存在大量空白单元格,不会占用磁盘空间,这对于海量数据来讲,非常重要。
# 5. 扩展性
	底层使用HDFS,存储能力可以横向扩展。
# 6. 高可靠性
	底层使用HDFS,拥有replication的数据高可靠性。
# 7. 高性能
	表数据达到一定规模,"自动分区",具备主键索引,缓存机制,使得HBase海量数据查询能达到毫秒级。

1.4 HBase与RDBMS

HBase关系型数据库
数据库以region的形式存在数据库以Table的形式存在
使用行键(row key)支持主键PK
使用行表示一条数据一条数据用row代表
使用列 column、列族 column familycolumn代表列数据的含义
使用HBase shell命令操作数据使用SQL操作数据
数据文件可以基于HDFS,是分布式文件系统,
可以任意扩展,数据总量取决于服务器数量
数据总量依赖于单体服务器的配置
不支持事务、不支持ACID支持事务和ACID
不支持表连接支持join表连接

1.5 HBase表逻辑结构

在这里插入图片描述

1.6 数据相关概念

# namespace 命名空间(数据库)
	hbase管理表的结构,在HDFS中对应一个文件夹。
# table 表
	hbase管理数据的结构,在HDFS中对应一个文件。
# column family 列族
	表中数据的列,要属于某个列族,所有的列的访问格式(列族:列名)
	注意:一张表中列族不宜过多,1-2即可
	1.1 创建表时不需要指定表包含的列,需要指定列族
	1.2 添加数据时,可以指定列族下的列
# rowkey 主键
	用来标记和检索数据的主键key。
# cell 单元格
	由 row key+column family+column+version 唯一确定的一条数据
# timestamp 时间戳
	时间戳,每个单元格可以保存多个值,每个值有对应的时间戳,每个cell中,不同版本的数据倒叙排序,排在最前面的是最新数据。

2 HBase伪分布式

2.1 下载

地址:http://archive.apache.org/dist/hbase/

2.2 准备

  1. 安装并配置hadoop

    [root@hadoop10 installs]# jps
    3440 Jps
    3329 SecondaryNameNode
    3030 NameNode
    3134 DataNode
    
  2. 安装并配置zookeeper

    单机版Zookeeper安装
        1.解压、配置环境变量
        2.在/opt/installs/zookeeper3.4.6/下创建data目录
        3.修改/opt/installs/zookeeper3.4.6/conf/zoo_sample.cfg文件名为zoo.cfg
        4.修改zoo.cfg , dataDir=/opt/installs/zookeeper3.4.6/data/
        5.启动zk  zkServer.sh start
    [root@hadoop10 installs]# jps
     3329 SecondaryNameNode
     3509 QuorumPeerMain
     3030 NameNode
     3595 Jps
     3134 DataNode
    
    [root@hadoop10 installs]# zkServer.sh status
     ZooKeeper JMX enabled by default
     Using config: /opt/installs/zookeeper3.4.14/bin/../conf/zoo.cfg
     Mode: standalone
    
  3. 设置日期同步

     # 查看linux系统时间
    [root@hadoop10 installs]# date
     # 重启chronyd服务,同步系统时间。
    [root@hadoop10 installs]# systemctl restart chronyd
    [root@hadoop10 installs]# date
     2020年 04月 12日 星期日 22:51:31 CST
    

2.3 启动顺序

在HBase启动之前,一定要确保HDFS、Zookeeper正常启动

  • HDFS 非HA情况 : HDFS和ZK的顺序关系不大

    启动顺序:ZK > HDFS > HBase

    关闭顺序:HBase > HDFS > ZK

  • HDFS HA情况: ZK最先启动

    启动顺序:ZK > HDFS > Hbase

    关闭顺序:HBase > HDFS > ZK

2.4 安装

# 1. 安装hbase
1. 解压HBase
	[root@hadoop10 modules]# tar zxvf hbase-1.2.4-bin.tar.gz -C /opt/installs/
2. 配置环境变量
	#JAVA
    export JAVA_HOME=/opt/installs/jdk1.8
    export PATH=$PATH:$JAVA_HOME/bin
    # HADOOP
    export HADOOP_HOME=/opt/installs/hadoop2.9.2/
    export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
    # zookeeper
    export PATH=$PATH:/opt/installs/zookeeper3.4.14/bin/
    # HBase
    export HBASE_HOME=/opt/installs/hbase1.2.4/
    export PATH=$PATH:$HBASE_HOME/bin
3. 加载profile配置
	source /etc/profile
# 2. 初始化配置文件
# 1 -------------------hbase-env.sh--------------------
# 配置Java_home
export JAVA_HOME=/opt/installs/jdk1.8

# 注释掉如下2行。
# export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
# export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"

# 禁用内置zookeeper
export HBASE_MANAGES_ZK=false
# 2. -------------------hbase-site.xml-------------------------
<configuration>
    <!-- 存储给habse的数据,最终存储在HDFS的位置  hbase这个文件夹会被自动创建在HDFS根目录 -->
    <property>
        <name>hbase.rootdir</name>
        <value>hdfs://hadoop10:9000/hbase</value>
    </property>
    <!-- 使用分布式模式 -->
    <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    <!-- zookeeper集群地址,端口默认2181不需要指定 -->
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>hadoop10</value>
    </property>
</configuration>
#  -------------------配置regionservers(regionserver所在节点的ip) -------------------
hadoop10
# 3. 启动hbase
启动顺序:
    1. 启动zookpeer
    2. 启动hdfs
    3. 启动hbase
# hbase启动方式一
1. 启动hbase
	start-hbase.sh
2. 关闭hbase
	stop-hbase.sh
	
# hbase启动方式二
1. 启动HMaster
[root@hadoop10 installs]# hbase-daemon.sh start master
# 关闭
[root@hadoop10 installs]# hbase-daemon.sh stop master

2. 启动HRegionServer
[root@hadoop10 installs]# hbase-daemon.sh start regionserver
# 关闭
[root@hadoop10 installs]# hbase-daemon.sh stop master
# 4. 验证访问
1. java进程查看
[root@hadoop10 installs]# jps
4688 NameNode
5618 HMaster
5730 HRegionServer
4819 DataNode
3509 QuorumPeerMain
6150 Jps
4984 SecondaryNameNode
2. HMaster WebUI查看
http://ip:16010
3. 进入客户端
hbase shell
hbase(main):001:0>

在这里插入图片描述

3 HBase命令

3.1 客户端命令

# 进入客户端:
	hbase shell
# 退出客户端命令:
	quit
# 帮助
	help

3.2 namespace操作

默认存在一个default的namespace
#1. 查看namespace
  list_namespace

#2. 创建namespace
  create_namespace "命名空间名字"`

#3. 删除namespace
  drop_namespace "命令空间名字"

3.3 表操作

# 1. 查看所有表
hbase(main):024:0> list
TABLE
abcns:t_person # namespace:表
t_user # default:表 default被省略了
2 row(s) in 0.1140 seconds

# 2. 查看某个namespace下的所有表
hbase(main):027:0> list_namespace_tables "abcns"
TABLE
t_person
1 row(s) in 0.3970 seconds

# 3. 创建表
语法:create "namespace:表名","列族1","列族2"
hbase(main):023:0> create "abcns:t_person","info","edu"
0 row(s) in 9.9000 seconds

# 4. 查看表结构
hbase(main):030:0> desc "abcns:t_person"
Table abcns:t_person is ENABLED
abcns:t_person
COLUMN FAMILIES DESCRIPTION
{NAME => 'edu', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE',
 DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE =>
 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
{NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE'
, DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE =
> 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 1.6400 seconds

# 5. 删除表和禁用表
hbase(main):002:0> disable "namespace:表"
0 row(s) in 4.4790 seconds

hbase(main):002:0> drop "namespace:表"
0 row(s) in 4.4790 seconds

3.4 数据增删改查

# 1. 添加数据(每次只能添加一个列)
	put "namespace:表","rowkey","列族1:列名1","值"
	
hbase(main):007:0> put 'abcns:t_person','1001','info:name','zhangsan'
0 row(s) in 1.7250 seconds
hbase(main):008:0> put 'abcns:t_person','1001','info:age',20
0 row(s) in 0.0210 seconds
hbase(main):009:0> put 'abcns:t_person','1002','info:name','lisi'
0 row(s) in 0.0190 seconds
hbase(main):010:0> put 'abcns:t_person','1002','info:age',21
0 row(s) in 0.0620 seconds

# 2. 根据rowkey查找数据
	get "namespace:表名","rowkey"

hbase(main):015:0> get 'abcns:t_person','1001'
COLUMN                     CELL
 info:age                  timestamp=1598752891747, value=20
 info:name                 timestamp=1598752881461, value=zhangsan
2 row(s) in 0.1550 seconds
	
# 3. 根据rowkey和列族查找数据
	get "namespace:表名","rowkey","列族:列"
	
# 4. scan 查询表中所有数据
	hbase(main):019:0> scan "abcns:t_person"

hbase(main):024:0> scan 'abcns:t_person'
ROW                        COLUMN+CELL
 1001                      column=info:age, timestamp=1598753486814, value=20
 1001                      column=info:name, timestamp=1598753478658, value=zhangsan
 1002                      column=info:age, timestamp=1598753520306, value=21
 1002                      column=info:name, timestamp=1598753509800, value=lisi
2 row(s) in 0.0410 seconds

# 5. scan 查询表中前2条数据
	hbase(main):022:0> scan "abcns:t_person",{LIMIT=>2}

# 6. 使用start row 和 end row 范围查找
	hbase(main):029:0> scan "abcns:t_person",{STARTROW=>"1001",STOPROW=>"1003"}
    
hbase(main):032:0> scan 'abcns:t_person',{STARTROW=>'1001',STOPROW=>'1003'}
ROW                        COLUMN+CELL
 1001                      column=info:age, timestamp=1598753486814, value=20
 1001                      column=info:name, timestamp=1598753478658, value=zhangsan
 1002                      column=info:age, timestamp=1598753520306, value=21
 1002                      column=info:name, timestamp=1598753509800, value=lisi

问题:HBase中的数据是按照Rowkey的ASCII字典顺序进行全局排序的
假如有5个Rowkey:"012", "0", "123", "234", "3",按ASCII字典排序后的结果为:"0", "012", "123", "234", "3"。
Rowkey排序时会先比对两个Rowkey的第一个字节,如果相同,然后会比对第二个字节,依次类推... 对比到第X个字节时,已经超出了其中一个Rowkey的长度,短的Rowkey排在前面。

# 7. 使用start row和limit查找
	hbase(main):032:0> scan "abcns:t_person",{STARTROW=>"1002",LIMIT=>2}

hbase(main):033:0> scan 'abcns:t_person',{STARTROW=>'1002',LIMIT=>2}
ROW                        COLUMN+CELL
 1002                      column=info:age, timestamp=1598753520306, value=21
 1002                      column=info:name, timestamp=1598753509800, value=lisi
 1003                      column=info:name, timestamp=1598753628840, value=wangwu

# 8. 修改数据
	put "namespace:表","rowkey","列族:列名","值"
	
# 9. 删除数据(删除某个cell)
	delete "namespace:表","rowkey","列族:列名"
	
# 10. 删除某个rowkey对应的数据
	deleteall "namespace:表","rowkey"
	
# 11. 统计表中所有数据
	count "namespace:表"

# 12. 清空表中的所有数据
    truncate "namespace:表"

3.5 多版本问题

# 1. 创建表
hbase(main):013:0> create "abcns:user","info"
# 2. 修改版本数
hbase(main):016:0> alter "abcns:user",{NAME=>'info',VERSIONS=>2}

# 表的列族的VERSIONS=>2表示的该列族的数据,要保存2个版本。如果put3次,则保留最新的2个版本。

# 3. 同一个cell添加2次数据。
hbase(main):014:0> put "abc:user","10001","info:name","aaa"
0 row(s) in 0.2620 seconds

hbase(main):015:0> put "abc:user","10001","info:name","bb"
0 row(s) in 0.0290 seconds
# 4. 查看多版本
hbase(main):017:0> get "abc:user","10001",{COLUMN=>'info:name',VERSIONS=>3}
COLUMN                      CELL
 info:name                  timestamp=1586795010367, value=bb
 info:name                  timestamp=1586795004085, value=aaa
说明:
	1. 可以查看VERSIONS指定的版本数量的值。
	2. cell中多个版本的值,按照时间戳降序排序。
	3. 在get或者scan查询数据,并不指定VERSIONS,默认读取的cell中最新的1个的版本的值。

4 HBase API

4.1 环境准备

  • 依赖

    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-client</artifactId>
        <version>1.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-server</artifactId>
        <version>1.2.4</version>
    </dependency>
    
  • 初始化配置

    将hbase中的conf中的 hbase-site.xml放到resource配置文件目录中。

    conf.addResource("/hbase-site.xml")

  • windows配置IP映射

4.2 API介绍

API含义创建
Configuration配置文件HBaseConfiguration.create();
Connection连接,用来操作数据ConnectionFactory.createConnection(conf);
Admin客户端,用来操作元数据
(namespace和table结构)
conn.getAdmin();
NamespaceDescriptor命名空间相当于databaseNamespaceDescriptor.create(“abcns”).build();
TableName表名TableName.valueOf(“abc:user”);
HTableDescriptornew HTableDescriptor(tablename);
HColumnDescriptor列族new HColumnDescriptor(“info”);
Put添加数据new Put(Bytes.toBytes(“10001”));
Deleterowkey的删除条件new Delete(Bytes.toBytes(“10001”));
Getscan多行查询器new Get(Bytes.toBytes(“10019”));
Scanscan多行查询器new Scan();
Result查询结果集(单条结果)table.get(get);
ResultScanner查询结果集(N条结果)table.getScanner(scan);
Bytes类型转化工具类,HBase中数据类型为字节,
所有类型存入后都变成字节,需要相互转化。

4.3 HBase客户端

注意:配置windows向linux的ip映射

// 获得客户端
//1. 读取配置文件
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum","hadoop10");
BasicConfigurator.configure();//打印日志信息
//2. 建立连接
Connection conn = ConnectionFactory.createConnection(conf);
//3. 获得客户端
admin = conn.getAdmin();
// 释放资源
admin.close();

4.4 常用API

4.4.1 创建namespace

//1. 构建namespace信息。
NamespaceDescriptor abcns = NamespaceDescriptor.create("abcns").build();
//2. 创建namespace
admin.createNamespace(abcns);

4.4.2 表操作

操作表,使用admin

  • 判断表是否存在

    //1. 创建表名
    TableName tableName = TableName.valueOf("abcns:person");
    //2. 判断表是否存在
    boolean b = admin.tableExists(tableName);
    System.out.println(b?"存在":"不存在");
    
  • 创建表

    //1. 初始化表名
    TableName person = TableName.valueOf("abcns:person");
    //2. 初始化列族信息
    HColumnDescriptor info = new HColumnDescriptor("info");
    HColumnDescriptor addr = new HColumnDescriptor("addr");
    //3. 绑定表名,绑定列族
    HTableDescriptor hTableDescriptor = new HTableDescriptor(person);
    hTableDescriptor.addFamily(info);
    hTableDescriptor.addFamily(addr);
    //4. 创建表
    admin.createTable(hTableDescriptor);
    

4.4.3 添加

操作数据使用conn

//1. 初始化要操作的表
Table table = conn.getTable(TableName.valueOf("abcns:t_person"));
//2. 创建 添加数据
Put put = new Put(Bytes.toBytes("1001"));//构造rowkey
// Bytes是HBase提供的进行字节和java数据类型转化的工具类
put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes("张三") );
put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("age"), Bytes.toBytes(18));
put.addColumn(Bytes.toBytes("addr"), Bytes.toBytes("zipCode"), Bytes.toBytes("45000"));
//3. 将put数据添加。
table.put(put);
//4. 释放资源
table.close();

4.4.4 修改

//1. 初始化要操作的表
Table table = conn.getTable(TableName.valueOf("abcns:person"));
//2. 修改的本质就是添加,利用时间戳覆盖旧的数据而已。
Put put = new Put(Bytes.toBytes("1001"));
put.addColumn(Bytes.toBytes("addr"), Bytes.toBytes("zipCode"), Bytes.toBytes("45001"));
//3. 添加到表中
table.put(put);
//4. 关闭table
table.close();

4.4.5 删除

//1. 获得要操作的表
Table table = conn.getTable(TableName.valueOf("abcns:person"));
//2. 创建要删除的条件,以rowkey为条件
Delete delete = new Delete(Bytes.toBytes("1001"));
//删除某个列族
//delete.addFamily(Bytes.toBytes("cf2"));
//删除某个列
//delete.addColumn(Bytes.toBytes("cf1"),Bytes.toBytes("age"));
//3. 执行删除
table.delete(delete);

4.4.6 查询

  • 根据rowkey单条查询

    //1. 获得要操作的表
    Table table = conn.getTable(TableName.valueOf("abcns:person"));
    //2. 使用rowkey作为查询条件
    Get get = new Get(Bytes.toBytes("10019"));
    //3. 执行查询
    Result result = table.get(get);
    //4. 处理结果集:result.getValue;
    byte[] namebyte = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
    //下面代码雷同。
    byte[] agebyte = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
    byte[] zipbyte = result.getValue(Bytes.toBytes("addr"), Bytes.toBytes("zipCode"));
    //获得rowkey
    byte[] rowbytes = result.getRow();
    System.out.println(Bytes.toString(namebyte));
    System.out.println(Bytes.toInt(agebyte));
    System.out.println(Bytes.toString(zipbyte));
    
  • 多条查询

    //1. 获得要操作的表
    Table table = conn.getTable(TableName.valueOf("abcns:person"));
    //2. 创建scan扫描器,多行查询
    Scan scan = new Scan();
    //3. 指定要投射的列族。
    scan.addFamily(Bytes.toBytes("info"));
    scan.addFamily(Bytes.toBytes("addr"));
    //4. 设置起始和查询条数
    scan.setStartRow(Bytes.toBytes("1001"));
    scan.setFilter(new PageFilter(3));
    //5. 执行查询
    ResultScanner result = table.getScanner(scan);
    //6. 处理结果集
    for (Result res:result){
        byte[] namebyte = res.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
        byte[] agebyte = res.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
        byte[] zipCodebyte = res.getValue(Bytes.toBytes("addr"), Bytes.toBytes("zipCode"));
        String name = Bytes.toString(namebyte);
        int age = Bytes.toInt(agebyte);
        String zipcode = Bytes.toString(zipCodebyte);
        System.out.println(name+":"+age+":"+zipcode);
    }
    //7. 关闭table
    table.close();
    
  • 范围查询

    //1. 获得要操作的表
    Table table = conn.getTable(TableName.valueOf("abcns:person"));
    //2. 创建scan扫描器,多行查询
    Scan scan = new Scan();
    //3. 指定要投射的列族。
    scan.addFamily(Bytes.toBytes("info"));
    scan.addFamily(Bytes.toBytes("addr"));
    //4. 设置起始和查询条数
    scan.setStartRow(Bytes.toBytes("1001"));
    scan.setStopRow(Bytes.toBytes("1003"));
    //5. 执行查询
    ResultScanner result = table.getScanner(scan);
    //6. 处理结果集
    for (Result res:result){
        byte[] namebyte = res.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
        byte[] agebyte = res.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
        byte[] zipCodebyte = res.getValue(Bytes.toBytes("addr"), Bytes.toBytes("zipCode"));
        String name = Bytes.toString(namebyte);
        int age = Bytes.toInt(agebyte);
        String zipcode = Bytes.toString(zipCodebyte);
        System.out.println(name+":"+age+":"+zipcode);
    }
    //7. 关闭table
    table.close();
    
  • 前缀查询

    Scan scan = new Scan();
    Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new RegexStringComparator("a-"));
    scan.setFilter(filter);
    ResultScanner results = table.getScanner(scan);
    for (Result result : results) {
        byte[] nameByte = result.getValue(Bytes.toBytes("cf1"),Bytes.toBytes("name"));
        byte[] ageByte = result.getValue(Bytes.toBytes("cf1"),Bytes.toBytes("age"));
        System.out.println(Bytes.toString(nameByte) + "\t" + Bytes.toString(ageByte));
    }
    table.close();
    
  • 多版本查询

    Get get = new Get(Bytes.toBytes("1001"));
    //可以指定查询某一个列
    get.addColumn(Bytes.toBytes("cf1"),Bytes.toBytes("name"));
    get.setMaxVersions(5);
    Result result = table.get(get);
    //方式1
    Cell[] cells = result.rawCells();
    for (Cell cell : cells) {
        System.out.println(Bytes.toString(CellUtil.cloneValue(cell)));
    }
    //方式2
    List<Cell> cells = result.listCells();
    for (Cell cell : cells) {
        System.out.println(Bytes.toString(CellUtil.cloneValue(cell)));
    }
    

5 HBase架构体系

5.0 HBase基础架构

在这里插入图片描述

5.1 HRegionServer

HBase 是集群结构,会把这些块儿分散存储到多个服务器中,每个服务器名为HRegionServer
在这里插入图片描述

HRegionServer(和DataNode同一节点)
1. 存储表数据部分
2. put delete get scan等针对数据的操作
3. 定时向Master报告自身节点的状态
4. 管理表的数据的Table的数据

5.2 HMaster

服务器多,需要一个管理者HMaster,负责 HRegion 的分配、HRegionServer 负载均衡的处理
在这里插入图片描述

HMaster
1. Region Server状态的管理
2. 表的管理:create drop alter
3. 实现HRegionServer的数据负载均衡,平衡HRegion的分布

5.3 Zookeeper

Zookeeper
1. 解决HMaster的单点故障问题
2. 存放HMaster管理的HRegionServer的状态信息,并通知HMaster
3. 存放HMaster管理的表的元数据信息
   表名、列名、key区间等。

5.4 HRegion

当某个 HRegion 的大小达到阈值后,便会被分割开来,新的 HRegion 也会由 HMaster 进行分配,放置到合适的 HRegionServer 中,HRegion 是 HBase 中分布式存储的最小单元,但并不是存储的最小单元,HRegion 内部会按照列族进行切分,分为多个 Store,每个 Store 保存一个列族,所以 HRegion 由一个或者多个 Store 组成
在这里插入图片描述

HRegion
1. 表的横向切片的物理表现,大表的子表,有(startkey endkey),多行数据。
2. 为了减小单表操作的大小,提高读写效率。

5.5 Store

每个 Strore 又由一个 MemStore 和 N个 StoreFile 组成 , MemStore 是内存存储单元,当内存中数据达到阈值后,写入 StoreFile,StoreFile 以 HFile 格式保存
在这里插入图片描述

Store
1. 表的纵向切分的物理表现,按照列族作为切分。
2. 按照列族查询,仅需要检索一定范围内的数据,减少全表扫描。

在这里插入图片描述

6 HBase读写原理

meta表:快速定位一条数据,在哪个regionserver的region中

6.1 读数据

获取读数据的region所在的RegionServer,先去BlockCache读取,若BlockCache没有,则到Memstore读取,若Memstore中没有,则到HFile中去读。

在这里插入图片描述

6.2 写数据

获取写数据的region所在的RegionServer,然后先将数据写到WAL(Write-Ahead Logging,预写日志系统)中,然后再将数据写到Memstore等待刷新,回复客户端写完成,然后再写入到storefile

在这里插入图片描述

7 HBase底层原理

7.1 Region Split分区

  • 分区原因:提高Region的负载和读写效率
    在这里插入图片描述

  • 分区说明:Region一拆为二,并分布在不同的RegionServer上

  • 默认分区机制:

    Region中数据超过128M、512M、1152M… *Region数量2hbase.hregion.memstore.flush.size … 10G、10G

    hbase.hregion.memstore.flush.size=128M
    hbase.hregion.max.filesize=10G
    

在这里插入图片描述

  • 分区问题

    默认分区容易导致数据倾斜,硬件资源无法利用。(数据热点问题,大量的客户端访问,落在部分节点上,导致忙的忙死,闲的闲死。)

7.2 Region 预分区

  • 预分区原因

    ①增加读写效率。(多个region分布在不同的RegionServer中,可以提高并发效率)

    ②尽量保证每个Region中的数据量相当,防止数据倾斜。(合理利用计算资源)

  • 分区效果

    每个Region维护一对StartKey和EndKey,限定维护输入rowkey范围。

    添加数据时,将rowkey放入匹配的region中

    region的切分问题:

    1. 切分的过程影响集群的运行效率

    2. region切分之后,可能会导致单个region的热点问题

  • 命令预分区

    命令:create "namespace:表","列族",SPLITS=>["100000","200000","300000","400000"]

    效果:(http://ip:16030)访问RegionServers

  • Java预分区
    在这里插入图片描述

7.3 MemStore Flush刷写

  • 刷写说明

    简言:持久化,保护数据不丢失。

    将RegionServer中内存中的数据Memstore,写入到硬盘中。

在这里插入图片描述
在这里插入图片描述

  • 刷写时机(自动刷写)

    1. 当 region server 中 memstore 的总大小达到java_heapsize的阈值,默认值 0.4

      对应参数:hbase.regionserver.global.memstore.size

    2. 到达自动刷写的时间,默认 1 小时

      对应参数:hbase.regionserver.optionalcacheflushinterval

    3. 单个Region中的数据文件大小超过128M

      对应参数:hbase.hregion.memstore.flush.size

  • 手动flush

    命令:flush "namespace:表名"

  • 文件位置:

    hdfs:ip:50070/hbase/data/abcns/user2/faf64f7f6cfa6282c2a92864faa3909d
    

7.4 StoreFile Compaction

  • 目的

    storefile小文件过多,查询时,需要遍历所有文件,效率低。

    storefile中遍布过期数据,占用空间,且查询效率低。

  • 说明

    简言:为提高检索效率,合并store。
    在这里插入图片描述

  • 分类和时机

    • minor compact(局部合并)

      特点:少量相邻(加速合并,并有序)文件的合并

      时机:发生频率较高,不影响性能。

      手动命令:compact "namespace:表名"

    • major compact(全局合并)

    特点:

    1. 全局的所有store file文件的合并。
    2. 去除删除被覆盖的文件。
    3. 特别消耗RegionServer的性能资源。(重点)
      服务器执行全局合并至,对外暂时不提供服务

    时机:每7天执行一次:参数:hbase.hregion.majorcompaction

    一般手动触发。手动触发命令:major_compact "namespace:表名"

7.5 rowkey设计原则

HBase四点RowKey设计原则:长度原则、唯一原则、排序原则,散列原则

  1. 长度原则:RowKey本质上是一个二进制码的流,可以是任意字符串,最大长度为64kb,实际应用中一般为10-100byte,以byte[]数组形式保存,一般设计成定长。官方建议越短越好,不要超过16个字节。

  2. 唯一原则:由于RowKey用来唯一标识一行记录,所以必须在设计上保证RowKey的唯一性。

  3. 排序原则:HBase会把RowKey按照ASCII进行自然有序排序,所以反过来在设计RowKey的时候可以根据这个特点来设计完美的RowKey,利用好这个特性就是排序原则。

  4. 散列原则:设计出的RowKey需要能够均匀的分布到各个RegionServer上。比如设计RowKey的时候,当Rowkey 是按时间戳的方式递增,就不要将时间放在二进制码的前面,可以将 Rowkey 的高位作为散列字段,由程序循环生成,可以在低位放时间字段,这样就可以提高数据均衡分布在每个Regionserver实现负载均衡的几率。
    在这里插入图片描述

7.6 热点现象及解决

当大量请求访问HBase集群的一个或少数几个节点,造成少数RegionServer的读写请求过多,负载过大,而其他RegionServer负载却很小,这样就造成热点现象

通过RowKey优化,避免热点现象

  1. 反转(Reversing):顾名思义就是把固定长度或者数字格式的rowkey进行反转,反转分为一般数据反转和时间戳反转,其中以时间戳反转较常见。

    适用场景:初步设计出的RowKey在数据分布上不均匀,但RowKey尾部的数据却呈现出了良好的随机性(注意:随机性强代表经常改变,没意义,但分布较好),可以考虑将RowKey的信息翻转,或者直接将尾部的bytes提前到RowKey的开头。反转可以有效的使RowKey随机分布,但是反转后有序性就得不到保障,因此它牺牲了RowKey的有序性。

  2. 加盐(Salting):不同于密码学里的加盐方法,RowKey的加盐原理是在原RowKey的前面添加固定长度的随机数,也就是给RowKey分配一个随机前缀使它和之前的RowKey的开头不同。

    适用场景:设计的RowKey虽有意义,但是数据类似,随机性比较低,反转也没法保证随机性,这样就没法根据RowKey分配到不同的Region里,这时候就可以使用加盐的方式。

    需要注意随机数要能保障数据在所有Regions间的负载均衡,也就是说**分配的随机前缀的种类数量应该和想把数据分散到的那些region的数量一致**。只有这样,加盐之后的rowkey才会根据随机生成的前缀分散到各个region中,避免热点现象。

  3. 哈希(Hashing):基于RowKey的完整或部分数据进行Hash,而后将哈希后的值完整替换或部分替换原RowKey的前缀部分。这里说的hash常用的有MD5、sha1、sha256 或 sha512 等算法。

    适用场景:哈希和加盐的适用场景类似,但是由于加盐方法的前缀是随机数,用原rowkey查询时不方便,因此出现了哈希方法,由于哈希是使用各种常见的算法来计算出的前缀,因此哈希既可以使负载分散到整个集群,又可以轻松读取数据。

7.7 BlockCache(高速读写)

# 1 Memstore
  Region内存中
  特点:
  	(内存)
  	(数据最新的)
  	(有序)
# 2 BlockCache(LRU)
   HBase缓存中。
   缓存策略:LRU(数据淘汰机制),最近最少使用原则,保留最近最新使用多的数据。
   
写:数据写入MemStore(内存),然后再刷写到storefile (硬盘) 
   MemStore提供写的效率,底层写入数据到MemStore就认为写功能
   
读:从BlockCache(内存缓存)中读取,读取不到再去MemStore(内存)中读,读取不到再去StoreFile(硬盘)中读取,读取到数据之后存储到BlockCache(内存缓存)中
    BlockCache底层采用的LRU算法,会将最近最少使用的数据淘汰掉,保证内存中多存储一些热点数据 

8 HBase完全分布式

注意

  1. 编辑regionservers,使用vi编辑
  2. 安装hbase之前,同步系统时间

8.1 官方架构图

在这里插入图片描述

8.2 完全分布式

集群规划
192.168.199.11: HMaster
192.168.199.12: HRegionServer
192.168.199.13: HRegionServer
# 0 确保HDFS HA已经搭建完毕
[root@hadoop11 ~]# jps
1259 JournalNode
1965 NameNode
1758 DFSZKFailoverController
2110 Jps
1215 QuorumPeerMain
# 1. 安装HBase
1. 解压HBase
	[root@hadoop11 modules]# tar zxvf hbase-1.2.4-bin.tar.gz -C /opt/installs/
2. 配置环境变量
	#JAVA
    export JAVA_HOME=/opt/installs/jdk1.8
    export PATH=$PATH:$JAVA_HOME/bin
    # HADOOP
    export HADOOP_HOME=/opt/installs/hadoop2.9.2/
    export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
    # zookeeper
    export PATH=$PATH:/opt/installs/zookeeper3.4.14/bin/
    # HBase
    export HBASE_HOME=/opt/installs/hbase-1.2.4
    export PATH=$PATH:$HBASE_HOME/bin
3. 加载profile配置
	source /etc/profile
# 2. 初始化HBase 配置文件
# 1 -------------------hbase-env.sh--------------------
# 配置Java_home
export JAVA_HOME=/opt/installs/jdk1.8

# 注释掉如下2行。
# export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
# export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"

# 禁用内置zookeeper
export HBASE_MANAGES_ZK=false
# 2. -------------------hbase-site.xml-------------------------
<configuration>
    <!-- hbase的入口,ns HaHadoop的虚拟命名空间 -->
    <property>
        <name>hbase.rootdir</name>
        <value>hdfs://hdfs-cluster/hbase</value>
    </property>
    <!-- 使用分布式模式 -->
    <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    <!-- zookeeper集群地址,端口默认2181不需要指定 -->
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>hadoop11,hadoop12,hadoop13</value>
    </property>
</configuration>
# 3. -------------------regionservers--------------------
hadoop12
hadoop13
#** 4. 将hadoop的配置文件拷贝到hbase的conf目录中。(core-site.xml  hdfs-site.xml)
[root@hadoop11 installs]# ln -s /opt/installs/hadoop2.9.2/etc/hadoop/core-site.xml /opt/installs/hbase-1.2.4/conf/core-site.xml
[root@hadoop11 installs]# ln -s /opt/installs/hadoop2.9.2/etc/hadoop/hdfs-site.xml /opt/installs/hbase-1.2.4/conf/hdfs-site.xml
# 3. 远程拷贝
1. 拷贝profile文件
[root@hadoop11 installs]# scp /etc/profile root@hadoop12:/etc/
[root@hadoop11 installs]# scp /etc/profile root@hadoop13:/etc/
2. 拷贝hbase安装软件和配置文件
[root@hadoop11 installs]# scp -r hbase-1.2.4/ root@hadoop12:/opt/installs/
[root@hadoop11 installs]# scp -r hbase-1.2.4/ root@hadoop13:/opt/installs/
3. 重新加载profile
[root@hadoop11 ~]# source /etc/profile
[root@hadoop12 ~]# source /etc/profile
[root@hadoop13 ~]# source /etc/profile
# 3. 启动HBase
1. 启动hbase
	start-hbase.sh
2. 关闭hbase
	stop-hbase.sh
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:42:24  更:2021-07-11 16:43:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 5:32:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码