HBase中, 从逻辑上来讲数据大概就长这样:

单从图中的逻辑模型来看, HBase 和 MySQL 的区别就是:

  1. 将不同的列归属与同一个列族下
  2. 支持多版本数据

这看着感觉也没有那么太大的区别呀, 它解决了 MySQL 的那些问题呢? 每一个新事物的出现, 都是为了解决原本存在的问题.

  1. 对写入友好, 支持异步大批量并发写入
  2. 可动态添加列
  3. 按列存储数据, 不存在的列不会落盘, 节省空间. 而 MySQL 中不存在的内容也要用 null 填充
  4. 支持海量数据分布式存储(BigTable 最开始就是 Google 为了解决数据存储问题而提出来的)
  5. 等等

那么他是如何解决这些问题的呢? 他的数据是如何进行存储的呢?

HBase 数据物理结构

在介绍其物理结构之前, 要先简单提一下 LSM 树

LSM树

和 MySQL 所使用的B+树一样, 也是一种磁盘数据的索引结构. B+树是一种对读取友好的存储结构, 但是当大量写入的时候, 比如日志信息, 因为涉及到随机写入, 就显得捉襟见肘了.

LSM树就是针对这种大量写入的场景而提出的. 他的中文名字叫: 日志结构合并树. 文件存储的是对数据的修改操作, 数据会 append 但不会去修改原有的数据. 是顺序写入操作.

但是, 如果不管不顾的将所有的操作都顺序写入了, 那读取数据的时候没有任何根据, 需要扫描所有操作才能读到. LSM 树的做法是, 先在内存中维护一份小的有序的数据(内存不存在随机读写的问题), 当这份数据超过一定大小的时候, 将其整个放入磁盘中.

这样, 磁盘中就存在很多个有序的文件了, 但是会有大量的小文件, 读取数据时要依次查找, 导致读取性能降低. 这时就需要对多个小文件进行多路归并合成一个文件来优化读取的性能.

至此, 基本就是LSM 树的全部思想了.

  1. 在内存中维护一个有序的数据
  2. 将内存中的数据push 到磁盘中
  3. 将磁盘中的多个有序文件进行归并, 合成一个较大的有序文件

HBase存储

HBase中, 数据的存储就使用了 LSM 树进行存储. 其中每一条数据都是一条操作记录. 那么在HBase实现中的部分内容如下.

内存有序结构的实现

通过跳表来维护内存中的有序结构, 当一个跳表装满之后, 将禁止新的写入操作并将其 push 到磁盘中, 同时开一个新的数据结构来接收新到的操作请求.

每条数据的存储内容

存储了一个KV 键值对, 其中的 V 就是我们写入的值, 而这个 key 由以下部分组成:

  • row key
  • 列族
  • 列名
  • 时间戳
  • 操作类型: Put、Delete、DeleteColumn、DeleteFamily 等等

整个列表是 key 的顺序列表. 其排序规则如下:

  1. row key小的排在前面
  2. 同 row key 比较列族
  3. 同列族比较列名
  4. 同列名比较时间戳, 时间戳大的在前面.

按照这个顺序进行读取指定 row key 的某一列数据时, 最先拿到的数据就是最新的版本, 若是 delete 操作, 说明最后执行了删除操作, 即使后面有数据, 最新数据也是空.

磁盘文件的结构

由三部分组成:

  1. 头信息: 存储文件大小, 文件块数量, 索引位置, 索引大小等信息
  2. 索引数据: 用户对文件中所有数据块进行索引, 其中每一个数据块都包含一条索引数据, 索引内容包括
    • 数据块的最后一条数据. 用于对索引进行二分查找, 快速定位到指定的数据块
    • 数据块在文件中的位置
    • 数据块的大小
    • 布隆过滤器. 用户在扫描时快速过滤不存在的数据块
  3. 数据块. 其中存储了每一条 KV 数据.

按照这个结构, 用户在进行指定row_key 读取的时候, 每个文件的操作如下:

  1. 根据头信息内容, 加载索引数据
  2. 通过二分查找, 找到 row_key 在哪一数据块下
  3. 根据布隆过滤器过滤掉不存在的数据块, 加速读取
  4. 根据数据块的位置和大小, 找到指定数据块并二分查找指定数据

HBase 数据列族式存储

先简单回顾一下行式存储和列式存储.

行式存储

行式存储, 将一行数据存储在一起, 一行数据写完了才会写下一行. 例如典型的 MySQL.

行式存储在读取一行数据的时候是比较快的, 但如果读取的是某一列数据, 也需要将整行读取到内存中进行过滤.

列式存储

与行式存储相对应的就是列式存储, 既将一列数据存储在一起, 不同列的数据分别存储.

列式存储对于只读取某一列比较友好, 但相对的, 如果要读取多列数据, 需要读取多次并进行合并.

列族式存储

而 HBase 中选用了一种折中的方案, 列族式存储, 将列族放到一起存储, 不同列族分别存储.

那么也就是说, 如果一个表有多个列族, 每个列族下只有一列, 那么就等同于列式存储

如果一个表只有一个列族, 该列族下有多个列, 那么就等同与行式存储.

HBase 会将一张表同一列族的数据, 分配到同一个 region 上, 这个region 分配在集群中的某一个 regionServer. 所有的 region 存储在表: hbase:meta 表中, 表结构如下:

表不同列含义如下:

  • row_key 由以下字段拼接(逗号)而成

    • 表名
    • 起始 row_key
    • 创建时间戳
    • 上面三个字段的md5
  • info:regioninfo 主要存储以下数据(json)
    • STARTKEY: 起始 row_key
    • ENDKEY: 结束 row_key
    • NAME: region 名
    • ENCODED: 不清楚是什么
  • info:seqnumDuringOpen 表示regionServer 在线时长
  • info:server 落在哪个 regionServer 上
  • info:serverstartcode regionServer 的启动时间
  • 等等

总结

简单了解了HBase的数据落盘格式, 也大概解释 HBase 的很多疑惑, 比如:

  1. 为什么只支持 row key 索引查询

    • 因为整个文件是按照 row key 排序的
  2. 为什么读取效率比 MySQL 低
    • 因为要依次读取文件进行查找
  3. 为什么支持高效率的写入操作
    • 因为全部都是顺序读写操作
  4. 应该如何设置 HBase 的列族
    • 将同一场景读取的放到同一列族下, 不同场景读取的放到不同列族下
  5. 等等

HBase 数据存储结构的更多相关文章

  1. HBase 的存储结构

    HBase 的存储结构 2016-10-17 杜亦舒 HBase 中的表常常是超级大表,这么大的表,在 HBase 中是如何存储的呢?HBase 会对表按行进行切分,划分为多个区域块儿,每个块儿名为  ...

  2. Cassandra 的数据存储结构——本质是SortedMap<RowKey, SortedMap<ColumnKey, ColumnValue>>

    Cassandra 的数据存储结构 Cassandra 的数据模型是基于列族(Column Family)的四维或五维模型.它借鉴了 Amazon 的 Dynamo 和 Google's BigTab ...

  3. Berkeley DB的数据存储结构——哈希表(Hash Table)、B树(BTree)、队列(Queue)、记录号(Recno)

    Berkeley DB的数据存储结构 BDB支持四种数据存储结构及相应算法,官方称为访问方法(Access Method),分别是哈希表(Hash Table).B树(BTree).队列(Queue) ...

  4. kafka 数据存储结构+原理+基本操作命令

    数据存储结构: Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的.每个topic又可以分成几个不同的partition(每个topic有几个partitio ...

  5. HBase介绍(2)---数据存储结构

    在本文中的HBase术语:基于列:column-oriented行:row列组:column families列:column单元:cell 理解HBase(一个开源的Google的BigTable实 ...

  6. HBase数据存储

    HRegionServer  HBase的数据文件都存储在HDFS上,格式主要有两种: - HFile:HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制文件,实际上Sto ...

  7. BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览

    一.引言 时间到了2019年,数据库也发展到了一个新的拐点,有三个明显的趋势: 越来越多的数据库会做云原生(CloudNative),会不断利用新的硬件及云本身的优势打造CloudNative数据库, ...

  8. Hashtable数据存储结构-遍历规则,Hash类型的复杂度为啥都是O(1)-源码分析

    Hashtable 是一个很常见的数据结构类型,前段时间阿里的面试官说只要搞懂了HashTable,hashMap,HashSet,treeMap,treeSet这几个数据结构,阿里的数据结构面试没问 ...

  9. 使用MapReduce读取HBase数据存储到MySQL

    Mapper读取HBase数据 package MapReduce; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hba ...

随机推荐

  1. ST在keil下开发时候文件options配置的一些小技巧

    作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:Conscience_Remains 总述     这是之前ST芯片载keil下开发时候总结的一些代码文件options配置小笔记,虽然不是很复杂 ...

  2. SparkCore2

    二.RDD编程 2.5 RDD中的函数传递 在实际开发中我们往往需要自己定义一些对于RDD的操作,那么此时需要主要的是,初始化工作是在Driver端进行的,而实际运行程序是在Executor端进行的, ...

  3. OsgEarth开发笔记(三):Osg3.6.3+OsgEarth3.1+vs2019x64开发环境搭建(下)

    前言   上一篇编译了proj6.2.0.gdal3.2.1,本篇继续.   OsgEarth编译过程简介   OsgEarth的编译,是基于Osg和OsgEarth结合在一起的,先要编译Osg,然后 ...

  4. Codeforces Round #690 (Div. 3)

    第一次 ak cf 的正式比赛,不正式的是寒假里 div4 的 Testing Round,好啦好啦不要问我为什么没有 ak div4 了,差一题差一题 =.= 不知不觉已经咕了一个月了2333. 比 ...

  5. 2015 Multi-University Training Contest 1(7/12)

    2015 Multi-University Training Contest 1 A.OO's Sequence 计算每个数的贡献 找出第\(i\)个数左边最靠右的因子位置\(lp\)和右边最靠左的因 ...

  6. Codeforces Round #501 (Div. 3) D. Walking Between Houses (思维,构造)

    题意:一共有\(n\)个房子,你需要访问\(k\)次,每次访问的距离是\(|x-y|\),每次都不能停留,问是否能使访问的总距离为\(s\),若能,输出\(YES\)和每次访问的房屋,反正输出\(NO ...

  7. .Net Core 国际化

    创建项目什么的就不说了吧 直接进入正题吧 我这里建的是个webapi 添加资源文件 1.首先我们创建一个Language文件夹,这就是我们在后面Startup类中需要配置的目录名. 2.然后我们在La ...

  8. LeetCode刷题笔记 - 12. 整数转罗马数字

    学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...

  9. Logstash 日志收集(补)

    收集 Tomcat 日志 安装 Tomcat # 安装 jdk [root@web01 ~]# rpm -ivh jdk-8u181-linux-x64.rpm # 下载 [root@web01 ~] ...

  10. 7A - Kalevitch and Chess

    A. Kalevitch and Chess time limit per test 2 seconds memory limit per test 64 megabytes input standa ...