admin 管理员组

文章数量: 887175

14

八、HBase

🔖Day14-Hbase的入门及系统框架

重点掌握

1、掌握Hbase的数据存储结构
2、掌握Hbase的访问方式
3、掌握Hbase的系统架构

理解内容

1、Hbase的四维数据存储模型 -03
2、Hbase0.96前后数据定位方式 -24~25

8.1HBase的介绍

8.1.1HBase简介

  1. 定义理解:

    • HBase(HadoopDatabase)是一个开源的非关系型的分布式数据库,运行于HDFS文件系统之上,可以容错地存储海量稀疏的数据。HBase是一个高可靠、高性能、面向列、可伸缩、实时读写的分布式数据库,主要用来存储非结构化半结构化的松散数据

    • 基于列式存储,适合大数据的实时查询。

    • 对于结构化和非结构化的理解

      • 结构化数据
        • 关系型数据库围绕表、列和数据类型——数据的形态使用严格的规则。遵守这些严格规则的数据称为结构化数据。
      • 非结构化数据
        • HBase 设计上没有严格形态的数据。数据记录可能包含不一致的列、不确定大小等。这种数据称为半结构化数据(semistructured data)
  2. HBase与其他组件的结合使用

    • 利用HDFS作为其文件存储系统
    • 利用Zookeeper作为其分布式系统服务
    • 利用MapReduce来处理HBase中的海量数据

    参考资料: Hbase简介与基本原理_奋斗吧,青年!的博客-CSDN博客_hbase原理

8.1.2HBase优点

  1. 容量大

    • HBase单表可以有百亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性
  2. 面向列

    • 面向列的存储和权限控制,并支持独立检索,可以动态增加列。即,可以单独对列进行各方面的操作列式存储,其数据在表中时按照某列存储的,这样在查询只需要少数的几个字段的时候,能大大减少读取的数量
    • 下图显示了列族在面向列的数据库:

  3. 多版本

    • HBase的每一个列的数据存储有多个version,比如住址列,可能有多个变更,所有该列可以有多个version
  4. 稀疏性

    • 为空的列并不占用存储空间,表可以设计的非常稀疏
    • 不必向关系型数据库那样需要预先知道所有的列然后进行null填充
  5. 拓展性:

    • 底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加datanode节点服务(机器)就可以了
  6. 高可靠性:

    • WAL机制,保证数据写入的时候不会因为集群异常而导致写入数据丢失Replication机制,保证了在集群出现严重的问题时候,数据不会发生丢失或者损坏Hbase底层使用HDFS,本身也有备份。
  7. 高性能:

    • 底层的LSM数据结构和RowKey有序排列等架构上的独特设计,使得Hbase写入性能非常高。Region切分、主键索引、缓存机制使得Hbase在海量数据下具备一定的随机读取性能,该性能针对Rowkey的查询能够到达毫秒级别,LSM树,树形结构,最末端的子节点是以内存的方式进行存储的,内存中的小树会flush到磁盘中(当子节点达到一定阈值以后,会放到磁盘中,且存入的过程会进行实时merge成一个主节点,然后磁盘中的树定期会做merge操作,合并成一棵大树,以优化读性能。)
      LSM树的介绍:.html

8.1.3 HBase应用

Hbase是一种NoSQL数据库,这意味着它不像传统的RDBMS数据库那样支持SQL作为查询语言。Hbase是一种分布式存储的数据库,技术上来讲,它更像是分布式存储而不是分布式数据库,它缺少很多RDBMS系统的特性,比如列类型,辅助索引,触发器,和高级查询语言等待。那Hbase有什么特性呢?如下

  1. 适合用HBase的场景

    • 首先数据库量要足够多,如果有十亿及百亿行数据,那么Hbase是一个很好的选项,如果只有几百万行甚至不到的数据量,RDBMS是一个很好的选择。因为数据量小的话,真正能工作的机器量少,剩余的机器都处于空闲的状态
    • 其次,如果你不需要辅助索引,静态类型的列,事务等特性,一个已经用RDBMS的系统想要切换到Hbase,则需要重新设计系统。
    • 最后,保证硬件资源足够,每个HDFS集群在少于5个节点的时候,都不能表现的很好。因为HDFS默认的复制数量是3,再加上一个NameNode。
    • Hbase在单机环境也能运行,但是请在开发环境的时候使用。
  2. 实际应用场景

    • 存储业务数据:车辆GPS信息,司机点位信息,用户操作信息,设备访问信息。。。
    • 存储日志数据:架构监控数据(登录日志,中间件访问日志,推送日志,短信邮件发送记录。。。),业务操作日志信息
    • 存储业务附件:UDFS系统存储图像,视频,文档等附件信息

    不过在公司使用的时候,一般不使用原生的Hbase API,使用原生的API会导致访问不可监控,影响系统稳定性,以致于版本升级的不可控。

  3. Hbase和RDBMS的比较

    属性HbaseRDBMS
    数据类型只有字符串丰富的数据类型
    数据操作增删改查,不支持join各种各样的函数与表连接
    存储模式基于列式存储基于表结构和行式存储
    数据保护更新后仍然保留旧版本替换
    可伸缩性轻易增加节点需要中间层,牺牲性能
  4. 数据管控层(助于理解)

8.2 HBase数据模型

HBase 是一个稀疏的、分布式、持久、多维、排序的映射,它以行键(row key),列族(columnFamily),列名(Column Qualifier)和时间戳(timestamp)为索引。

8.2.1 NameSpace 命名空间

  1. 定义理解
    • 命名空间是类十余关系数据库系统中的数据库的概念,他其实是表的逻辑分组,这种抽象为多租户相关功能奠定了基础
    • 为了保护我们的表,创建的一个更高层级的单位
    • 命名空间是可以管理维护的,可以创建、删除或者更改
  2. 两个特殊预定义的命名空间:
    • default :没有明确指定名称空间的表将会自动落入此名称空间
    • hbase :系统命名空间,用户包含HBase内部表

8.2.2 Table 表

  1. 定义理解
    • 存储相同数据的一个逻辑单元
    • 表有多个行数据组成,行有很多列组成
    • HBase是一个半结构化的数据库,所以每一行的列都有可能是不同的

8.2.3 RowKey 行键

  1. 定义理解
    • RowKey是用来检索记录的主键,是一行数据的唯一标识
    • RowKey(行键)可以是任意字符串(最大长度是64KB,实际应用中长度一般为 10-100bytes),RowKey以字节数组保存。
    • HBase按照列进行存储,所以我们查询数据的时候会看到很多RowKey相同的列
  2. RowKey排序规则
    • RowKey存储的时候默认是以字典序排序的

8.2.4 Column Family 列族

  1. 定义理解
    • 列族在物理上包含了许多的列与列的值,每个列族都有一些存储的属性可配置
      • 例如是否使用缓存、压缩类型、存储版本等。在表中,每一行都有相同的列族,尽管有些列族什么东西也没存。
    • 可以理解为多个列的集合,方便队列进行查找和管理
    • 一个表的列族需要在创建之前就要声明(先创建表,后期再维护表),而且一般一个表中的列族数不要超过3个
  2. 列的存放原则
    • 将功能属性相近的列存放在同一个列族,而且同一个列族中的列存放在同一个Store中
  3. 列、列族和表之间的关系
    • 列属于列族,列族属于表,即 列-->列族-->表
    • 一个表中的列族是固定的,但是列族中的列是不固定的

8.2.5 Column Qualifier

  1. 定义理解
    • 列族额限定词,理解为列的唯一标识。但是列标识是可以改变的,因此每一行可能有不同的列标识
    • 使用的时候必须 列族:列
    • 列可以根据需求动态添加或者删除,同一个表中不同行的数据列都可以不同

8.2.6 TimeStamp

  1. 定义理解:
    • 默认数据版本就是时间戳,解决HDFS不能随时修改数据的弊端
    • 查询数据的时候默认显示最新的数据
  2. 版本回收方式
    • 为了避免数据存在过多版本中造成管理 (包括存贮和索引)负担,HBASE 提供了两种数据版本回收方式
      • 一是保存数据的最后n个版本
      • 二是保存最近一段时间内的版本(比如最近七天)

8.2.7 Cell

  1. 定义理解:
    • Cell是由row,column family,column qualifier,version 组成的,所有的数据都是字符串
    • Cell中的数据是没有类型的,全部是字节码形式存贮。
      • 因为HDFS上的数据都是字节数组

8.3 HBase高可用集群搭建

8.3.1准备安装环境

  • [root@node01 ~]# tar -zxvf hbase-2.2.5-bin.tar.gz
  • [root@node01 ~]# mv hbase-2.2.5 /opt/yjx/
  • [root@node01 ~]# cd /opt/yjx/hbase-2.2.5/conf/

8.3.2 修改集群环境

  • [root@node01 conf]# vim hbase-env.sh

    export HBASE_LOG_DIR=${HBASE_HOME}/logs
    export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
    export HBASE_MANAGES_ZK=false
    export HADOOP_HOME=/opt/yjx/hadoop-3.1.2/
    

8.3.3修改配置文件

  • [root@node01 conf]# vim hbase-site.xml

    <!-- 31dd -->
    <!--设置HBase表数据,也就是真正的HBase数据在hdfs上的存储根目录-->
    <property>
    <name>hbase.rootdir</name>
    <value>hdfs://hdfs-yjx/hbase</value>
    </property>
    <!--是否为分布式模式部署,true表示分布式部署-->
    <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
    </property>
    <!--zookeeper集群的URL配置,多个host中间用逗号-->
    <property>
    <name>hbase.zookeeper.quorum</name>
    <value>node01:2181,node02:2181,node03:2181</value>
    </property>
    <!--HBase在zookeeper上数据的根目录znode节点-->
    <property>
    <name>zookeeper.znode.parent</name>
    <value>/hbase</value>
    </property>
    <!-- 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很
    多文件都会默认设置成它下面的-->
    <property>
    <name>hbase.tmp.dir</name>
    <value>/var/yjx/hbase</value>
    </property>
    <!-- 使用本地文件系统设置为false,使用hdfs设置为true -->
    <property>
    <name>hbase.unsafe.stream.capability.enforce</name>
    <value>false</value>
    </property>
    
  • vim regionservers

    node01
    node02
    node03
    

8.3.4 备用Master节点

  • [root@node01 conf]# vim backup-masters

    node02
    

8.3.5 拷贝Hadoop配置文件

  • [root@node01 conf]# cp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml /opt/yjx/hbase-2.2.5/conf/
  • [root@node01 conf]# cp /opt/yjx/hadoop-3.1.2/etc/hadoop/hdfs-site.xml /opt/yjx/hbase-2.2.5/conf/

8.3.6 拷贝分发软件

  • [root@node02 ~]# scp -r root@node01:/opt/yjx/hbase-2.2.5 /opt/yjx/
  • [root@node03 ~]# scp -r root@node01:/opt/yjx/hbase-2.2.5 /opt/yjx/

8.3.7 修改环境变量

  • [root@node01 conf]# vim /etc/profile

    export HBASE_HOME=/opt/yjx/hbase-2.2.5
    export PATH=$HBASE_HOME/bin:$PATH
    
  • 拷贝到其他节点

    • [root@node01 conf]# scp /etc/profile root@node02:/etc/profile
    • [root@node01 conf]# scp /etc/profile root@node03:/etc/profile
  • 让配置文件生效

    • 【123】 source /etc/profile

8.4.8 启动集群

  • 【123】 zkServer.sh start
  • [root@node01 conf]# start-all.sh
  • [root@node01 conf]# start-hbase.sh

8.4.9 web页面验证

  1. 可以看到服务器1启动和HMaster 和 HRegionServer进程,服务器2和服务器3启动和HRegionServer进程。

  2. 查看HBase的集群情况:http://192.168.88.101:16010

8.4 HBase访问方式

8.4.1 HBase shell

我们可以先用HBase提供的命令行工具,位于HBase的/bin/目录下

  1. 开启环境命令

    • 【123】zkServer.sh start
    • 【1】start-all.sh
    • 【1】start-hbase.sh
  2. 进入退出HBase

    • hbase shell
    • exit
  3. 关闭环境并关机命令

    • 【1】stop-hbase.sh
    • 【1】stop-all.sh
    • 【123】zkServer.sh stop
    • 【123】shutdown -h now
  4. 查看帮助信息

    • help
  5. 查询服务器状态

    • status
  6. 查询hbase版本

    • version

1. Shell实现DDL操作

  1. 创建表

    • 语法:create ‘表名’ , {NAME => , VERSIONS => }
    • 例如:创建表t1,有两个family name:f1,f2,且版本数均为2
      • create ‘t1’,{NAME => ‘f1’, VERSIONS => 2},{NAME => ‘f2’, VERSIONS=> 2}
    • 非标准创建表的语法:创建表member,列族是member_id,address,info,版本为1
      • create ‘member’,‘member_id’,‘address’,‘info’
  2. 获得表的描述信息

    • 语法:
      • list ‘表名’
      • describe ’ 表名’
    • 例如
      • list :查看所有的表名称(列出所有的表)
      • describe ‘member’ :查看表的描述信息
  3. 删除一个列族

    • 语法 alter,disable,enable
      • alter
        • 我们之前建了3个列族,但是发现member_id这个列族是多余的,因为他就是主键,所以我们要将其删除
        • alter ‘member’,{NAME=>‘member_id’,METHOD=>‘delete’}
      • enable
        • 使表可用
        • enable ‘member’
      • disable
        • 禁用表
        • disable ‘member’
  4. drop一个表

    create 'temp_table','member_id','address','info'
    hbase(main):029:0>disable 'temp_table'
    hbase(main):030:0>drop 'temp_table'
    
  5. 查询表是否存在

    exists 'member'
    
  6. 判断表是否enable(启用)

    is_enabled 'member'
    
  7. 判断表是否disable

    is_disabled 'member'
    
  8. 查看文件存储路径

    hdfs dfs -ls /yjx/hbase/data/default/member

  9. truncate此命令将删除并重新创建一个表

    truncate ‘t1’

  10. 表的预分区

    # create table with specific split points
    hbase>create 'table1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00','\x40\x00']
    # create table with four regions based on random bytes keys
    hbase>create 'table2','f1', { NUMREGIONS => 8 , SPLITALGO => 'UniformSplit' }
    # create table with five regions based on hex keys
    hbase>create 'table3','f1', { NUMREGIONS => 10, SPLITALGO => 'HexStringSplit' }
    

2.Shell实现DML操作

3.Shell实现DQL操作

4. Shell实现Region管理

8.4.2 Java访问HBaseAPI

8.5 HBase架构模型

HBase有三个主要组成部分:客户端库,主服务器和区域服务器。

8.5.1Client

  1. 主要功能
    • 客户端负责发送请求到数据库,客户端连接的方式有很多种
      • hbase shell
      • 类JDBC
    • client维护着一些cache来加快对hbase的访问,比如regione的位置信息。
  2. 发送请求的类型
    • DDL:数据库定义语言(表的建立,删除,添加删除列族,控制版本)
    • DML:数据库操作语言(增删改)
    • DQL:数据库查询语言(查询–全表扫描–基于主键–基于过滤器)

8.5.2 HMaster

  1. 定义
    • HBase集群的主节点,HMaster也可以实现高可用(active–standby)
      • 通过Zookeeper来维护主副节点的切换
  2. 作用
    • 上下线的监督,创建表的时候为Region server分配region并负责Region server的负载均衡
    • 负责接受客户端对table的结构DDL(创建,删除,修改)操作,DML和DQL由其他节点承担
      • 因为HMaster没有联邦机制,业务承载能力有限,而且数据库的表结构很少会变化,大部分都是CRUD操作
      • 表的元数据信息–>Zookeeper上面
      • 表的数据–>HRegionServer上
    • 负责监督HRegionServer的健康状况
      • 当HRegionServer下线的时候,HMaster会将当前HRegionServer上的Region转移到其他的HRegionServer

8.5.3 HRegionServer

  1. 定义

    • HBase的具体工作节点(RegionServer属于HBase具体数据的管理者),一般一台主机就是一个RegionServer
  2. 作用

    • 一个RegionServer中包含很多HMaster分配给RegionServer的Region,同时RegionServer处理这些Region的IO请求(DML和DQL请求)
    • 当客户端发送DML和DQL操作的时候,HRegionServer负责和客户端建立连接
    • HRegionServer会实时和HMaster保持心跳,汇报当前节点的信息
    • 当接收到Hmaster命令创建表的时候,分配一个Region对应一张表
    • Region server负责切分在运行过程中变得过大的region
  3. 其他:

    • 当意外关闭的时候,当前节点的Region会被其他HRegionServer管理
  4. 图解 RegionServer、Region、store和storefile之间的关系

8.5.4 HRegion

  1. 定义理解
    • HRegion是HBase中分布式存储和负载均衡最小单元(HBase的表数据具体存放的位置)
      • 最小单元就表示不同的HRegion可以分布在不同的 HRegion server上。
    • 一个Region只属于一张表,但是一张表可以有多个Region
    • HBase自动把表水平划分成多个区域(region),每个region会保存一个表里面某段连续的数据
  2. Region的平分
    • 最开始声明表的时候就会为这个表默认创建一个Region,一个Region只属于一张表,随着时间的推移Region会越来越大 ,当达到阈值10G时,然后Region会1分为2(逻辑上平分,尽量保证数据的完整性)
      • 切分后的其中一个Region转移到其他的HRegionServer上管理
  3. 预分区
    • 当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Regionserver 上。
    • 为了防止前期数据的处理都集中在一个HRegionServer,我们可以根据自己的业务进行预分区

8.5.5 Store

  1. 定义理解
    • 一个表中的一个列族对应一个Store
    • 一个Store里面分为1个MenStore和0或多个StoreFile
  2. HRegion、Store和columns family之间的关系
    • HRegion是表获取和分布的基本元素,由一个或者多个Store组成,每个store保存一个columns family。
  3. HFile
    • HFile是Hbase在HDFS中存储数据的格式,它包含多层的索引,这样在Hbase检索数据的时候就不用完全的加载整个文件。
    • StoreFile存储在HDFS上之后就称为HFile

8.5.6 StoreFile

  1. 定义理解
    • StoreFile是文件的硬盘存储,直接存到HDFS上,存到HDFS之后被称为HFile
    • StoreFile是数据存储文件的映射,对应HDFS上的HFile
  2. 表、Region、Store、StoreFile之间的关系
    • 一个table对应多个Region,一个Region对应多个Store,一个Store对应一个MEMStore和多个StoreFile,多个StoreFile内部有序,但是外部无序
    • 集群会设置一些阈值,当达到阈值的时候开始将小文件合并成大文件

8.5.7 MenStore

  1. 定义理解

    • MenStore是基于内存存放数据,每个Store大概分配128M的空间
    • HFile中并没有任何Block,数据首先存在于MemStore中。Flush发生时,创建HFile Writer
    • 数据最开始优先写入到MEMStore,当flush的时候才会被写入到磁盘中(之前在内存中)
    • 默认情况下,一个MemStore的大小为128M,当客户端向数据库插入数据的时候,当内存使用到128M的时候,直接申请128M的内存空间,数据直接写到新内存中,原来已经满的数据写出到HDFS上,称为HFile
  2. MenStore与 Data Block之间的关系

    • 当操作数据的时候,第一个空的Data Block初始化,初始化后的Data Block中为Header部分预留了空间,Header部分用来存放一个Data Block的元数据信息。
    • 位于MemStore中的KeyValues被一个个append到位于内存中的第一个Data Block中
      • 如果配置了Data Block Encoding,则会在Append KeyValue的时候进行同步编码,编码后的数据不再是单纯的KeyValue模式。
      • Data Block Encoding是HBase为了降低KeyValue结构性膨胀而提供的内部编码机制

8.5.8 Hlog

  1. 定义理解

    • HBase的日志机制,WAL(Write After Log)做任何操作之前先写日志,一个HRegionServer只有一个Log文档
    • 日志也会存储到HDFS上,在任何操作之前先记录日志到HDFS,以后MenStore丢失数据或者RegionServer异常都能够通过日志进行恢复一个RegionServer对应的一个Hlog
    • HLog文件就是一个普通的Hadoop Sequence File,SequeceFile的Key是HLogKey对象
  2. 作用

    • 当memStore达到阈值的时候开始写出到文件之后,会在日志中对应的位置标识一个检查点
    • WAL记录所有的Hbase数据改变,如果一个RegionServer在MemStore进行FLush的时候挂掉了,WAL可以保证数据的改变被应用到。如果写WAL失败了,那么修改数据的完整操作就是失败的。
  3. 图解Hlog在整个HBase中的结构

8.5.9 Zookeeper

  1. 定义理解
    • HBase的协调服务
  2. 作用
    • 主备选举与切换
    • 记录当前集群的状态信息,当主备切换的时候,集群的状态可以被新主节点直接读取到
    • 记录当前集群的数据存放信息
    • 存储HBase的元数据信息

8.6 HBase读写流程

8.6.1 公共流程(三层索引)

  1. 对于数据对应的Region位置在哪里的问题的提出
    • HBase中单表的数据量通常可以达到TB级或PB级,但大多数情况下数据读取可以做到毫秒级。HBase是如何做到的呢?要想实现表中数据的快速访问,通用的做法是数据保持有序并尽可能的将数据保存在内存里。HBase也是这样实现的
    • 对于海量级的数据,首先要解决存储的问题。数据存储上,HBase将表切分成小一点的数据单位region,托管到RegionServer上,和以前关系数据库分区表类似。但比关系数据库分区、分库易用。这一点在数据访问上,HBase对用户是透明的。数据表切分成多个Region,用户在访问数据时,如何找到该条数据对应的region呢?

1. HBase 0.96以前

  1. 两个表-Root- .Meta.

    • 系统维护的两个特殊的表 -Root- .Meta. 用来查找各种表的region位置在哪里

    • -Root-和.Meta.也像HBase中其他表一样会切分成多个region

    • .Meta. 表

      • 存储了表对应Region对应的RegionServer RowKey的区间(目录)
      • 但是.Meta. 表也是一张普通的Hbase表,也需要存放到RegionServer中
    • -Root- 表

      • 专门用来记录 .meta.表的存放位置(目录的目录),通过-root-表就可以找到 .meta. 表的region位置
      • 它的机构和meta一模一样,但是它只维护meta表的切分信息
      • 理论上-root-表不会被切分(数据量),一般 -root- 表只需要一个Region即可(目录的目录,内容不会超过一个Region的10G大小),-root- 的Region信息存放在Zookeeper
  2. 用户访问表的流程

    • client–>Zookeeper --> .root. 表–>-meta-表–>RegionServer–>Region

2.HBase 0.96以后

  1. -ROOT-表被移除,直接将.Meta表region位置信息存放在Zookeeper中。Meta表更名为hbase:meta,

  2. 查询流程

    Client—>Zookeeper—>HBase:meta—>用户表Region

本文标签: 14