大数据理论与实践10 分布式NewSQL数据库Hyperbase

一个重量级的组件,原生HBase不支持SQL(NoSQL),星环Hyperbase提供SQL的支持。

简介

概念

  • 高可靠、可伸缩、高并发、实时(实时随机读写)、面向列(存储和优化以列为单位)的分布式NewSQL数据库。
  • 基于Hbase(Hadoop Database,是Google Bigtable的开源实现)实现。
  • NewSQL数据库:NoSQL+RDBMS。
  • Key-Value数据库:主要通过Key实现数据的增删改查,以及扫库操作。
  • 列式存储:按列族存储,可以自由添加列,对Schema限制较少,用于存储和管理海量的半结构化(大的稀疏数据表)数据。
  • 文件存储采用HDFS(HBase寄生于HDFS;HBase基于日志,适合追加写,适合采用HDFS)
    在这里插入图片描述
    HyperDrive是一个转换驱动,二维表转换为HBase的,也支持ES。

特点

  1. 超大规模数据存储
    半结构化数据(大而稀疏)、图片/音视频等小对象、面向高并发访问的结构化数据(关系数据库并发度不高,一般是三位数,上万的并发查询关系型数据库不适合的)
    例如高考查成绩的高并发查询结构化数据的场景,适合采用HyperBase。
  2. 支持随机读写:可以和流计算引擎进行对接
  3. 高并发点查:点查指的是简单条件(与或非)的精确查询
  4. 线性扩展:不停机条件下可以动态扩展、负载均衡、性能线性增长
  5. 高可用
    数据高可用、Region高可用(会进行负载均衡、故障迁移)、HDFS高可用、预写日志
  6. 数据强一致性(HyperBase是数据库而不是数据仓库)

访问方式

HBase Shell、Inceptor SQL、HBase API

原理

数据模型

在这里插入图片描述
RowKey:行键,二维表(一般为Rowkey | 列)中的行标识(rk001,rk002)
HyperBase是四维表
Rowkey | 列族 | 列限定符 | 时间戳
列族:一组列的统称,Basic是一个列族,里面的name、age等是列限定符。列族是固定的但是列限定符是可以增加的,提供了弹性。
时间戳:也被称为Version,区分数据的版本。例如手机号后来换了,老的数据不会被覆盖,而是通过timestamp进行区分,老数据在下面新数据在上面。
读取顺序:表->RowKey->列族->列限定符->单元格->时间戳

概念

  1. 命名空间(Namespace):命名空间是对表的逻辑分组,类似于关系数据库中的Database,在多租户场景下可做到更好的资源和数据隔离
  2. 表(Table):Hyperbase以“表”为单位组织数据,表由多行组成
    行(Row):表以“行”为单位组织数据,行由一个Rowkey和多个列族组成, RowKey是行的主键,字典序排列,大小为64K
  3. 列族(Column Family)
    数据按“列族”垂直分组,每一行由若干列族组成,每个列族下可包含多个列,必须在建表时明确定义且不能频繁修改。它的数量不能太多,理论上限制在几十个(实际会更少);物理上同一列族的数据存储在一起,即列式存储;权限控制、存储以及调优都在列族层面进行
  4. 列与列限定符(Columen & Column Qualifier)
    一个列族可包含多个列,且各列族可包含不同的列;列由列族和列限定符唯一指定,列名由列族名和列限定符组成,以“:”分隔;新列可按需动态加入列族
  5. 单元格(Cell)
    单元格由Rowkey、列族、列限定符唯一定位;存放若干<Value, Version>。例如上图红色部分,手机号值和时间戳是一个单元格。可以由<Rowkey, Column(Column Family: Column Qualifier), Version>来唯一定位。具体的值是无类型的(Byte[])
  6. 时间戳
    单元格的值利用时间戳来标识版本;最新的数据排在最前面(默认拿数据是拿最新的)。数据结构为64为整型。
  7. Rowkey & Key
    Rowkey用于唯一标识逻辑上的行。但是在物理上,HBase是Key-Value的,这个Key并不是RowKey。
    <Rowkey, Column family, Column Qualifier, Version, Value> → <Key, Value>
    <Rowkey, Column family, Column Qualifier, Version> → Key
    在这里插入图片描述

表的特点

规模大,无模式,面向列族,稀疏(空值不占空间),数据多版本(时间戳区分),无类型(所有数据Byte[]类型存储)

系统架构

Master+Slave
在这里插入图片描述

HMaster(Master)

  • 管理表的创建、删除和修改
  • 动态添加和删除HRegionServer
  • 为HRegionServer分配Region:HRegionServer宕机后,重新分配其上的Region;通过调整Region分布,实现HRegionServer的负载均衡
  • 管理元数据:元数据包括HRegionServer、Region相关信息,存储在HRegionServer中
  • 不处理Client的数据读写请求(为了实现高并发,不经过Master直接找HRegionServer,提高效率)

HRegionServer(Slave)

  • 处理Client的数据读写请求
  • 管理Region Split(分裂)
  • 管理StoreFile Compaction(合并)

Zookeeper

实现HMaster高可用;监控HRegionServer的上下线信息,并通知HMaster;存储元数据的寻址入口(无需通过Master)

Client

通过接口访问Hyperbase;为了加快数据访问速度,将元数据缓存在Client Cache中

数据存储

Region

含义:将表水平(按行)划分为多个区域(Region),每个Region保存表的一段连续数据(按Key排序,这里的key是上面写的RowKey+Column family+Column Qualifier+Version)。表通常被保存在多个HRegionServer的多个Region中。
Regin分裂:默认每张表开始只有一个Region,随着数据不断写入,Region不断增大,当Region大小超过阀值时,会分裂成两个子Region(等分)。
Region迁移:随着Region的不断增多,HMaster会将部分Region迁移到其他HRegionServer中,实现负载均衡。
Region是Hyperbase中分布式存储和负载均衡的最小单元(默认256M)。不同Region可分布在不同的HRegionServer上,但一个Region不会拆分到多个HRegionServer上。
在这里插入图片描述

Store

一个Region由多个Store组成,每个Store存储一个列族;Store由内存中的MemStore和磁盘中的若干StoreFile组成。
在这里插入图片描述
内存中的Store是MemStore,Store的内存缓冲区即内存中一个存储<Key, Value>的MAP。实现的方式是一个跳表(SkipList)。写数据时,先写MemStore(默认64MB),当数据量超过阈值,会溢写磁盘,生成StoreFile。读数据时,先读MemStore,再读StoreFile。
StoreFile是MemStore的磁盘溢写文件,StoreFile底层是存储在HDFS上的HFile(Hadoop二进制文件)。Storefile合并:当Store中StoreFile数量超过阈值时,会将若干小文件合并为一个大StoreFile(底层是小B+树合成大B+树实现,很耗资源)。
当Region中最大Store的大小超过阈值时,会将其等分为两个子Region(很耗资源)。

HFile(v1)

KeyValue:
在这里插入图片描述
Key/Value Length:Key和Value长度
Row:Rowkey行键
Row/Column Family Length:Rowkey和Column Family的长度
Key Type:Key类型(Put / Delete,例如删除数据,这个标签为删除。删除的数据当StoreFile合并时会被扔掉)
宏观下的数据存储:
在这里插入图片描述

微观上存储举例

在这里插入图片描述
这是一个表,r1r2代表RowKey,cf1、cf2代表列族,c1c2代表列限定符,三个黄色小块代表有三个历史数据。
接下来按照按照列族进行区分:
![在这里插入图片描述](https://img-blog.csdnimg.cn/6540d1f73cf14326a364088b01220608.png?x-oss-process 400x300)
分为多个StoreFile
![在这里插入图片描述](https://img-blog.csdnimg.cn/bf4e0144e34447188e64a865037b7caa.png?x-oss-process 400x300)
在这里插入图片描述

读写操作

关系型数据库底层采用B+树,但是B+树随着新数据的插入,叶节点会慢慢分裂,逻辑上连续的叶节点在物理上往往不连续,甚至相隔很远,这样会产生大量的随机写IO。例如,随着数据越来越多,物理上分隔越来越远,硬盘在随机写的过程中寻道开销会很大,影响效率。这样在大数据、实时性的要求下可能出现问题。

LSM-Tree

读写采用LSM-Tree(The Log-Structured Merge-Tree,日志结构合并树)。核心思想是数据赞一批,批量写。
原理
在这里插入图片描述
写入或更新数据时,先预写日志,再写入内存中的C0树,并在符合条件时溢写到磁盘上的C1树,然后C1树与磁盘上的其他树合并为一棵大树CK。
这样写的时候是先写内存,不直接往硬盘上写,在内存中先排好序再写硬盘。相当于把一棵大树拆分成若干棵小树。这样就把随机写转换为了顺序写,也符合HDFS顺序写效率高的特点。
在这里插入图片描述

这样在性能上,写入速度快,牺牲了部分读性能(先读内存再找磁盘,磁盘上有很多小树)。

写操作

在这里插入图片描述

  1. Client从ZK中获取-ROOT-表地址(元数据寻址入口),读取-ROOT-表并缓存在Cache中(-ROOT-表:记录.META.的Region信息,只包含一个Region。ROOT表相当于元数据的索引)
  2. Client根据-ROOT-表读取.Meta.表并缓存在Cache中,同时根据Namespace、表名和Rowkey,获得目标Region的位置信息
  3. Client向HRegionServer发出写请求
    请添加图片描述
  4. HRegionServer先将操作和数据写入HLog(Write Ahead Log / WAL / 预写日志),再将数据写入MemStore
  5. 当MemStore的数据超过阈值时,溢写磁盘生成StoreFile文件
  6. 当StoreFile的数量超过阈值时,将若干小StoreFile合并(Compact)为一个大StoreFile
  7. 当Region中最大Store的大小超过阈值时,Region分裂(Split),等分成两个子Region

读操作

  1. Client访问-ROOT-表和.META.表,获取目标Region的位置信息(见写操作的第1、2步)
  2. Client向HRegionServer发出读请求
  3. HRegionServer按照“MemStore(内存)→ BlockCache(内存)→ StoreFile(磁盘)”的顺序查找
    BlockCache:①HRegionServer会将上一次查找的Block块缓存到BlockCache中,以便后续同一请求或者邻近数据的读取请求,可以直接从内存中获得;②采用LRU(Least Recently Used / 最近最少使用)淘汰策略
  4. 先将本次查找的Block块缓存在BlockCache中,再返回结果

删除操作打上删除标记,但不做物理删除,读数据时会忽略。

StoreFile Compaction

将Store中的全部或部分StoreFile小文件合并为一个StoreFile大文件的过程。
目的:减少StoreFile数量,提升数据读取效率。
触发时机:①Memstore溢写;②后台线程周期性检查;③手动触发且不能停止(推荐)
触发条件:当Store中的StoreFile数量超过阈值时,触发StoreFile Compaction
分为Minor CompactionMajor Compaction
Minor Compaction选取Store下的部分StoreFile(小的或相邻的),将它们合并为一个StoreFile,开销较小;
Major Compaction将Store下的所有StoreFile合并为一个StoreFile,删除过期版本、带删除标记的数据。默认一周一次,推荐手动触发。

Region Split

根据一定的触发条件和分裂策略,将Region划分为两个子Region的过程,来实现数据访问的负载均衡。
方式:利用Middle Key将当前Region划分为两个等分的子Region。
触发时间:①Memstore溢写;②StoreFile Compaction;③手动
触发条件:当Region中最大Store的大小超过阈值时,触发Region Split。

Split会产生大量I/O操作,在开始前和Split完成后,HRegionServer都会通知HMaster,HMaster会根据集群负载情况决定是否需要调整Region分布。Split完成后,HRegionServer会更新.Meta.表。

WAL 预写日志

WAL(Write Ahead Log,预写日志),主要为了防止意外宕机,导致C0树丢失。

全局索引

原理

  1. 原表(一级索引)
    按Rowkey字典序排列,效率是比较高的,但无法实现基于其他列的条件查询。
  2. 全局索引(二级索引,原生HBase不支持)
    通过在某个或某些列上建立二级索引,实现基于列的快速条件查询。
    在这里插入图片描述
    对整个检索列进行一个排序,建立索引,加快查找。

Index DDL

CREATE GLOBAL INDEX <index_name> ON <tableName> (
	<column1> <SEGMENT LENGTH length1> | <(length1)> 
	[, <column2> <SEGMENT LENGTH length2> | <(length2)>, ...] 
);
# <column1>:在某个列上建全局索引,但不可以是首列,因首列映射为Rowkey
# <SEGMENT LENGTH length2>:只有索引列为String类型时,才需要指定长度,简写为(length2)
#例子:
CREATE GLOBAL INDEX index_name ON hyper_student(name(12)); 

新建的索引中没有数据,数据在以下两种情况下才会生成

  • 原表中有新数据插入时,系统会为新插入的数据自动生成索引
  • 如果表里面有数据,后来又创建索引,需要对索引执行重建(Rebuild)操作,系统会为表中所有数据生成索引
# 为全表生成索引
rebuild_global_index 'table_name', 'index_name'

Hyperbase基本用法

HBase Shell命令

/* 创建表,cf1、cf2为列族名 */
create ‘table_name’, ‘cf1’, ‘cf2’ …
/* 插入或更新数据,cf为列族名,cq为列名,value为要写入的数据 */
put ‘table_name’, ‘row_key’, ‘cf:cq’,value[, timestamp]
/* 读取单行数据 */
get ‘table_name’, ‘row_key’
/* 读取列族数据 */
get ‘table_name’, ‘row_key’, ‘cf’
/* 读取列数据 */
get ‘table_name’, ‘row_key’, ‘cf:cq’
/* 删除列 */
delete ‘table_name’, ‘row_key’, ‘cf: cq’[, timestamp]
/* 删除行 */
delete ‘table_name’, ‘row_key’
/* 全表扫描 查看表的全部数据 */
scan ‘table_name’
/* 计算表的行数 */
count ‘table_name’

Inceptor SQL

采用Hyperdrive表,实现SQL与HBase对接而专门设计的Inceptor表,是HBase四维表的二维映射表。
Inceptor在Hyperbase中用作:SQL引擎:SQL解析、优化和执行,SQL与HBase之间的桥梁;逻辑数仓:管理Hyperdrive表,以及与HBase表的映射关系,表的Schema存储在Inceptor Metastore中。

Hyperbase数据快速入库

传统数据入库

采用的是TableOutputFormat方式:利用MapReduce将数据批量写入(put)到HBase中
在这里插入图片描述

大规模数据入库时,TableOutputFormat方式效率低下:

  • 导致频繁的Flush、Split、Compact等IO操作
  • 在持续写入的过程中,Memstore会占用大量内存
  • 被迫使用更大的HLog(HLog用的会很快),或完全停用HLog
  • 对节点的稳定性造成一定影响,如GC时间过长,系统响应过慢,导致节点超时退出

BulkLoad数据入库 (原生HBase)

由于数据以HFile的形式存储于HDFS,所以可以绕过HBase API,先预分Region(RowKey的一个范围),再将数据加工成HFile文件,并加载到HBase中,从而完成大规模数据的快速入库。
相当于之间去写底层的HFile文件,而不需要去调用存储的方法。这样做极大地提高了入库效率;不占用HRegionServer资源,显著减轻了集群的写入压力;利用MapReduce加工HFile文件,非常高效。

HBase BulkLoad基本流程

  1. 抽取:从数据源中抽取数据。对于MySQL,运行mysqldump命令导出数据
  2. 转换:利用MapReduce将数据转换为HFile文件
    对于TSV或CSV文件,使用HBase ImportTsv工具将其转换成HFile文件
    每个输出文件夹中的每个区域都会创建一个HFile文件
  3. 转换:利用MapReduce,将数据转换为HFile文件。
    HDFS中的可用磁盘空间至少为原始输入文件的两倍
  4. 加载:将HFile文件加载到HBase
    利用HBase CompleteBulkLoad工具,将HFile文件移动到HBase表的相应目录中,完成加载
    在这里插入图片描述

Hyperbase SQL BulkLoad(星环)

操作步骤:

  1. 将数据集上传至HDFS

  2. 为HDFS中的数据集创建Inceptor外表

  3. 对Inceptor外表预分Region,获取Split Key
    可以人工选取Split Key,也可以通过SQL自动生成Split Key
    根据Rowkey对数据集预先划分Region,使各个Region的大小均匀、行数接近。每个Region的大小为1-3GB,每个HResionServer管理10-1000个Region。
    在这里插入图片描述

  4. 在Inceptor中创建Hyperdrive表(HBase表的二维映射表),利用Split Key(第3步获取)对HBase表预分Region

  5. 在Inceptor中使用SQL BulkLoad语句,将外表中的数据导入Hyperdrive表

复习

为什么可以将HBase表看作是一个四维表?
为什么说HBase是一个Key-Value数据库?
简述Table、Region、Store和StoreFile的关系。
为什么要进行Region Split和StoreFile Compaction?
请分析一下HBase能做到实时随机读写的主要原因。

参考

课程内容来自:南京大学+星环科技课程,大数据大数据理论与实践课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值