深入浅出 HBase 实战 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第10天,本篇笔记主要是关于第十次大数据课程《深入浅出 HBase 实战》的课堂笔记
HBase适用场景
HBase:一个开源的NoSQL分布式数据库,采用存储计算分离架构:
- 存储层基于HDFS存储数据,提供容错机制和高可靠性
- 计算层提供灵活快速的水平扩展、负载均衡和故障恢复能力
HBase和关系型数据库区别
HBase数据模型:
HBase以列族(column family)组织数据,以行键(rowkey)索引数据。
- 以列族( column family )为单位存储数据,以行键( rowkey )索引数据。
- 列族需要在使用前预先创建,列名( column qualifier )不需要预先声明,因此支持半结构化数据模型。
- 支持保留多个版本的数据,(行键+列族+列名+版本号)定位一一个具体的值。
HBase数据模型-逻辑结构:
- 适合稀疏数据,缺省列不占用存储空间。
- 允许批量读取多行的部分列族/列数据。
HBase数据模型-物理结构:
- 物理数据结构最小单元是KeyValue结构。
- 每个版本的数据都携带全部行列信息。
- 同一行,同一列族的数据物理上连续有序存储。
- 同列族内的KeyValue按rowkey字典序升序,column qualifier 升序,version降序排列。
- 不同列族的数据存储在相互独立的物理文件,列族间不保证数据全局有序。
- 同列族下不同物理文件间不保证数据全局有序。
- 仅单个物理文件内有序。
HBase数据模型的优缺点:
HBase架构设计
HBase架构:
- 主要组件包括:
- HMaster:元数据管理,集群调度、保活。
- RegionServer:提供数据读写服务,每个实例负责若千个互不重叠的rowkey区间内的数据。
- ThriftServer:提供Thrift API读写的代理层。
- 依赖组件包括:
- Zookeeper:分布式一致性共识协作管理 ,例如HMaster选主、任务分发、元数据变更管理等。
- HDFS:分布式文件系统, HBase数据存储底座。
RegionServer主要职责:
- 提供部分rowkey区间数据的读写服务
- 如果负责meta表,向客户端SDK提供rowkey位置信息
- 认领HMaster发布的故障恢复任务,帮助加速数据恢复过程
- 处理HMaster下达的元数据操作,如region打开/关闭/分裂/合并操作等
ZooKeeper主要职责:
- HMaster登记信息,对active/backup分工达成共识
- RegionServer登记信息,失联时HMaster保活处理
- 登记meta表位置信息,供SDK查询读写位置信息
- 供HMaster和RegionServer协作处理分布式任务
大数据支撑
水平扩展能力:
- 增加RegionServer实例,分配部分region到新实例。
- 扩展过程平滑,无需搬迁实际数据。
- 可用性影响时间很短,用户基本无感知。
Region热点切分:
- 当某个region数据量过多, 切分成两个独立的子region分摊负载。
- RegionServer在特定时机( flush、compaction )检查region是否应该切分,计算切分点并RPC上报HMaster,由AssignmentManager负责执行RegionState Transition。
- 不搬迁实际数据,切分产生的新region数据目录下生成一个以原region文件信息命名的文件,内容是切分点对应的rowkey,以及标识新region是上/下半部分的数据。
Region碎片整合:
- 当某些region数据量过小、碎片化,合并相邻region整合优化数据分布。
- AssignmentManager创建Merge TableRegionsProcedure执行整合操作。
- 不搬迁实际数据,通过reference file定位原region的文件直到下次 compaction 时实际处理数据。 注意:只允许合并相邻region否则会打破 rowkey空间连续且不重合的约定。
Region负载均衡:
定期巡检各RegionServer上的region数量,保持region的数量均匀分布在各个RegionServer上。
SimpleLoadBalancer具体步骤:
- 根据总region数量和RegionServer数量计算平均region数,设定弹性上下界避免不必要的操作。
- 将RegionServer按照region数量降序排序,对region数量超出上限的选取要迁出的region并按创建时间从新到老排序。
最佳实践分享
Rowkey设计策略:
- 不需要顺序扫描批量连续rowkey
- 对原始rowkey做哈希(如MD5), 作为真实rowkey的前缀。
- 建议取适当长度的子串,避免过多占用存储空间。
- 需要顺序扫描批量连续rowkey
- 首先用grouplD/applD/userlD前缀避免数据热点,然后加上定义顺序的信息(如时间戳等)
- ID前缀也建议哈希处理,避免非预期的热点。
- rowkey长度尽量保持较短,因为会冗余存储到每个KeyValue中。 避免用时间戳直接作为rowkey前缀,会导致最新的数据始终集中在单个RegionServer上,造成热点瓶颈,且无法通过水平扩容缓解。
Column Family设计策略:
- Column family数量过多容易影响性能,建议尽量少,不超过5个。
- 需要同时读取的数据尽量放在相同列族,反之尽量放在不同列族,读取时尽量只读取必需的列族,避免读不必要的列族。
- 列族(以及column qualifier )名称尽量短,因为会冗余存储到每个KeyValue中。