第四章 非关系分布式数据库HBase
本文简要介绍HBase,以及数据库的使用场景、产品定位、数据存储知识, keyvalue,然后从服务分别介绍。RegionServer, HMaster, Zookeeper,HBase数据写入和读取过程。
1. HBase简介
HBase是一种高可靠性、高性能、面向列、可伸缩的分布式存储系统。
-
适用于存储大表数据(数十亿行和数百万列表),读写访问可达到实时水平
BigTable 疏松分布式持久多维排序map,这个map有行健、列键和时间戳索引,每个值都是连续的byte数组
-
利用HDFS作为文件存储系统
-
利用Zookeeper作为协同服务
1. 分布式锁 2. 事件监控 3. Region Server数据的存储
1.1 HBase与RDB的对比
HBase | RDB | |
---|---|---|
只有一个索引-行键,所有访问方法要么通过行键访问,要么通过行键扫描 ,确保查询效率 | 多个索引可以为不同列构建复杂的索引 | |
追加新版本,旧版本保留 | 直接替换 | |
容易扩展,增加集群硬件数量 | 横向扩展困难,纵向扩展空间有限 |
1.2 HBase应用场景
内容 | 特点 | |
---|---|---|
对象存储 | 1B~100M 对象存储(图片、网页、文本、新闻) | 海量存储 |
时序数据 | 时间序列数据(传感器、监控数据、股票K线) | 高并发/海量存储 |
气象数据 | 卫星轨道,气象数据 | 高并发/海量存储 |
Cube分析 | 实时报表 | 高并发/海量存储 |
NewSQL | 元数据库,索引查询 | SQL、二级索引,动态列 |
Feeds流 | 朋友圈 | 高并发请求 |
存储信息/订单 | 聊天信息,订单/存储 | 强同步 海量数据 |
用户画像 | 存储用户特征 | 稀疏矩阵万列 |
兼容结构化/非结构化数据 | 数据库 | 大容量、高并发、低延迟、低成本 |
2. HBase数据模型
2.1 HBase表结构
组成 | 解释 |
---|---|
表(Table) | 组织数据的单位 |
行 | 每个行由行键(Row Key)唯一标识 |
列族(Column Family) | 一个表是基本的访问控制单元,分为多列族集合 |
列限定符 | 列 |
单元格(Cell) | HBase在表中,单元格是通过行、列族确定。单元格存储的数据没有数据类型,总是被视为字节数组byte[] |
时间戳(Time Stamp) | 每个单元格数据保留多个版本,通过时间戳索引 |
2.2 行存储和列存储
行存储 | 列存储 | |
---|---|---|
架构 | ||
优点 | 增加/修改/阅读整行记录速度快 | 单列数据读取/统计速度快 |
缺点 | 单列查询/统计效率低 | 整行读取需要多次IO操作 |
3. HBase体系架构
组件 | 功能 |
---|---|
Zookeeper | Zookeeper为集群的各个过程提供分布式合作服务RegionServer注册自己的信息Zookeeper中,主用Hmaster据此感知各RegionServer的健康状态 |
Client | Client使用HBase的RPC机制与Hmaster,RegionServer管理和数据通信 |
RegionServer | RegionServer提供表数据读写等服务HBase数据处理与计算单元,RegionServer一般与HDFS集群的DataNode部署在一起,实现数据存储功能 |
主Hmaster | RegionServer管理,包括表格的增删改查,RegionServer负载平衡,Region分布调整,Region分裂与分配,RegionServer失效后的Region迁移等 |
备Hmaster | 主要故障时,外部服务,故障恢复后,原主要用为备用 |
HDFS | HDFS为HBase提供文件存储服务 |
HBase该架构包括三个主要功能组件:
- 库函数:链接到每个客户端
- Hmaster主服务器
- 多个HRegionServer服务器
MemStore | StoreFile |
---|---|
当RegionServer中的MemStore大小达到配置的容量上限时, RegionServer会将MemStore中的数据“flush”到HDFS中 | 随着数据的插入,一个Store会产生多个StoreFile,当StoreFile的个数达到配置的最大值时, RegionServer会将多个StoreFile合并为一个大的StoreFile |
组件 | 功能 |
---|---|
HMaster | 管理维护HBase的分区信息,维护HRegionServer列表,分配Region,负载均衡 |
HRegionSever | 维护分配给自己的Region,处理来自客户端的读写请求 |
Client | 从Zookeeper获取Region位置信息,直接找RegionServer读写,大多数情况不与HMaster通信,HMaster负载很小 |
Table
- Region 1 to n
- Store 1 to n 一个列族(column family)对应一个store
- MemStore 1 to 1
- StoreFile 1 to n
- Block 1 to n
3.1 Table与Region
- HBase开始只有一个Region,后来不断分裂
- Region拆分操作非常快,接近瞬间,拆分过程中的region不可读,直到把region存储文件异步地写到独立的文件之后,才会读取新文件
3.2 Region的定位
Region分为元数据Region以及用户Region两类
- Meta Region记录了每一个User Region的路由信息
- 读写Region数据的路由,需要先找Meta Region的地址,再由Meta Region找寻User Region地址
HBase:meta表被保存在Zookeeper中。
假设HBase:meta表的每行(一个映射条目)在内存中大约占用1KB,并且每个Region限制meta表大小为128M,那么二层表结构可以保存的Region数目是128M/1KB = 2^17个Region
3.3 客户端
客户端包含:
- 访问HBase的接口
- 缓存已访问的Region位置信息
访问过程:
- 查询HBase:meta表,然后确定Region的位置
- 客户端直接访问Region(不经过HMaster)进行读写
4. HBase关键流程
4.1 HBase读流程
- 读取数据时,HRegionServer会先访问MemStore缓存,如果找不到,再去StoreFile中寻找
- 根据时间范围,RowKey范围,以及布隆过滤器缩短定位HFile的时间
4.2 HBase写流程
- Client 请求RegionServer地址(Zookeeper中meta表或缓存)
- 用户数据先写入到HLog(WAL)中,再写入MemStore中,最终写入磁盘StoreFile
- 只有当操作写入Hlog后,commit()命令才返回给客户端
4.3 HLog
分布式环境必须要考虑系统出错,HBase采用HLog保证系统恢复。
- HBase系统为每个HRegionServer配置了一个HLog文件,它是一种预写式日志(Write Ahead Log)
- 用户更新数据必须在写入日志之后,才能写入到MemStore进行缓存,直到缓存内容对应的日志写入到磁盘,缓存内容才能flush到磁盘
- Zookeeper实时监测每个HRegionServer的状态,当某个HRegionServer发生故障时,Zookeeper会通知HMaster
- HMaster首先会处理该故障HRegionServer上面遗留的HLog文件,根据Region对象对HLog数据进行拆分,分别放到相应Region的目录下,然后再重新分配HLog到相应的HRegionServer
- HRegionServer领取分配给自己的Region对象以及HLog,重新做一遍日志记录中的各种操作,把日志记录中的数据写入MemStore缓存中,然后,刷新到磁盘的StoreFile
多个Region共用日志的优点:提高表的读写性能,缺点是故障时需要分拆。
5. HFile特点
5.1 HFile压缩Compaction
当HFile的数量越来越多,同样的查询,需要同时打开的文件也越来越多,查询时延也越来越大。
Compaction分为两类:
Minor | 小范围的Compaction,会选择一些连续时间范围的小文件进行合并 |
---|---|
Compaction首先会对File进行一一排查,排除不满足条件的部分文件:
- 排除当前正在执行compact的文件以及比这些文件更新的所有文件(SequenceId更大)
- 排除某些过大的单个文件,否则会产生大量IO消耗
经过排除的文件称为候选文件,HBase接下来会判断是否满足major compaction条件,如果满足,就会选择全部文件进行合并,判断条件有3条,只要满足其中一条就会执行major compaction:
- 用户强制执行major compaction
- 长时间没有进行compact且候选文件数小于hbase.hstore.compaction.max(默认为10)
- Store中含有Reference文件,Reference文件是split region产生的临时文件,只是简单的引用文件,一般必须在compact过程删除
如果不满足major条件,就必然为minor
5.2 OpenScanner
在寻找到rowkey所对应的RegionServer和Region之后,需要打开一个查找器Scanner,由其具体执行查找数据, Region中会包含内存数据MemStore,文件数据Hfiles,那么在openscanner的时候就需要分别读取这两块数据,打开对应不同的scanner做查询操作
- HFile对应的Scanner为StoreFileScanner
- MemStore对应的Scanner为MemStoreScanner
5.2 BloomFilter
Bloom用来优化一些随机读取的场景,即Get场景。它可以被用来快速地判断一条用户数据在一个大的数据集合中是否存在。
- Bloom在判断一个数据是否‘’存在‘’,具有一定的误判率,但对于一个数据是否‘’不存在‘’的判断结果是可信的
- HBase的BloomFilter相关数据,被保存在HFile中
6. HBase性能优化
6.1 行键(Row Key)
行键是字典序存储,因此设计行键时要充分利用这一特点,将经常一起读取的数据存储到一起。
比如:最近写入HBase的数据是最可能被访问的,可以考虑将时间戳作为行键的一部分
6.2 构建HBase二级索引
HBase只有一个针对行键的索引。
访问HBase表中的行,只有三种方式:
- 通过单个行键访问
- 通过一个行键的区间访问
- 全表扫描
可以通过Apache Phoenix进行二级索引。 客户端发起请求时,数据处理模块会对请求进行解析,然后向Phoenix的二级处理模块发起请求,找到对应数据记录的rowkey,然后根据rowkey去查询数据,避免了全表扫描。
6.2.1 Phoenix简介
Apache Phoenix让Hadoop中支持低延迟OLTP和业务操作分析。
-
提供标准的SQL以及完备的ACID事务支持
-
通过利用HBase作为存储,让NoSQL数据库具备通过有模式的方式读取数据,我们可以使用SQL语句来操作HBase,例如:创建表、以及插入数据、修改数据、删除数据等
-
Phoenix通过协处理器在服务器端执行操作,最小化客户机/服务器数据传输
Apache Phoenix可以很好地与其他的Hadoop组件整合在一起,例如:Spark、Hive、Flume以及MapReduce。