快速上手NoSQL数据库HBase-2
3 深入HBase架构原理
Region概念解释
1 | Region可以翻译为区域,在HBase里面,一个表中的数据,会按照行被横向划分为多个Region。 |
1 | 在这个图里面,表t1刚创建的时候默认只有1个Region,后来数据量多了以后,Region会自动分裂,这样就产生了多个Region。 |
1 | 如果表t1有两个列族c1和c2,那么在存储的时候,列族c1中的数据是一个独立的文件,列族c2中的数据也会是一个独立的文件,也就是说,每一个列族中的数据在底层存储的时候都是一个单独的文件。 |
1 | 所以说我们在设计列族的时候,可以把经常读取的列存储到一个列族中,不经常读取的列放到另一个列族中。 |
HBase物理架构
1 | 主要包含以下内容: |
Zookeeper
1 | ZooKeeper为HBase集群提供协调服务,它管理着HMaster和HRegionServer的状态(available/alive等),并且会在HRegionServer宕机时通知给HMaster。 |
1 | 对Zookeeper的作用总结一下,一共有3点: |
1 | 登录Zookeeper,查看HBase的一些节点信息,HBase默认会在Zookeeper的根节点下面创建hbase节点 |
HMaster
1 | HMaster是HBase集群的主节点,HBase集群支持多个HMaster节点,可以实现HA。 |
HRegionserver
1 | HRegionserver是HBase集群的从节点。 |
HBase架构详解

1 | 图中虚线下面是HDFS部分 上面是HBase的部分 |
1 | [zk: localhost:2181(CONNECTED) 3] get /hbase/meta-region-server |
1 | 我们也可以通过HBase的UI界面进行查看验证。 |

1 | 然后点击进去,显示的这个表确实是在bigdata03这个节点上面 |

1 | 我们可以在这里点击bigdata03:16030这个链接,然后进入到这个界面 |

1 | 最终会发现meta表的数据确实就是在bigdata03这个节点上面的。 |
详解HRegionServer
1 | 下面就来详细看一下HRegionServer里面的内容 |
1 | HRegionServer里面有2块内容,一个是HLog ,另一个是HRegion(其实就是我们前面分析的Region,是同一个意思,Region是HRegion的简称)。 |
1 | 看一下HRegion内部: |

1 | 每一个Store对应一个列族,所以一个HRegion里面可能会有多个Store。 |
HBase物理存储模型
1 | HBase中表的数据是存储在Region中的,表中的数据会越来越多,Region就会分裂,分裂出来的多个Region会分布到多个节点上面,因为单台机器的存储能力是有限的,这样对后期数据并行读取也有好处,有利于扩展。 |
WAL(Write-Ahead Logging)预写日志系统
1 | WAL最重要的作用是灾难恢复。和MySQL的Binlog类似,它记录所有的数据改动。一旦服务器崩溃,通过重放log可以恢复崩溃之前的数据。这也就意味如果写入WAL失败,整个写入操作将认为失败。 |
HFile介绍
1 | HFile是HBase中重要的一个存在,可以说是HBase架构中最小的结构,HBase的底层数据都在HFile中。 |

1 | Data(数据块): 保存表中的数据(key-value的形式),这部分可以被压缩,每个数据块都有一个Magic头,负责存储偏移量和第一个Key。 |
从读/写流程角度理解Hbase架构
写流程

1 | 总结下来: |
读流程

1 | Hbase的读比写慢,因为读的时候,一定要扫描磁盘. |
BloomFilter布隆过滤器
1 | 布隆过滤器是一种比较巧妙的概率型数据结构,可以用来告诉你 “某样东西一定不存在或者可能存在”。 |


1 | 优化: |
HFile compaction(合并)机制
1 | 当MemStore超过阀值的时候,就会持久化生成一个(StoreFile)HFile。 |
Region Split(分裂)机制
1 | 前面我们分析了HFile文件的合并机制,当HFile文件合并多次之后,会导致Region中的数据过大,此时就需要涉及Region的分裂机制了。 |
Region Balance(负载均衡策略)
1 | Region分裂之后就会涉及到Region的负载均衡。 |
4 HBase高级用法
列族高级设置
生存时间(TTL)
1 | 应用系统经常需要从数据库里删除老数据,配置此项,可使数据增加生命周期,超过该配置时间的数据,将会在大合并时“被删除”。(单位:秒) |
1 | hbase(main):009:0> create 't3', {NAME => 'cf1', TTL => '18000'} |
版本数
1 | 在0.96的版本之前默认每个列族是3个version, 0.96之后每个列族是1个version,在大合并时,会遗弃过期的版本。 |
1 | hbase(main):010:0> create 't4', {NAME => 'cf1', VERSIONS => 3} |
压缩
1 | HFile可以被压缩并存放在HDFS上。这有助于节省硬盘IO,但是读写数据时压缩和解压缩会抬高CPU利用率。 |
1 | hbase(main):012:0> create 't5',{NAME => 'cf1', COMPRESSION => 'SNAPPY'} |
数据块(BLOCKSIZE)大小的配置
1 | 随机查询:数据块越小,索引越大,查找性能更好 |
1 | hbase(main):014:0> create 't6',{NAME => 'cf1', BLOCKSIZE => '65537'} |
1 | HBase 的数据块和 HDFS 的数据块是不同的概念,它们用于不同的目的。HBase 的数据块是 HBase 存储数据的最小单元,也是 HBase 缓存数据的基本单位;HDFS 的数据块是 HDFS 存储数据的最小单元,也是 HDFS 分布数据的基本单位。HBase 的数据块通常比 HDFS 的数据块要小得多,因为 HBase 需要支持快速的随机访问,而 HDFS 需要支持高效的顺序访问。 |
1 | HFile 和 HDFS 数据块相比,一般来说 HFile 更大,因为 HFile 是由多个 HBase 数据块组成的,而 HBase 数据块又是存储在 HDFS 数据块中的。HFile 的大小取决于 HBase 数据的量和 MemStore 的刷新策略,通常是几百 MB 或者几 GB 的级别;HDFS 数据块的大小取决于 HDFS 的配置,通常是 64 MB 或者 128 MB 的级别。 |
1 | 根据我的搜索结果,hbase数据块的大小是可以在建表语句中通过参数BlockSize指定的,而memstore和blockcache的大小是可以在配置文件中设置的。因此,它们之间不一定相等,也不一定有固定的比例关系。12 |
数据块缓存(BLOCKCACHE)
1 | 如果一张表或表里的某个列族只被顺序化扫描访问或者很少被访问,这个时候就算Get或Scan花费时间是否有点儿长,你也不会很在意。在这种情况下,你可以选择关闭那些列族的缓存。 |
1 | hbase(main):016:0> create 't7',{NAME => 'cf1', BLOCKCACHE => 'false'} |
布隆过滤器(Bloom filters)
1 | HBase中存储额外的索引层次会占用额外的空间。布隆过滤器随着它们的索引对象的数据增长而增长,所以行级布隆过滤器比列标识符级布隆过滤器占用空间要少。当空间不是问题的时候,它们可以帮助你榨干系统的性能潜力。 |
1 | hbase(main):018:0> create 't8',{NAME => 'cf1', BLOOMFILTER => 'ROWCOL'} |
Scan (全表扫描)
1 | HBase中的Scan操作,类似于SQL中的select * from ... |
Scan的Java API用法
1 | Scan 在Java API中支持以下用法: |
常见的Filter
1 | 在进行Scan的时候,可以添加Filter实现数据过滤 |
RowFilter
1 | RowFilter:对Rowkey进行过滤。 |
1 | LESS 小于 |
PrefixFilter
1 | PrefixFilter:筛选出具有特定前缀的行键的数据。 |
ValueFilter
1 | ValueFilter:按照具体的值来筛选列中的数据,这会把一行中值不能满足的列过滤掉 |
Scan和Filter结合的案例
1 | 注意:在执行下面代码之前,先创建表,初始化一批数据 |
1 | hbase(main):001:0> create 's1','c1','c2' |
1 | package com.imooc.hbase; |
批量导入
1 | 批量导入两种方式: |
批量导入之 MapReduce
1 | 首先初始化输入数据: |
1 | [root@bigdata04 soft]# vi hbase_import.dat |
1 | 把hbase_import.dat上传到HDFS中 |
1 | 此时项目的pom.xml文件中除了添加hbase-client的依赖,还需要添加hadoop-client和hbase-mapreduce的依赖,否则代码报错 |
1 | <dependency> |
1 | 详细代码如下: |
BatchImportMR
1 | package com.imooc.hbase; |
1 | 对代码打jar包: |
1 | <dependencies> |
1 | 还需要添加maven打包配置 |
1 | 执行打jar包命令 |
批量导入之 BulkLoad

1 | 测试数据继续使用hdfs中的hbase_import.dat |
1 | 想要实现BulkLoad需要两步 |
BatchImportBulkLoad
1 | package com.imooc.hbase; |
1 | 打jar包 |
1 | 第二步:加载HFile文件 |
批量导出
1 | 批量导出两种方式: |
批量导出之TableMapReduceUtil
1 | 将HBase中的表batch1中的数据导出到hdfs上面 |
BatchExportTableMapReduceUtil
1 | package com.imooc.hbase; |
1 | 打jar包 |
1 | 注意:想要导出什么格式的数据,具体的逻辑代码在map函数内部根据需求实现即可。 |
批量导出之HBase内部方法
1 | 使用HBase提供的Export工具类直接导出数据 |
HBase连接池
1 | 注意:HBase2.1.2之后的版本,无需创建HBase线程池,HBase2.1.2提供的代码已经封装好,只需创建调用即可。 |