理解HBase(一个开源的Google的BigTable实际应用)最大的困难是HBase的数据结构概念到底是什么?首先HBase不一样于通常的关系数据库,它是一个适合于非结构化数据存储的数据库.另外一个不一样的是HBase基于列的而不是基于行的模式.html
Google's BigTable论文 清楚地解释了什么是BigTable:
Bigtable是一个疏松的分布式的持久的多维排序的map,这个map被行键,列键,和时间戳索引.每个值都是连续的byte数组.(A Bigtable is a sparse, distributed, persistent multidimensional sorted map. The map is indexed by a row key, column key, and a timestamp; each value in the map is an uninterpreted array of bytes.)mysql
Hadoop wiki的HBase架构 页面提到:
HBase使用和Bigtable很是相同的数据模型.用户存储数据行在一个表里.一个数据行拥有一个可选择的键和任意数量的列.表是疏松的存储的,所以 用户能够给行定义各类不一样的列.(HBase uses a data model very similar to that of Bigtable. Users store data rows in labelled tables. A data row has a sortable key and an arbitrary number of columns. The table is stored sparsely, so that rows in the same table can have crazily-varying columns, if the user likes.)算法
1、架构思路sql
Hbase是基于Hadoop的项目,因此通常状况下咱们使用的直接就是HDFS文件系统,这里咱们不深谈HDFS如何构造其分布式的文件系统,只须要知 道虽然Hbase中有多个RegionServer的概念,并不意味着数据是持久化在RegionServer上的,事实上,RegionServer是 调度者,管理Regions,可是数据是持久化在HDFS上的。明确这一点,在后面的讨论中,咱们直接把文件系统抽象为HDFS,再也不深究。数据库
Hbase是一个分布式的数据库,使用Zookeeper来管理集群。在架构层面上分为Master(Zookeeper中的leader)和多个RegionServer,基本架构如图:apache
在Hbase的概念中,RegionServer对应于集群中的一个节点,而一个RegionServer负责管理多个Region。一个Region代 表一张表的一部分数据,因此在Hbase中的一张表可能会须要不少个Region来存储其数据,可是每一个Region中的数据并非杂乱无章 的,Hbase在管理Region的时候会给每一个Region定义一个Rowkey的范围,落在特定范围内的数据将交给特定的Region,从而将负载分 摊到多个节点上,充分利用分布式的优势。另外,Hbase会自动的调节Region处在的位置,若是一个RegionServer变得Hot(大量的请求 落在这个Server管理的Region上),Hbase就会把Region移动到相对空闲的节点,依次保证集群环境被充分利用。数组
2、存储模型网络
有了架构层面的保证,接下来的事情就只是关注于数据的具体存储了。这里就是每一个Region所承担的工做了。咱们知道一个Region表明的是一张 Hbase表中特定Rowkey范围内的数据,而Hbase是面向列存储的数据库,因此在一个Region中,有多个文件来存储这些列。Hbase中数据 列是由列簇来组织的,因此每个列簇都会有对应的一个数据结构,Hbase将列簇的存储数据结构抽象为Store,一个Store表明一个列簇。数据结构
因此在这里也能够看出为何在咱们查询的时候要尽可能减小不须要的列,而常常一块儿查询的列要组织到一个列簇里:由于要须要查询的列簇越多,意味着要扫描越多的Store文件,这就须要越多的时间。架构
咱们来深刻Store中存储数据的方式。Hbase的实现是用了一种LSM 树的结构!
LSM树是由B+树改进而来,因此咱们首先来简单的看看B+树。
这是一颗简单的B+树,含义不言而喻,这里很少分析,可是这种数据结构并不适合Hbase中的应用场景。这样的数据结构在内存中效率是很高的,可是 Hbase中数据是存储在文件中的,若是按照这样的结构来存储,意味着咱们每一次插入数据都要由一级索引找到文件再在文件中间做操做来保证数据的有序性, 这无疑是效率低下的。因此Hbase采用的是LSM树的结构,这种结构的关键是,每一次的插入操做都会先进入MemStore(内存缓冲区),当 MemStore达到上限的时候,Hbase会将内存中的数据输出为有序的StoreFile文件数据(根据Rowkey、版本、列名排序,这里已经和列 簇无关了由于Store里都属于同一个列簇)。这样会在Store中造成不少个小的StoreFile,当这些小的File数量达到一个阀值的时 候,Hbase会用一个线程来把这些小File合并成一个大的File。这样,Hbase就把效率低下的文件中的插入、移动操做转变成了单纯的文件输出、 合并操做。
由上可知,在Hbase底层的Store数据结构中,每一个StoreFile内的数据是有序的,可是StoreFile之间不必定是有序的,Store只 须要管理StoreFile的索引就能够了。这里也能够看出为何指定版本和Rowkey能够增强查询的效率,由于指定版本和Rowkey的查询能够利用 StoreFile的索引跳过一些确定不包含目标数据的数据。
HBase | Cassandra | |
---|---|---|
语言 | Java | Java |
出发点 | BigTable | BigTable and Dynamo |
License | Apache | Apache |
Protocol | HTTP/REST (also Thrift) | Custom, binary (Thrift) |
数据分布 | 表划分为多个region存在不一样region server上 | 改进的一致性哈希(虚拟节点) |
存储目标 | 大文件 | 小文件 |
一致性 | 强一致性 | 最终一致性,Quorum NRW策略 |
架构 | master/slave | p2p |
高可用性 | NameNode是HDFS的单点故障点 | P2P和去中心化设计,不会出现单点故障 |
伸缩性 | Region Server扩容,经过将自身发布到Master,Master均匀分布Region | 扩容需在Hash Ring上多个节点间调整数据分布 |
读写性能 | 数据读写定位可能要经过最多6次的网络RPC,性能较低。 | 数据读写定位很是快 |
数据冲突处理 | 乐观并发控制(optimistic concurrency control) | 向量时钟 |
临时故障处理 | Region Server宕机,重作HLog | 数据回传机制:某节点宕机,hash到该节点的新数据自动路由到下一节点作 hinted handoff,源节点恢复后,推送回源节点。 |
永久故障恢复 | Region Server恢复,master从新给其分配region | Merkle 哈希树,经过Gossip协议同步Merkle Tree,维护集群节点间的数据一致性 |
成员通讯及错误检测 | Zookeeper | 基于Gossip |
CAP | 1,强一致性,0数据丢失。2,可用性低。3,扩容方便。 | 1,弱一致性,数据可能丢失。2,可用性高。3,扩容方便。 |