MemStore 中累积了足够多的的数据后 , 整个有序数据集就会被写入一个新的 HFile 文件到 HDFS 上 。HBase 为每个 Column Family 都创建一个 HFile , 里面存储了具体的 Cell , 也即 KeyValue 数据 。随着时间推移 , HFile 会不断产生 , 因为 KeyValue 会不断地从 MemStore 中被刷写到硬盘上 。
注意这也是为什么 HBase 要限制 Column Family 数量的一个原因 。每个 Column Family 都有一个 MemStore;如果一个 MemStore 满了 , 所有的 MemStore 都会被刷写到硬盘 。同时它也会记录最后写入的数据的最大序列号(sequence number) , 这样系统就能知道目前为止哪些数据已经被持久化了 。
最大序列号是一个 meta 信息 , 被存储在每个 HFile 中 , 来表示持久化进行到哪条数据了 , 应该从哪里继续 。当 region 启动时 , 这些序列号会被读取 , 取其中最大的一个 , 作为基础序列号 , 后面的新的数据更新就会在该值的基础上递增产生新的序列号 。
文章插图
点评:这里有个序列号的概念 , 每次 HBase 数据更新都会绑定一个新的自增序列号 。而每个 HFile 则会存储它所保存的数据的最大序列号 , 这个元信息非常重要 , 它相当于一个 commit point , 告诉我们在这个序列号之前的数据已经被持久化到硬盘了 。它不仅在 region 启动时会被用到 , 在故障恢复时 , 也能告诉我们应该从 WAL 的什么位置开始回放数据的历史更新记录 。HBase HFile
数据存储在 HFile 中 , 以 Key/Value 形式 。当 MemStore 累积了足够多的数据后 , 整个有序数据集就会被写入一个新的 HFile 文件到 HDFS 上 。整个过程是一个顺序写的操作 , 速度非常快 , 因为它不需要移动磁盘头 。(注意 HDFS 不支持随机修改文件操作 , 但支持 Append 操作 。)
文章插图
HBase HFile 文件结构
HFile 使用多层索引来查询数据而不必读取整个文件 , 这种多层索引类似于一个 B+ tree:
- KeyValues 有序存储 。
- rowkey 指向 index , 而 index 则指向了具体的 data block , 以 64 KB 为单位 。
- 每个 block 都有它的叶索引 。
- 每个 block 的最后一个 key 都被存储在中间层索引 。
- 索引根节点指向中间层索引 。
文章插图
HFile 索引
刚才讨论的索引 , 在 HFile 被打开时会被载入内存 , 这样数据查询只要一次硬盘查询 。
文章插图
HBase Read 合并
我们已经发现 , 每行(row)的 KeyValue cells 可能位于不同的地方 , 这些 cell 可能被写入了 HFile , 可能是最近刚更新的 , 还在 MemStore 中 , 也可能最近刚读过 , 缓存在 Block Cache 中 。所以 , 当你读一行 row 时 , 系统怎么将对应的 cells 返回呢?一次 read 操作会将 Block Cache , MemStore 和 HFile 中的 cell 进行合并:
- 首先 scanner 从 Block Cache 读取 cells 。最近读取的 KeyValue 都被缓存在这里 , 这是 一个 LRU 缓存 。
- 然后 scanner 读取 MemStore , 即写缓存 , 包含了最近更新的数据 。
- 如果 scanner 没有在 BlockCache 和 MemStore 都没找到对应的 cells , 则 HBase 会使用 Block Cache 中的索引和布隆过滤器来加载对应的 HFile 到内存 , 查找到请求的 row cells 。
文章插图
之前讨论过 , 每个 MemStore 可能会有多个 HFile , 所以一次 read 请求可能需要多读个文件 , 这可能会影响性能 , 这被称为读放大(read amplification) 。
推荐阅读
- 中国最大的黄鳝38斤 世界上最大的黄鳝有多重
- 一个进程开启多少线程最好
- 最实用的家庭储藏茶叶的方法
- 铁观音的最佳储存方法
- 一小时搭建微信聊天机器人
- 古希腊旧喜剧古典时期的喜剧最重要的作家是谁 古希腊三大喜剧家及其代表作
- 儿童疱疹性咽喉炎
- 梦见高考迟到但最终进了考场 梦见高考迟到是什么意思
- 去惠州罗浮山哪个寺庙最好 梅州灵光寺风景区
- 大红袍的最佳储存方法