概述
hbase是一种基于HDFS存储之上的NoSQL的KV分布式存储,与hadoop一样,Hbase目标主要依靠横向扩展,通过不断增加廉价的商用服务器,来增加计算和存储能力。
hbase有自己支持的很多特性,比如:
1. 强一致读写:
hbase支持的一致性是强一致的,不是最终一致的;
2. 自动分片
HBase的表通过region来分布式存储在集群中,会随着数据的增长自动拆分并重新分区。
3. 故障转移
RegionServer能够自动故障转移,提高可用性。
4.集成Hadoop/HDFS
hbase天然支持HDFS文件系统。
5.支持缓存
hbase支持缓存来提高数据查询效率。
同时hbase也提供了java client api和thrift api来操作数据。
那么,一般我们选型时候什么情况下会使用hbase呢?
1. 大量的数据,如果你的数据行数有上亿条甚至10亿条更多,则非常适合,如果只有几百万条,那么关系型数据库可能更合适;
2. 合适的场景, hbase是KV的存储,因为使用hbase意味着要放弃关系型数据库的很多高级特性(多类型列,二级索引,高级SQL等),因此我们的场景要合适;
3. 足够的机器,hbase依赖于HDFS,而HDFS至少需要5个DataNode节点加上一个NameNode节点才表现的很好;
基本架构
下面我们看看hbase是如何支持上述一些特性的,HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由一下类型节点组成:HMaster节点、HRegionServer节点、ZooKeeper集群,而在底层,它将数据存储于HDFS中,总体结构如下:
Hmaster
hbase的Master/Slave架构中的Master就是HMaster,它负责监集群中所有的RegionServer节点,并且负责metadata的变更。
hbase的内部结构图如下所示:
外部接口
外部接口表示和外部世界的诸如Hmaster web site, client, Region Servers 和别的管理工具如 JConsole的接口,这里不多说。
executor service
executor service是hmaster的核心部分,用来控制RegionServer相关工作,通过一个事件队列来实现,用于处理不同的事件,主要事件机器处理如下:
当master检测到一个region成功开启(通过zookeeper),会提交一个RS_ZK_REGION_OPENED类型的事件,会通过事件处理器OpenRegionHandler()来处理。其他处理的事件包括关闭region,region拆分和客户端增删改查操作的请求事件。
RegionServer
regionServer是hbase数据的主要处理部分,主要提供两种类型的操作:
1) 数据的增删改查;
2)region的管理,诸如拆分合并;
regionServer读写数据
HBase上Regionserver的内存分为两个部分,一部分作为Memstore,主要用来写;另外一部分作为BlockCache,主要用于读。
写请求会先写入Memstore,Regionserver会给每个region提供一个Memstore,当Memstore满64MB以后,会启动 flush刷新到磁盘。
读请求先到Memstore中查数据,查不到就到BlockCache中查,再查不到就会到磁盘上读,并把读的结果放入BlockCache。
regionServer功能
regionSever包含一系列后台线程来执行各自的功能:
- CompactSplitThread
检查拆分,处理minor compactions。 - MajorCompactionChecker
检查major compactions。 - MemStoreFlusher
定期将MemStore中数据刷入StoreFiles(HFiles)。 - LogRoller
定期检查RegionServer的WAL日志。 - Coprocessors
压缩,参考这里。 - Block Cache
hbase提供两种类型BlockCache,默认的on-heap LruBlockCache 和BucketCache。
regionServer如何拆分
hbase region中有一个内存存储系统叫memstore,当它满了会把数据写入磁盘作为storeFiles,随着storeFiles累积,RegionServer会将它压缩成更新更大的文件,当文件的两足够大的时候,就会根据相应策略决定是否拆分。
下面,简单描述一下拆分的步骤,首先见图:
图中是RegionServer A中一个Region的拆分过程,1-10描述了拆分步骤,假设RegionServer B中保持了.META表。分步骤描述如下:
1. RegionServer准备拆分
拆分过程中表的schema不允许改变(先获取共享锁),并在zookeeper的/hbase/region-in-transition/region-name中创建一个节点,状态置为SPLITTING。
2. Master感知
master感知到RegionServer准备拆分。
3. HDFS准备
RegionServer在父Region的HDFS文件夹中创建一个文件夹,叫.splits。
4. 关闭父Region
RegionServer关闭父Region并标记为offline,注意此时客户端请求会抛出异常NotServingRegionException。
5. 拆分storeFiles
RegionServer在之前的.splits目录下创建两个儿女region目录daughter A 和daughter B,然后开始拆分storeFiles,通过两个创建指向原来storeFiles引用的方式。
6. HDFS创建儿女region目录
RegionServer创建两个儿女region目录,并将上面引用文件移动到其中。
7. 更改元信息
RegionServer更改.META表中父region为offline,并添加儿女region的相关信息,但此时对客户端还不可见。
8. 打开儿女region
RegionServer并行打开两个拆分的regionA和B。
9. 更新元信息
RegionServer增加拆分后的region信息到.META表中,此时客户端可以看到新的拆分后的region。
10. 拆分结束
RegionServer将zookeeper中/hbase/region-in-transition/region-name节点更新为SPLIT完成拆分。
Catalog表
hbase中存在一张特殊的表,表名叫hbase:meta,(在0.96版本之前是-ROOT-和.META表),该表存储了系统中所有region的列表,该表的location保存在zookeeper中。
hbase:meta表的结构
key:
[table],[region start key],[region id]形式
Values:
- info:regioninfo (每个region的 HRegionInfo实例信息)
- info:server (包含该region的RegionServer的server:port信息)
- info:serverstartcode (包含该region的RegionServer的启动时间)
【参考资料】http://blog.zahoor.in/2012/08/hbase-hmaster-architecture/