这是我参与「第四届青训营 」笔记创作活动的第9天
HBase 核心数据模型
- HBase 是存储计算分离架构,以 HDFS 作为分布式存储底座。数据实际存储在 HDFS。
- HBase 依赖 Zookeeper 实现元数据管理和服务发现。Client 通过 Zookeeper 配置连接到 HBase集群
- Log-Structured Merge Tree 了解 LSM tree 的基本结构和特性。
-
HBase 写流程:
- 数据先写入 WAL 持久化,用于宕机时恢复内存里丢失的数据;
- 再写入内存态 MemStore,以一种跳表(SkipList)数据结构提供有序的数据和高效的随机读写;
- 当满足特定条件时(比如内存中数据过多,或间隔时间过长),MemStore 数据以 HFile 格式写入 HDFS
- HBase 读流程
- 首次读某个 rowkey 时,client 需要从 Zookeeper 获取 hbase:meta 表位于哪个 RegionServer上;
- 然后访问该 RegionServer 查询 hbase:meta 表该 rowkey 对应 region 所在的 RegionServer B;
- Client 缓存该位置信息,去 RegionServer B 读取 rowkey;
- 基于该region内可能存在该 rowkey 的 HFile 和 MemStore 构建一个最小堆,用以全局有序地 scan 数据(具体实现可搜索参考 LSM tree 设计原理)
-
Compaction
-
HBase 基于策略和定期整理 HFile 文件集合,将多个有序小文件合并成若干个有序的大文件。
-
HBase 提供两种 compaction 类型:
- Minor compaction: 指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次 Minor Compaction 的结果是更少并且更大的StoreFile。
- Major compaction: 指将所有的StoreFile合并成一个StoreFile,这个过程会清理三类没有意义的数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。另外,一般情况下,major compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此线上业务都会将关闭自动触发major compaction功能,改为手动在业务低峰期触发。
-
Compaction 触发条件:
- memstore flush:可以说compaction的根源就在于flush,memstore 达到一定阈值或其他条件时就会触发flush刷写到磁盘生成HFile文件,正是因为HFile文件越来越多才需要compact。HBase每次flush之后,都会判断是否要进行compaction,一旦满足minor compaction或major compaction的条件便会触发执行。
- 后台线程周期性检查: 后台线程 CompactionChecker 会定期检查是否需要执行compaction,检查周期为hbase.server.thread.wakefrequency*hbase.server.compactchecker.interval.multiplier,这里主要考虑的是一段时间内没有写入请求仍然需要做compact检查。其中参数 hbase.server.thread.wakefrequency 默认值 10000 即 10s,是HBase服务端线程唤醒时间间隔,用于log roller、memstore flusher等操作周期性检查;参数 hbase.server.compactchecker.interval.multiplier 默认值1000,是compaction操作周期性检查乘数因子。10 * 1000 s 时间上约等于2hrs, 46mins, 40sec。
- 手动触发:是指通过HBase Shell、Master UI界面或者HBase API等任一种方式 执行 compact、major_compact等命令。
-
客户端定位数据
直连HBase的客户端需要配置对应的Zookeeper信息来定位数据所在的RegionServer,具体包括zookeeper集群实例的地址列表和该hbase集群在zookeeper中对应的根路径。
直连客户端具体定位步骤如下:
- 客户端访问Zookeeper获取元信息表hbase:meta所在的regionserver地址;
- 客户端访问该regionserver查询要读/写的table的rowkey在哪个regionserver;
- 客户端访问存数据的regionserver进行读写。
通过Thrift协议访问HBase的客户端需要ThriftServer的地址,通过ThriftServer转发请求。可以通过Consul实现thriftserver的服务发现。
LSM tree
HBase将每个column family的数据独立管理,称为HStore。一个HStore包含一到多个物理文件块(称为HFile)存储到HDFS。实际存储时每个column family独立存储,一个column family对应多个HFile文件块。
每个HFile内的数据按rowkey有序存储,但HFile间没有顺序保证。这一特点是由于LSM的写入方式决定的,下面介绍LSM树的读写流程:
- 写入:写入操作先记录到Write-Ahead Log持久化(可选)保存,然后写入内存中的MemStore。WAL可以保证实例挂掉或重启后丢失的内存数据可以恢复。
- 读取:从写入逻辑可以看出HFile包含的rowkey范围会有交集,以全局rowkey顺序读取就需要以一种归并排序的形式组织所有HFile。HBase会打开该cf下所有HFile,分别构建一个迭代器用以rowkey从小到大扫对应HFile的数据。所有这些迭代器又以当前指向rowkey的大小组织成一个最小堆,这样堆顶的迭代器指向的rowkey就是下一个全局最小的rowkey。迭代该rowkey后重新调整最小堆即可。
生态
通过在 HBase之上引入各种组件可以使HBase应用场景得到极大扩展,例如监控、车联网、风控、实时推荐、人工智能等场景的需求。
- Phoenix
主要提供SQL的方式来查询HBase里面的数据。一般能够在毫秒级别返回,比较适合OLTP以及操作性分析等场景,支持构建二级索引。
- Spark
很多企业使用HBase存储海量数据,一种常见的需求就是对这些数据进行离线分析,我们可以使用Spark(Spark SQL) 来实现海量数据的离线分析需求。同时,Spark还支持实时流计算,我们可以使用 HBase+Spark Streaming 解决实时广告推荐等需求。
- HGraphDB
分布式图数据库,可以使用其进行图 OLTP查询,同时结合 Spark GraphFrames 可实现图分析需求,帮助金融机构有效识别隐藏在网络中的黑色信息,在团伙欺诈、黑中介识别等。
- GeoMesa
目前基于NoSQL数据库的时空数据引擎中功能最丰富、社区贡献人数最多的开源系统。提供高效时空索引,支持点、线、面等空间要素存储,百亿级数据实现毫秒(ms)级响应;提供轨迹查询、区域分布统计、区域查询、密度分析、聚合、OD 分析等常用的时空分析功能;提供基于Spark SQL、REST、GeoJSON、OGC服务等多种操作方式,方便地理信息互操作。
- OpenTSDB
基于HBase的分布式的,可伸缩的时间序列数据库,适合做监控系统;比如收集大规模集群(包括网络设备、操作系统、应用程序)的监控数据并进行存储,查询。
- Solr
原生的HBase只提供了Rowkey单主键,仅支持对Rowkey进行索引查找。可以使用 Solr来建立二级索引/全文索引来扩展更多查询场景的支持。
功能
Bulkload
大批量向HBase导入数据的功能。使用MapReduce任务直接生成底层存储的HFile文件,并直接移动到HBase存储目录下,节省HBase写路径的开销从而提高写入效率。
Coprocessor
提供一套接口框架,给HBase原生接口添加类似lifecycle hook函数的能力,用来执行用户自定义的功能来扩展HBase的能力,例如二级索引、Observer等功能。
Filter
将用户的过滤逻辑下推到HBase服务端,避免无用数据传输处理开销来提高查询效率。
MOB
Medium Object Storage解决HBase对中等大小对象(10-100MB)的低延迟读写支持,拓宽HBase适用场景。
Snapshot
数据备份功能,将某一时刻的数据以及元数据备份,用于数据恢复、快照读、复制表等功能。
Replication
将一个HBase集群中的数据复制到目标HBase集群,使用WAL将变更记录同步到其他集群。
数据组织方式
HBase是半结构化存储。数据以行(row)组织,每行包括一到多个列簇(column family)。使用列簇前需要通过创建表或更新表操作预先声明column family。
column family是稀疏存储,如果某行数据未使用部分column family则不占用这部分存储空间。
每个column family由一到多个列(column qualifier)组成。column qualifier不需要预先声明,可以使用任意值。
最小数据单元为cell,支持存储多个版本的数据。由rowkey + column family + column qualifier + version指定一个cell。
同一行同一列族的数据物理上连续存储,首先以column qualifier字典序排序,其次以timestamp时间戳倒序排序。