01HBase介绍

0 阅读14分钟

HBase介绍

关系型与非关系型数据库

关系型数据库

image.png

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织

优点

  1. 易于维护:都是使用表结构,格式一致
  2. 使用方便:SQL语言通用,可用于复杂查询
  3. 复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询

缺点

  1. 读写性能比较差,尤其是海量数据的高效率读写
  2. 固定的表结构,灵活度稍欠
  3. 高并发读写需求,传统关系型数据库,硬盘IO是一个很大的瓶颈

非关系型数据库

image.png

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或键值对

优点

  1. 格式灵活:存储数据的格式可以是key/value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型
  2. 速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘
  3. 高扩展性
  4. 成本低:nosql数据库部署简单,基本都是开源软件

缺点

  1. 不提供sql支持,学习和使用成本较高
  2. 无事务处理
  3. 数据结构相对复杂,复杂查询方面稍欠

NoSQL的全称是Not Only SQL,泛指非关系型数据库

HBase简介

当需要对大数据进行随机、实时的读写访问时,请使用Apache HBase™。这个项目的目标是在商用硬件集群上托管非常大的表——数十亿行×数百万列。Apache HBase是一个开源的、分布式的、多版本的、非关系型数据库,它模仿了Chang等人提出的谷歌的Bigtable:一个结构化数据的分布式存储系统。正如Bigtable利用了谷歌文件系统提供的分布式数据存储,Apache HBase在Hadoop和HDFS之上提供了类似Bigtable的功能(这是官网介绍)

HBase的全称是Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式NOSQL数据库。利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为其分布式协调服务。主要用来存储非结构化、半结构化和结构化的松散数据(列式存储的 NoSQL 数据库)

HBase数据模型

逻辑上,HBase 的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列。但从底层物理存储结构(Key-Value)来看,HBase 更像一个 Map

HBase的逻辑结构如下

image.png

image.png

HBase的物理结构存储如下

image.png

NameSpace

命名空间,相当于关系型数据库中的 database,每个命名空间下有多个表。Hbase 默认自带的命名空间 hbase 和 default;hbase 中存放的是 HBase 内置的表,default 是用户默认使用的命名空间

Table(Region)

Table通过Region的方式存储数据,一个Table可以包含多个Region。类似关系型数据库的表,不同之处在于 HBase 定义表示只需要声明列族,不需要声明具体的列。列可以动态的按需要指定;HBase 更加适合字段经常变更的场景。开始创建表是一个表对应一个 region,当表增大到一定值时会被拆分为两个 region,然后随着表的增大会继续拆分 region

RowKey

  1. 决定一行数据,每行记录的唯一标识(上面图片中表示的是一行数据)
  2. 按照字典序排序(可以通过对rowkey的设计,使得经常查询的数据排在一起,这样读取时可以顺序读取,可以提高整个查询的效率)
  3. RowKey能存储最大64K字节数据(很大),一般使用时会使用10-100字节的数据,RowKey越短越好

Column Family & Qualifier

  1. HBase表中的每个列都归属于某个列族(Column Family 简称CF),列族是HBase的最小控制单元,列族必须作为表模式(schema)定义的一部分预先给出。如 create 'test', 'course'
  2. 列名以列族作为前缀,每个“列族”都可以有多个列成员(column);如course:math, course:english, 新的列族成员(列)可以随后按需、动态加入
  3. 权限控制、存储以及调优都是在列族层面进行的
  4. HBase把同一列族里面的数据存储在同一目录下,由几个文件保存

Cell

  1. 某行中的某一列被称为 Cell(单元格),由行和列的坐标交叉决定
  2. 单元格是有版本的
  3. 单元格的内容是未解析的字节数组
    • {row key, column( =<family> +<qualifier>), version}唯一确定的单元(qualifier是指列族中列的限定符)
    • cell中的数据是没有类型的,全部是字节数组形式存储

TimeStamp时间戳

  1. 在HBase中每个cell存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异,不同版本的数据按照时间倒序排序,最新的数据版本排在最前面(这保证了每次取到的数据都是最新的,HBase中没有更新操作,只会put最新的数据)
  2. 时间戳的类型是 64位整型
  3. 时间戳可以由HBase(在数据写入时自动)赋值,此时间戳是精确到毫秒的当前系统时间
  4. 时间戳也可以由客户显式赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳

Row

HBase 表中的每行数据被称为 Row,由一个 RowKey 和多个 Column 组成,数据是按照 RowKey 的字典顺序存储的,并且查询时只能根据 RowKey 进行检索,所以 RowKey 的设计很关键

Column

列是由列族(Column Family)和列限定符(Column Qualifier)进行限定,例如:base:name,base:sex。建表示只需定义列族,而列限定符无需预先定义

HBase架构

image.png

角色介绍

Client
  1. 包含访问HBase的接口并维护cache来加快对HBase的访问
  2. 客户端通过查询zookeeper中信息获取HBase集群信息
Zookeeper
  1. 保证任何时候,集群中只有一个活跃master
  2. 存储所有region的寻址入口(zk中存储了元数据表的元数据)
  3. 实时监控region server的上线和下线信息,并实时通知HMaster
  4. 存储HBase的schema和table元数据(只存储元数据表的元数据比较少,还有更多的数据表元数据是存储在hbase中的)
Master(HMaster)
  1. 为region server分配region
  2. 负责region server的负载均衡
  3. 发现失效的region server并重新分配其上的region
  4. 管理用户对table的增删改操作
RegionServer(HRegionServer)
  1. region server维护region,处理对这些region的IO请求
  2. region server负责切分在运行过程中变得过大的region
HLog(WAL Log)
  1. HLog文件就是一个普通的Hadoop Sequence File,Sequence File的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括sequence number和timestamp,timestamp是"写入时间",sequence number的起始值为0,或者是最近一次存入文件系统中sequence number
  2. HLog SequeceFile的Value是HBase的KeyValue对象,即对应HFile中的KeyValue

regionserver组件介绍

region
  1. HBase自动把表水平划分成多个区域(region),每个region会保存一个表里某段连续的数据
  2. 每个表一开始只有一个region,随着数据不断插入表,region不断增大,当增大到一个阈值的时候,region就会等分成两个新的region(裂变)
  3. 当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Regionserver上

一个region对应一个表,一个表可以对应多个region

memstore与storefile
  1. 一个region由多个store组成,一个store对应一个CF(列族)
  2. store包括位于内存中的memstore和位于磁盘的storefile,写操作先写入memstore(因此hbase的写操作很快),当memstore中的数据达到某个阈值,regionserver会启动flashcache进程写入storefile,每次写入形成单独的一个storefile,storefile在hdfs中表现为hfile
  3. storefile是只读的,一旦创建后就不可以再修改,因此Hbase的更新其实是不断追加的操作。当一个store中storefile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作(majar),将对同一个key的修改合并到一起,形成更大的storefile
  4. 当一个region所有storefile的大小和数量超过一定阈值后,会把当前的region分割为两个,并由master分配到相应的regionserver服务器,实现负载均衡
  5. 客户端检索数据,先在memstore找,找不到去blockcache找,找不到再找storefile

注意问题

  1. HRegion是HBase中分布式存储和负载均衡的最小单元。最小单元表示不同的HRegion可以分布在不同的HRegionServer上
  2. HRegion由一个或者多个store组成,每个store保存一个columns family
  3. 每个strore又由一个memStore和0至多个StoreFile组成,StoreFile以HFile格式保存在HDFS上

image.png

image.png

HBase读写流程

读流程

image.png

  1. 客户端从zookeeper中获取meta表所在的regionserver节点信息
  2. 客户端访问meta表所在的regionserver节点,获取到待操作的region所在的regionserver信息
  3. 客户端访问具体的region所在的regionserver,找到对应的region及store
  4. 首先从memstore中读取数据,如果读取到了那么直接将数据返回,如果没有,则去blockcache读取数据
  5. 如果blockcache中读取到数据,则直接返回数据给客户端,如果读取不到,则遍历storefile文件,查找数据
  6. 如果从storefile中读取不到数据,则返回客户端为空,如果读取到数据,那么需要将数据先缓存到blockcache中(方便下一次读取),然后再将数据返回给客户端
  7. blockcache是内存空间,如果缓存的数据比较多,满了之后会采用LRU策略,将比较老的数据进行删除,blockcache和storefile之间还会通过索引建立联系,当hbase中数据更新时,会实时更新索引,并将blockcache中的缓存更新,这样就不会造成缓存不一致

client首先从zookeeper找到meta表region的位置,然后读取meta表中的数据。而meta中又存储了用户表的region信息,根据namespace、表名和rowkey在meta表中找到读取数据对应的region信息。然后找到对应的RegionServer,查找对应的Region,先从内存中查找,找不到再到磁盘中查找

写流程

image.png

  1. 客户端从zookeeper中获取meta表所在的regionserver节点信息
  2. 客户端访问meta表所在的regionserver节点,获取到待操作的region所在的regionserver信息
  3. 客户端访问具体的region所在的regionserver,找到对应的region及store
  4. 开始写数据,写数据的时候会先向hlog(预写日志)中写一份数据(方便memstore中数据丢失后能够根据hlog恢复数据,向hlog中写数据的时候也是优先写入内存,后台会有一个线程定期(默认1s)异步刷写数据到hdfs,如果hlog的数据也写入失败,那么数据就会发生丢失)
  5. hlog写数据完成之后,会先将数据写入到memstore,memstore默认大小是64M,当memstore满了之后会进行统一的溢写操作,将memstore中的数据持久化到hdfs中(溢写之后,之前存储的memstore就会被删掉)
  6. 频繁的溢写会导致产生很多的小文件,因此会进行文件的合并,文件在合并的时候有两种方式,minor和major,minor表示小范围文件的合并,major表示将所有的storefile文件都合并成一个,具体详细的过程,后续会讲解

当memstore达到阈值后把数据刷到一个storefile文件,当多个storefile文件达到一定的大小或数量后,会触发compact合并操作,当compact后,逐渐形成越来越大的storefile。当一个region所有storefile的大小和数量超过一定阈值后,触发split操作,把当前HRegion Split成2个新的HRegion,老的HRegion会下线,新Split出的2个新HRegion会被HMaster分配到相应的HRegionServer上,使得原先1个HRegion的压力得以分流到2个HRegion上

写数据时都是先写内存,速度很快

HBase minor小合并和major大合并

当客户端向HBase中写入数据时,首先写入HLog和Memstore中,在一个Store中,当Memstore中的数据达到某个阈值,数据会写入磁盘形成一个新的数据存储文件(StoreFile),随着Memstore的刷写会生成很多StoreFile,当一个store中的storefile达到一定的阈值后,就会进行一次合并,将对同一个key的修改合并到一起,形成一个大的storefile

由于对表的更新是不断追加的,合并时,需要访问store中全部的storefile和memstore,将它们按rowkey进行合并,由于storefile和memstore都是经过排序的,并且storefile带有内存中索引,合并的过程还是比较快的

因为存储文件不可修改,HBase是无法通过移除某个键/值来简单的删除数据,而是对删除的数据做个删除标记,表明该数据已被删除,检索过程中,删除标记掩盖该数据,客户端读取不到该数据

随着memstore中数据不断刷写到磁盘中,会产生越来越多的storefile小文件,HBase内部通过将多个文件合并成一个较大的文件解决这一小文件问题,以上过程涉及两种合并

minor小合并

minor 合并负责合并Store中的多个storeFile文件,当StoreFile文件数量达到hbase.hstore.compaction.min 值(默认值为2)时,将会合并成一个StoreFile大文件。这种合并主要是将多个小文件重写为数量较少的大文件,减少存储文件数量,因为StoreFile的每个文件都是经过归类的,所以合并速度很快,主要受磁盘IO性能影响

major大合并

将一个region中的一个列簇(对应一个Store)的若干个经过minor合并后的大的StoreFile重写为一个新的StoreFile。而且major合并能扫描所有的键/值对,顺序重写全部数据,重写过程中会略过做了删除标记的数据

HBase目录表meta表

目录表hbase:meta作为HBase表存在,并从hbase shell的list(类似 show tables)命令中过滤掉,但实际上是一个表,就像任何其他表一样

hbase:meta 表(以前称为.META.),保有系统中所有 region 的列表。hbase:meta位置信息存储在 zookeeper 中,hbase:meta 表是所有查询的入口。表结构如下

key:
	region的key,结构为:[table],[region start key,end key],[region id]
values:
	info:regioninfo(当前region序列化的HRegionInfo实例)
	info:server(包含当前region的RegionServer的server:port)
	info:serverstartcode(包含当前region的RegionServer进程的开始时间)

当region正在拆分时,将创建另外两列,称为 info:splitA 和 info:splitB,这些列代表两个子 region, 这些列的值也是序列化的 HRegionInfo 实例。区域分割后,将删除此行

a,,endkey
a,startkey,endkey
a,startkey,

空值用于表示表开始和表结束。具有空开始键的 region 是表中的第一个 region。如果某个 region 同时具有空开始和空结束键,则它是表中唯一的 region