在HBase中, 从逻辑上来说数据大概就长这样:json
单从图中的逻辑模型来看, HBase 和 MySQL 的区别就是:数据结构
这看着感受也没有那么太大的区别呀, 它解决了 MySQL 的那些问题呢? 每个新事物的出现, 都是为了解决本来存在的问题.并发
那么他是如何解决这些问题的呢? 他的数据是如何进行存储的呢?app
在介绍其物理结构以前, 要先简单提一下 LSM 树异步
和 MySQL 所使用的B+树同样, 也是一种磁盘数据的索引结构. B+树是一种对读取友好的存储结构, 可是当大量写入的时候, 好比日志信息, 由于涉及到随机写入, 就显得捉襟见肘了.分布式
而LSM树就是针对这种大量写入的场景而提出的. 他的中文名字叫: 日志结构合并树. 文件存储的是对数据的修改操做, 数据会 append 但不会去修改原有的数据. 是顺序写入操做.性能
可是, 若是无论不顾的将全部的操做都顺序写入了, 那读取数据的时候没有任何根据, 须要扫描全部操做才能读到. LSM 树的作法是, 先在内存中维护一份小的有序的数据(内存不存在随机读写的问题), 当这份数据超过必定大小的时候, 将其整个放入磁盘中.优化
这样, 磁盘中就存在不少个有序的文件了, 可是会有大量的小文件, 读取数据时要依次查找, 致使读取性能下降. 这时就须要对多个小文件进行多路归并合成一个文件来优化读取的性能.日志
至此, 基本就是LSM 树的所有思想了.code
在HBase中, 数据的存储就使用了 LSM 树进行存储. 其中每一条数据都是一条操做记录. 那么在HBase实现中的部份内容以下.
内存有序结构的实现
经过跳表来维护内存中的有序结构, 当一个跳表装满以后, 将禁止新的写入操做并将其 push 到磁盘中, 同时开一个新的数据结构来接收新到的操做请求.
每条数据的存储内容
存储了一个KV 键值对, 其中的 V 就是咱们写入的值, 而这个 key 由如下部分组成:
整个列表是 key 的顺序列表. 其排序规则以下:
按照这个顺序进行读取指定 row key 的某一列数据时, 最早拿到的数据就是最新的版本, 如果 delete 操做, 说明最后执行了删除操做, 即便后面有数据, 最新数据也是空.
磁盘文件的结构
由三部分组成:
按照这个结构, 用户在进行指定row_key 读取的时候, 每一个文件的操做以下:
先简单回顾一下行式存储和列式存储.
行式存储
行式存储, 将一行数据存储在一块儿, 一行数据写完了才会写下一行. 例如典型的 MySQL.
行式存储在读取一行数据的时候是比较快的, 但若是读取的是某一列数据, 也须要将整行读取到内存中进行过滤.
列式存储
与行式存储相对应的就是列式存储, 既将一列数据存储在一块儿, 不一样列的数据分别存储.
列式存储对于只读取某一列比较友好, 但相对的, 若是要读取多列数据, 须要读取屡次并进行合并.
列族式存储
而 HBase 中选用了一种折中的方案, 列族式存储, 将列族放到一块儿存储, 不一样列族分别存储.
那么也就是说, 若是一个表有多个列族, 每一个列族下只有一列, 那么就等同于列式存储
若是一个表只有一个列族, 该列族下有多个列, 那么就等同与行式存储.
HBase 会将一张表同一列族的数据, 分配到同一个 region 上, 这个region 分配在集群中的某一个 regionServer. 全部的 region 存储在表: hbase:meta 表中, 表结构以下:
表不一样列含义以下:
简单了解了HBase的数据落盘格式, 也大概解释 HBase 的不少疑惑, 好比: