HBase
存储原理、读写原理
HBase
存储原理(架构)
HBase
依赖于Zookeeper
和Hadoop
的,所以在启动HBase
前需要启动Zookeeper
和Hadoop
。
HMaster
用于管理整个HBase
集群,即管理每个HRegionServer
,它掌握着整个集群的元数据信息,同时会将相应的数据存储到Zookeeper
(元数据信息、高可用信息等)。
HMaster
的职责:1)
管理用户对Table
的增、删、改、查操作;2)
记录region
在哪台Hregion server
上;3)
在Region Split
后,负责新Region
的分配;4)
新机器加入时,管理HRegion Server
的负载均衡,调整Region
分布;5)
在HRegion Server
宕机后,负责失效HRegion Server
上的Regions
迁移。
HRegionServer
是每台机器上的一个Java
进程(一台机器只有一个HRegionServer
进程),用来处理客户端的读写请求(和Hadoop
的DataNode
类似),并维护着元数据信息。
HRegionServer
的职责:1)
HRegion Server
主要负责响应用户I/O
请求,向HDFS
文件系统中读写数据,是HBASE
中最核心的模块。2)
HRegion Server
管理了很多table
的分区,也就是region
。
每个HRegionServer
有一个HLog
(有且仅有一个)。HLog
是操作日志,用来做灾难恢复的,当客户端发起一个写请求时,会先往HLog
中写再往Memory Store
中写。假设没有HLog
,我们进行一个写请求,会首先写到Memory Store
上,等到Memory Store
到达一定容量后,才会flush
到StoreFile
中。但是如果在这之前主机断电了呢?那这部分操作的数据全丢失了。这显然不是我们想到的结果,于是就有了HLog
。
每个HRegionServer
里面有多个HRegion
,一个HRegion
对应于HBase
的一张表(也可能是表的一部分,因为表太大了会切分,表和HRegion
的对应关系是一对多),当这张表到一定大小的时候会进行切分,切分成两个HRegion
,切分出来的新的HRegion
会保存到另一台机器上。每个HRegionServer
里面有多个HRegion
,可以理解为有多张表。
每个HRegion
里面有多个Store
(一张表中有多个列族),一个Store
对应于HBase
一张表的一个列族,。按照这个原理,我们在设计列族的时候,可以把经常查询的列放在同一个列族,这样可以提高效率,因为同一个列族在同一个文件里面(不考虑切分)。
每个Store
有一个内存级别的存储Memory Store
(有且仅有一个)。当Memory Store
达到一定大小或一定时间后会进行数据刷写(flush
),写到磁盘中(即HFile
)。
每个Store
有多个磁盘级别的存储StoreFile
,Memory Store
每刷写一次就形成一个StoreFile
,HFile
是StoreFile
在HDFS
上的存储格式。
HBase
读原理
在上图中,我们模拟一下客户端读取数据过程,假设Zookeeper
存放的meta
表在RS1
机器上,meta
表存放的内容如下,Student
表行键范围在1~100
的存放在RS4
上,在101~200
的存放在RS3
上,等等。
客户端现在要读取Student
表的第100
行,具体步骤如下:
1.
客户端向Zookeeper
发起请求,请求元数据所在RegionServer
,Zookeeper
集群存放的是HBase
的meta
表所在位置。
2.
Zookeeper
返回给客户端元数据所在RegionServer
(即RS1
)。
3.
客户端收到应答后去请求RS1
,请求查询Student
表的rowkey=100
数据所在位置。
4.
在RS1
上查询meta
表可知该数据在RS4
机器上,即返回给客户端rowkey
所在位置(RS4
)。
5.
客户端收到应答后去请求RS4
读数据。
6.
RS4
查询数据返回给客户端。查询时先去内存(MemStore
)查找,因为内存是最新的数据,如果找到了就返回结果,如果没找到则去缓存(cache
)找,如果找到了就返回结果,如果还没找到就去磁盘(StoreFile
)找,如果在磁盘找到了,则先将结果写入缓存(cache
),再返回给客户端,写入缓存是为了下次查询提高效率。
可以发现,在整个读过程中HMaster
并没有参与,即读流程与HMaster
无关,所以如果HMaster
挂了,也是可以读数据的。
HBase
写原理
HBase
的写是比读快的,为什么呢,看下面的写过程,同样假设Zookeeper
存放的meta
表在RS1
机器上,meta
表存放的内容如下,Student
表行键范围在1~100
的存放在RS4
上,在101~200
的存放在RS3
上,等等。
客户端现在要插入数据给Student
表,其中rowkey=100
,具体步骤如下:
1.
客户端向Zookeeper
发起请求,请求元数据所在RegionServer
,Zookeeper
集群存放的是HBase
的meta
表所在位置。
2.
Zookeeper
返回给客户端元数据所在RegionServer
(即RS1
)。
3.
客户端收到应答后去请求RS1
,请求查询Student
表的rowkey=100
数据所在位置。
4.
在RS1
上查询meta
表可知该数据在RS2
机器上,即返回给客户端rowkey
所在位置(RS2
)。
5.
客户端收到应答后去请求RS4
写入数据。
6.
RS2
收到请求,先将数据写入HLog
,再将数据写入MemStore
,写入MemStore
后就返回给客户端写入成功信息,此时,客户端的写流程完成了。
因为写入内存就结束了写流程,不用访问磁盘,所以总体比读流程是快一点的。
同样,在整个写流程中HMaster
也没有参与,所以如果HMaster
挂了,也是可以进行写数据的。但是,如果时间长了,表的大小一直变大,而HMaster却挂了,即不会触发Region
切分,这样就会导致数据倾斜,系统就变得不安全了。
以进行写数据的。但是,如果时间长了,表的大小一直变大,而HMaster却挂了,即不会触发Region
切分,这样就会导致数据倾斜,系统就变得不安全了。**