基础
数据模型
Name Space
命名空间,类似于关系型数据库的DatabBase
概念,每个命名空间下有多个表。HBase
有两个自带的命名空间,分别是hbase
和default
,hbase
中存放的是HBase
内置的表,default
表是用户默认使用的命名空间。Region
类似于关系型数据库的表概念。不同的是,HBase
定义表时只需要声明列族即可,不需要声明具体的列。这意味着, 往HBase
写入数据时,字段可以动态、 按需指定。因此,和关系型数据库相比,HBase
能够轻松应对字段变更的场景。Row
HBase
表中的每行数据都由一个RowKey
和多个Column
(列)组成,数据是按照RowKey
的字典顺序存储的,并且查询数据时只能根据RowKey
进行检索,所以RowKey
的设计十分重要。Column
HBase
中的每个列都由Column Family
(列族)和Column Qualifier
(列限定符) 进行限定,例如info: name
,info: age
。建表时,只需指明列族,而列限定符无需预先定义。Time
Stamp
用于标识数据的不同版本(version
), 每条数据写入时, 如果不指定时间戳, 系统会自动为其加上该字段,其值为写入HBase
的时间。Cell
由{rowkey
,column Family
:column Qualifier
,time Stamp
} 唯一确定的单元。cell
中的数据是没有类型的,全部是字节码形式存贮。
StoreFile 和 HFile
StoreFile 以 HFile的格式保存在HDFS上, HFile的格式:
HFile
文件是不定长的,长度固定的只有其中的两块:Trailer
和 FileInfo
-
Trailer
中有指针指向其他数据块的起始点。 -
FileInfo
中记录了文件的一些Meta
信息,例如:AVG_KEY_LEN
,AVG_VALUE_LEN
,LAST_KEY
,COMPARATOR
,MAX_SEQ_ID_KEY
等。
HFile
分为6个部分:
Data Block
段–保存表中的数据,这部分可以被压缩-
Meta Block
段 (可选的)–保存用户自定义的kv
对,可以被压缩。 -
File Info
段–Hfile
的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。 -
Data Block Index
段–Data Block
的索引。每条索引的key
是被索引的block
的第一条记录的key
。 -
Meta Block Index
段 (可选的)–Meta Block
的索引。 -
Trailer
段–这一段是定长的。保存了每一段的偏移量,读取一个HFile
时,会首先读取Trailer
,Trailer
保存了每个段的起始位置(段的Magic
Number
用来做安全check
),然后,DataBlock
Index
会被读取到内存中,这样,当检索某个key
时,不需要扫描整个HFile
,而只需从内存中找 到key
所在的block
,通过一次磁盘io
将整个block
读取到内存中,再找到需要的key
。DataBlock
Index
采用LRU
机制淘汰。
-
HFile
的 Data
Block
,Meta
Block
通常采用压缩方式存储,压缩之后可以大大减少网络 IO
和磁 盘 IO
,随之而来的开销当然是需要花费 cpu
进行压缩和解压缩。
目标 Hfile
的压缩支持两种方式:Gzip
,LZO
。
Data
Index
和 Meta
Index
块记录了每个 Data
块和 Meta
块的起始点。
Data
Block
是 HBase
I
/O
的基本单元,为了提高效率,HRegionServer
中有基于 LRU
的 Block
Cache
机制。每个 Data
块的大小可以在创建一个 Table
的时候通过参数指定,大号的 Block
有利于顺序 Scan
,小号 Block
利于随机查询。 每个 Data
块除了开头的 Magic
以外就是一个 个 KeyValue
对拼接而成, Magic
内容就是一些随机数字,目的是防止数据损坏。
HFile 里面的每个 KeyValue 对就是一个简单的 byte 数组。但是这个 byte 数组里面包含了很多项,并且有固定的结构。下面是具体结构:
其中Time Stamp
和 Key Type(Put/Delete)
Campaction
-
由于
memstore
每次刷写都会生成一个新的HFile
,且同一个字段的不同版本(timestamp
)和不同类型(Put
/Delete
)有可能会分布在不同的HFile
中,因此查询时需要遍历所有的HFile
。为了减少HFile
的个数,以及清理掉过期和删除的数据,会进行StoreFileCompaction
。-
Compaction
分为两种:Minor Compaction
会将临近的若干个较小的HFile
合并成一个较大的HFile
,但不会清理过期和删除的数据。Major Compaction
会将一个Store
下的所有的HFile
合并成一个大HFile
,并且会清理掉过期和删除的数据。
-
WAL日志
wal(write ahead log)
Table
中的所有行都按照RowKsey
的字典序排列。Table
在行的方向上分割为多个HRegion
。HRegion
按大小分割的(默认 10G
),每个表一开始只有一个HRegion
,随着数据不断插入 表,HRegion
不断增大,当增大到一个阀值的时候,HRegion
就会等分会两个新的HRegion
。 当表中的行不断增多,就会有越来越多的HRegion
。HRegion
是Hbase
中分布式存储和负载均衡的最小单元。最小单元就表示不同的HRegion
可以分布在不同的HRegionserver
上。但一个HRegion
是不会拆分到多个server
上的。HRegion
虽然是负载均衡的最小单元,但并不是物理存储的最小单元。事实上,HRegion
由一个或者多个Store
组成,每个Store
保存一个Column
Family
。每个Strore
又由一个memStore
和 0 至多个StoreFile
组成
-
为什么要一个
RegionServer
对应于一个HLog
。为什么不是一个region
对应于一个log
file
?
引用BigTable
中的一段话:
如果我们每一个“tablet
”(对应于HBase
的region
)都提交一个日志文件,会需要并发写入大量的文件到GFS
,这样,根据每个GFS
server
所依赖的文件系统,写入不同的日志文件会造成大量的磁盘操作。
HBase
依照这样的原则。在日志被回滚和安全删除之前,将会有大量的文件。如果改成一个region
对应于一个文件,将会不好扩展,迟早会引发问题。 -
延迟(异步)同步写入
WAL
WAL
在默认情况下时开启的,当然,我们也可以手动关闭。调用{Mutation
.setDurability
(Durability
.SKIP``WAL
)}方法来关闭,这样做的确可以使得数据操作快一点,但并不建议这样做,一旦服务器宕机,数据就会丢失。
延迟(异步)同步写入WAL
。调用setDurability
(Durability
.ASYNC``WAL
),这样通过设置时间间隔来延迟将操作写入WAL
。
时间间隔:HBase
间隔多久会将操作从内存写入到WAL
,默认值为1s
。 这种方法也可以相对应地提高性能。
架构
概念
-
Client
-
HBase
有两张特殊表:.
META
.:记录了用户所有表拆分出来的的Region
映射信息,.META
.可以有多个Regoin
-
ROOT
-:记录了.META
.表的Region
信息,-ROOT
-只有一个Region
,无论如何不会分裂 -
Client
访问用户数据前需要首先访问ZooKeeper
,找到-ROOT
-表的Region
所在的位置,然 后访问-ROOT
-表,接着访问.META
.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过client
端会做cache
缓存。 -
ZooKeeper
-
ZooKeeper
为HBase
提供Failover
机制,选举Master
,避免单点Master
单点故障问题 -
存储所有
Region
的寻址入口:-ROOT
-表在哪台服务器上。-ROOT
-这张表的位置信息 -
实时监控
RegionServer
的状态,将RegionServer
的上线和下线信息实时通知给Master
-
存储
HBase
的Schema
,包括有哪些Table
,每个Table
有哪些Column
Family
-
-
Master
-
为
RegionServer
分配Region
-
负责
RegionServer
的负载均衡 -
发现失效的
RegionServer
并重新分配其上的Region
-
HDFS
上的垃圾文件(HBase
)回收 -
处理
Schema
更新请求(表的创建,删除,修改,列簇的增加等等)
-
-
RegionServer
-
RegionServer
维护Master
分配给它的Region
,处理对这些Region
的IO
请求 -
RegionServer
负责Split
在运行过程中变得过大的Region
,负责Compact
操作
可以看到,
client
访问HBase
上数据的过程并不需要master
参与(寻址访问zookeeper
和RegioneServer
,数据读写访问RegioneServer
),Master
仅仅维护者Table
和Region
的元数据信息,负载很低。.
META
. 存的是所有的Region
的位置信息,那么RegioneServer
当中Region
在进行分裂之后 的新产生的Region
,是由Master
来决定发到哪个RegioneServer
,这就意味着,只有Master
知道new
Region
的位置信息,所以,由Master
来管理.META
.这个表当中的数据的CRUD
所以结合以上两点表明,在没有
Region
分裂的情况,Master
宕机一段时间是可以忍受的。 -
-
HRegion
table
在行的方向上分隔为多个Region
。Region
是HBase
中分布式存储和负载均衡的最小单元,即不同的region
可以分别在不同的Region
Server
上,但同一个Region
是不会拆分到多个server
上。
Region
按大小分隔,每个表一般是只有一个region
。随着数据不断插入表,region
不断增大,当region
的某个列族达到一个阈值时就会分成两个新的region
。
每个region
由以下信息标识:< 表名,startRowkey
,创建时间>
由目录表(-ROOT
-和.META
.)记录该region
的endRowkey
-
Store
每一个region
由一个或多个store
组成,至少是一个store
,hbase
会把一起访问的数据放在一个store
里面,即为每个ColumnFamily
建一个store
,如果有几个ColumnFamily
,也就有几个Store
。一个Store
由一个memStore
和0或者 多个StoreFile
组成。HBase
以store
的大小来判断是否需要切分region
-
MemStore
memStore
是放在内存里的。保存修改的数据即keyValues
。当memStore
的大小达到一个阀值(默认128MB
)时,memStore
会被flush
到文 件,即生成一个快照。目前hbase
会有一个线程来负责memStore
的flush
操作。 -
StoreFile
memStore
内存中的数据写到文件后就是StoreFile
,StoreFile
底层是以HFile
的格式保存。当storefile
文件的数量增长到一定阈值后,系统会进行合并(minor
、major
compaction
),在合并过程中会进行版本合并和删除工作(majar
),形成更大的storefile
。 -
HFile
HBase
中KeyValue
数据的存储格式,HFile
是Hadoop
的 二进制格式文件,实际上StoreFile
就是对Hfile
做了轻量级包装,即StoreFile
底层就是HFile
。 -
HLog
HLog
(WAL
log
):WAL
意为write
ahead
log
,用来做灾难恢复使用,HLog
记录数据的所有变更,一旦region
server
宕机,就可以从log
中进行恢复。
HLog
文件就是一个普通的Hadoop
Sequence
File
,Sequence
File
的value
是key
时HLogKey
对象,其中记录了写入数据的归属信息,除了table
和region
名字外,还同时包括sequence
number
和timestamp
,timestamp
是写入时间,sequence
number
的起始值为0,或者是最近一次存入文件系统中的sequence
number
。Sequence
File
的value
是HBase
的KeyValue
对象,即对应HFile
中的KeyValue
。
读写原理
写流程
Client
先访问zookeeper
,获取hbase
:meta
表位于哪个Region
Server
。- 访问对应的
Region
Server
,获取hbase
:meta
表,根据读请求的namespace
:table
/rowkey
,查询出目标数据位于哪个Region
Server
中的哪个Region
中。并将该table
的region
信息以及meta
表的位置信息缓存在客户端的meta
cache
,方便下次访问。 - 与目标
Region
Server
进行通讯; - 将数据顺序写入(追加)到
WAL
; - 将数据写入对应的
MemStore
,数据会在MemStore
进行排序; - 向客户端发送
ack
; - 等达到
MemStore
的刷写时机后,将数据刷写到HFile
。
读流程
Client
先访问zookeeper
,获取hbase
:meta
表位于哪个Region
Server
。- 访问对应的
Region
Server
,获取hbase
:meta
表,根据读请求的namespace
:table
/rowkey
,查询出目标数据位于哪个Region
Server
中的哪个Region
中。并将该table
的region
信息以及meta
表的位置信息缓存在客户端的meta
cache
,方便下次访问。 - 与目标
Region
Server
进行通讯; - 分别在
Block
Cache
(读缓存),MemStore
和Store
File
(HFile
)中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time
stamp
)或者不同的类型(Put
/Delete
)。 - 将从文件中查询到的数据块(
Block
,HFile
数据存储单元,默认大小为 64KB
)缓存到Block
Cache
。 - 将合并后的最终结果返回给客户端