HBase 基本概念和使用

HBase简介

HBase是一个分布式的、面向列的开源数据库,它是一个适合于非结构化数据存储的数据库。

HBase是基于列的而不是基于行的模式。

面向列:面向列(族)的存储和权限控制,列(族)独立检索。

稀疏:对于为空(null)的列,并不占用存储空间,因此,表的设计非常的稀疏。


HBase的角色

HMaster
  1. 监控RegionServer
  2. 处理RegionServer故障转移
  3. 处理元数据的变更
  4. 处理region的分配或移除
  5. 在空闲时间进行数据的负载均衡
  6. 通过zookeeper发布自己的位置给客户端
HRegionServer
  1. 负责存储HBase的实际数据
  2. 处理分配给它的Region
  3. 刷新缓存到HDFS
  4. 维护HLog
  5. 执行压缩
  6. 负责处理Region分片
Write-Ahead Logs
  • HBase的修改记录,当对HBase读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。
  • 但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile的文件中,然后再写入内存中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
HFile

这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。

Store

HFile存储在Store中,一个Store对应HBase表中的一个列族。

MemStore

内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在WAL中之后,RegionServer会在内存中存储键值对。

Region

HBase表的分片,HBase表会根据rowkey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region。

HBase的架构

一个RegionServer可以包含多个HRegion,每个RegionServer维护一个HLog,和多个HFiles以及其对应的MemStore。RegionServer运行于DataNode上,数量可以与DatNode数量一致,请参考如下架构图:

HBase的架构

HBase数据模型

确定一个单元格(cell)的位置,需要如下四个:

rowkey + column family + column + timestamp(version版本),数据有版本的概念,即一个单元格可能有多个值,但是只有最新的一个对外显示。

  • HBase中有两张特殊的Table,-ROOT-和.META.
  • .META.:记录了用户表的Region信息,.META.可以有多个region
  • -ROOT-:记录了.META.表的Region信息,-ROOT-只有一个region
  • Zookeeper中记录了-ROOT-表的location
  • Client访问用户数据之前需要首先访问zookeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过client端会做cache缓存(在0.96版本后,Hbase移除了-ROOT-表)。

访问数据流程

RowKey

行键,Table的主键,Table中的记录默认按照rowkey升序排序。

Timestamp

时间戳,每次数据操作对应的时间戳,可以看作是数据的version number。

Column Family

列族,Table在水平方向有一个或者多个Column Family组成,一个Column Family中可以由多个Column组成,即Column Family支持动态扩展,无需预先定义Column的数量以及类型,所有Column均以二进制格式存储,用户需要自行进行类型转换。

Table&Region

当Table随着记录数不断增加而变大后,会逐渐分裂成多份splits,成为regions,一个region由[startkey,endkey)表示,不同的region会被Master分配给相应的RegionServer进行管理。

HMaster

HMaster没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行,HMaster在功能上主要负责Table和Region的管理工作:

  1. 管理用户对Table的增、删、改、查操作
  2. 管理HRegionServer的负载均衡,调整Region分布
  3. 在Region Split后,负责新Region的分配
  4. 在HRegionServer停机后,负责失效HRegionServer上的Regions迁移
HRegionServer

HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,HRegion中由多个HStore组成。

每个HStore对应了Table中的一个Column Family的存储,可以看出每个Column Family其实就是一个集中的存储单元,因此最好将具备共同IO特性的column放在一个Column Family中,这样最高效。

MemStore&StoreFiles

HStore存储是HBase存储的核心了,其中由两部分组成,一部分是MemStore,一部分是StoreFiles。

MemStore是Sorted Memory Buffer,用户写入的数据首先会放入MemStore,当MemStore满了以后会Flush成一个StoreFile(底层实现是HFile),当StoreFile文件数量增长到一定阈值,会触发Compact合并操作,将多个StoreFiles合并成一个StoreFile,合并过程中会进行版本合并和数据删除,因此可以看出HBase其实只有增加数据,所有的更新和删除操作都是在后续的compact过程中进行的,这使得用户的写操作只要进入内存中就可以立即返回,保证了HBase I/O的高性能。

当StoreFiles Compact后,会逐步形成越来越大的StoreFile,当单个StoreFile大小超过一定阈值后,会触发Split操作,同时把当前Region Split成2个Region,父Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。

HLog

每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中,HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。

当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。

文件类型

HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括上述提出的两种文件类型:

  1. HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile。
  2. HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File。

Zookeeper中hbase的节点的存储信息:

  • rs:regionserver节点信息
  • table-lock:hbase的除meta以外的所有表
  • Table:hbase的所有的表

HBase的使用

HBase服务的启动
  • 启动方式1:
    bin/hbase-daemon.sh start master
    bin/hbase-daemon.sh start regionserver
    提示:如果集群之间的节点时间不同步,会导致regionserver无法启动,抛出ClockOutOfSyncException异常。
  • 启动方式2:
    bin/start-hbase.sh
    对应的停止服务:
    bin/stop-hbase.sh
查看HBase页面

启动成功后,可以通过“host:port”的方式来访问HBase管理页面,例如:
http://hadoop001:16010

基本操作
  • 进入HBase客户端命令行
    bin/hbase shell
  • 查看帮助命令
    hbase(main)> help
  • 查看当前数据库中有哪些表
    hbase(main)> list
  • 查看当前数据库中有哪些命名空间
    hbase(main)> list_namespace
表的操作
  • 创建表
    hbase(main)> create ‘student’,’info’
    hbase(main)> create ‘iparkmerchant_order’,’smzf’
    hbase(main)> create ‘staff’,’info’

  • 插入数据到表
    hbase(main) > put ‘student’,’1001’,’info:name’,’Thomas’
    hbase(main) > put ‘student’,’1001’,’info:sex’,’male’
    hbase(main) > put ‘student’,’1001’,’info:age’,’18’
    hbase(main) > put ‘student’,’1002’,’info:name’,’Janna’
    hbase(main) > put ‘student’,’1002’,’info:sex’,’female’
    hbase(main) > put ‘student’,’1002’,’info:age’,’20’
    数据插入后的数据模型:
    student表的数据模型

  • 扫描查看表数据
    hbase(main) > scan ‘student’
    hbase(main) > scan ‘student’,{STARTROW => ‘1001’, STOPROW => ‘1001’}
    hbase(main) > scan ‘student’,{STARTROW => ‘1001’} 从哪一个rowkey开始扫描

  • 查看表结构
    hbase(main):> desc ‘student’

  • 更新指定字段的数据
    hbase(main) > put ‘student’,’1001’,’info:name’,’Nick’
    hbase(main) > put ‘student’,’1001’,’info:age’,’100’
    hbase(main) > put ‘student’,’1001’,’info:isNull’,’’(仅测试空值问题)

  • 查看指定行或指定列族:列的数据
    hbase(main) > get ‘student’,’1001’
    hbase(main) > get ‘student’,’1001’,’info:name’

  • 删除数据
    删除某rowkey的全部数据:
    hbase(main) > deleteall ‘student’,’1001’

  • 清空表数据
    hbase(main) > truncate ‘student’
    提示:清空表的操作顺序为先disable,然后再truncate。

  • 删除表
    首先需要先让该表为disable状态:
    hbase(main) > disable ‘student’
    检查这个表是否被禁用:
    hbase(main) > is_enabled ‘hbase_book’
    hbase(main) > is_disabled ‘hbase_book’
    然后才能drop这个表:
    hbase(main) > drop ‘student’
    提示:如果直接drop表,会报错:Drop the named table. Table must first be disabled
    ERROR: Table student is enabled. Disable it first.
    恢复被禁用的表:
    enable ‘student’

  • 统计表数据行数
    hbase(main) > count ‘student’

  • 变更表信息
    将info列族中的数据存放3个版本:
    hbase(main) > alter ‘student’,{NAME=>’info’,VERSIONS=>3}
    查看student的最新版本的数据:
    hbase(main) > get ‘student’,’1001’
    查看HBase中的多版本:
    hbase(main) > get ‘student’,’1001’,{COLUMN=>’info:name’,VERSIONS=>10}

常用shell操作
  • status:显示服务器状态
    hbase> status ‘hadoop001’

  • exists:检查表是否存在,适用于表量特别多的情况
    hbase> exists ‘hbase_book’

  • is_enabled/is_disabled:检查表是否启用或禁用
    hbase> is_enabled ‘hbase_book’
    hbase> is_disabled ‘hbase_book’

  • alter:该命令可以改变表和列族的模式
    为当前表增加列族:
    hbase> alter ‘hbase_book’, NAME => ‘CF2’, VERSIONS => 2
    为当前表删除列族:
    hbase> alter ‘hbase_book’, ‘delete’ => ‘CF2’

  • drop:删除一张表
    hbase> disable ‘hbase_book’
    hbase> drop ‘hbase_book’

  • delete:删除一行中一个单元格的值
    hbase> delete ‘hbase_book’, ‘rowKey’, ‘CF:C’

  • truncate:清空表数据,即禁用表 => 删除表 => 创建表
    hbase> truncate ‘hbase_book’

  • create:创建多个列族
    hbase> create ‘t1’, {NAME => ‘f1’}, {NAME => ‘f2’}, {NAME => ‘f3’}