看的出来,KeyValue是支撑”稀疏矩阵”设计的一个关键点:一些Key相同的任意数量的独立KeyValue就可以构成一行数据。但这种设计带来的一个显而易见的缺点:每一个KeyValue所携带的自我描述信息,会带来显著的数据膨胀。
适用场景
在介绍完了HBase的数据模型以后,我们可以回答本文一开始的前两个问题:
- 什么样的数据适合用HBase来存储?
- 既然HBase也是一个数据库,能否用它将现有系统中昂贵的Oracle替换掉?
HBase的数据模型比较简单,数据按照RowKey排序存放,适合HBase存储的数据,可以简单总结如下:
- 以实体为中心的数据
实体可以包括但不限于如下几种:
-
自然人/账户/手机号/车辆相关数据
-
用户画像数据(含标签类数据)
-
图数据(关系类数据)
描述这些实体的,可以有基础属性信息、实体关系(图数据)、所发生的事件(如交易记录、车辆轨迹点)等等。
-
以事件为中心的数据
-
监控数据
-
时序数据
-
实时位置类数据
-
消息/日志类数据
上面所描述的这些数据,有的是结构化数据,有的是半结构化或非结构化数据。HBase的“稀疏矩阵”设计,使其应对非结构化数据存储时能够得心应手,但在我们的实际用户场景中,结构化数据存储依然占据了比较重的比例。由于HBase仅提供了基于RowKey的单维度索引能力,在应对一些具体的场景时,依然还需要基于HBase之上构建一些专业的能力,如:
-
OpenTSDB 时序数据存储,提供基于Metrics+时间+标签的一些组合维度查询与聚合能力
-
GeoMesa 时空数据存储,提供基于时间+空间范围的索引能力
-
JanusGraph 图数据存储,提供基于属性、关系的图索引能力
HBase擅长于存储结构简单的海量数据但索引能力有限,而Oracle等传统关系型数据库(RDBMS)能够提供丰富的查询能力,但却疲于应对TB级别的海量数据存储,HBase对传统的RDBMS并不是取代关系,而是一种补充。
HBase与HDFS
我们都知道HBase的数据是存储于HDFS里面的,相信大家也都有这么的认知:
HBase是一个分布式数据库,HDFS是一个分布式文件系统
理解了这一点,我们先来粗略回答本文已开始提出的其中两个问题:
- HBase中的数据为何不直接存放于HDFS之上?
HBase中存储的海量数据记录,通常在几百Bytes到KB级别,如果将这些数据直接存储于HDFS之上,会导致大量的小文件产生,为HDFS的元数据管理节点(NameNode)带来沉重的压力。
- 文件能否直接存储于HBase里面?
如果是几MB的文件,其实也可以直接存储于HBase里面,我们暂且将这类文件称之为小文件,HBase提供了一个名为MOB的特性来应对这类小文件的存储。但如果是更大的文件,强烈不建议用HBase来存储,关于这里更多的原因,希望你在详细读完本文所有内容之后能够自己解答。
集群角色
关于集群环境,你可以使用国内外大数据厂商的平台,如Cloudera,Hontonworks以及国内的华为,都发行了自己的企业版大数据平台,另外,华为云、阿里云中也均推出了全托管式的HBase服务。
我们假设集群环境已经Ready了,先来看一下集群中的关键角色:
相信大部分人对这些角色都已经有了一定程度的了解,我们快速的介绍一下各个角色在集群中的主要职责(注意:这里不是列出所有的职责):
- ZooKeeper
在一个拥有多个节点的分布式系统中,假设,只能有一个节点是主节点,如何快速的选举出一个主节点而且让所有的节点都认可这个主节点?这就是HBase集群中存在的一个最基础命题。
利用ZooKeeper就可以非常简单的实现这类”仲裁”需求,ZooKeeper还提供了基础的事件通知机制,所有的数据都以 ZNode的形式存在,它也称得上是一个”微型数据库”。
- NameNode
HDFS作为一个分布式文件系统,自然需要文件目录树的元数据信息,另外,在HDFS中每一个文件都是按照Block存储的,文件与Block的关联也通过元数据信息来描述。NameNode提供了这些元数据信息的存储。
- DataNode
HDFS的数据存放节点。
- RegionServer
HBase的数据服务节点。
- Master
HBase的管理节点,通常在一个集群中设置一个主Master,一个备Master,主备角色的”仲裁”由ZooKeeper实现。 Master主要职责:
-
负责管理所有的RegionServer
-
建表/修改表/删除表等DDL操作请求的服务端执行主体
-
管理所有的数据分片(Region)到RegionServer的分配
-
如果一个RegionServer宕机或进程故障,由Master负责将它原来所负责的Regions转移到其它的RegionServer上继续提供服务
-
Master自身也可以作为一个RegionServer提供服务,该能力是可配置的
集群部署建议
如果基于物理机/虚拟机部署,通常建议:
- RegionServer与DataNode联合部署,RegionServer与DataNode按1:1比例设置。
这种部署的优势在于,RegionServer中的数据文件可以存储一个副本于本机的DataNode节点中,从而在读取时可以利用HDFS中的”短路径读取(Short Circuit)“来绕过网络请求,降低读取时延。
- 管理节点独立于数据节点部署
如果是基于物理机部署,每一台物理机节点上可以设置几个RegionServers/DataNodes来提升资源使用率。
也可以选择基于容器来部署,如在HBaseCon Asia 2017大会知乎的演讲主题中,就提到了知乎基于Kubernetes部署HBase服务的实践。
对于公有云HBase服务而言,为了降低总体拥有成本(TCO),通常选择”计算与存储物理分离“的方式,从架构上来说,可能导致平均时延略有下降,但可以借助于共享存储底层的IO优化来做一些”弥补”。
HBase集群中的RegionServers可以按逻辑划分为多个Groups,一个表可以与一个指定的Group绑定,可以将RegionServer Group理解成将一个大的集群划分成了多个逻辑子集群,借此可以实现多租户间的隔离,这就是HBase中的RegionServer Group特性。
示例数据
给出一份我们日常都可以接触到的数据样例,先简单给出示例数据的字段定义:
如上定义与实际的通话记录字段定义相去甚远,本文力求简洁,仅给出了最简单的示例。如下是”虚构”的样例数据:
在本文大部分内容中所涉及的一条数据,是上面加粗的最后一行”Mobile1“为”13400006666“这行记录。
写数据之前:建立连接
Login
在启用了安全特性的前提下,Login阶段是为了完成用户认证(确定用户的合法身份),这是后续一切安全访问控制的基础。
当前Hadoop/HBase仅支持基于Kerberos的用户认证,ZooKeeper除了Kerberos认证,还能支持简单的用户名/密码认证,但都基于静态的配置,无法动态新增用户。如果要支持其它第三方认证,需要对现有的安全框架做出比较大的改动。
创建Connection
Connection可以理解为一个HBase集群连接的抽象,建议使用ConnectionFactory提供的工具方法来创建。因为HBase当前提供了两种连接模式:同步连接,异步连接,这两种连接模式下所创建的Connection也是不同的。我们给出ConnectionFactory中关于获取这两种连接的典型方法定义:
CompletableFuture createAsyncConnection(Configuration conf,
User user);
Connection createConnection(Configuration conf, ExecutorService pool, User user)
throws IOException;
Connection中主要维护着两类共享的资源:
-
线程池
-
Socket连接
这些资源都是在真正使用的时候才会被创建,因此,此时的连接还只是一个”虚拟连接”。
写数据之前:创建数据表
DDL操作的抽象接口 – Admin
Admin定义了常规的DDL接口,列举几个典型的接口:
void createNamespace(final NamespaceDescriptor descriptor) throws IOException;
void createTable(final HTableDescriptor desc, byte[][] splitKeys) throws IOException;
TableName[] listTableNames() throws IOException;
预设合理的数据分片 – Region
分片数量会给读写吞吐量带来直接的影响,因此,建表时通常建议由用户主动指定划分Region分割点,来设定Region的数量。
HBase中数据是按照RowKey的字典顺序排列的,为了能够划分出合理的Region分割点,需要依据如下几点信息:
-
Key的组成结构
-
Key的数据分布预估
如果不能基于Key的组成结构来预估数据分布的话,可能会导致数据在Region间的分布不均匀
- 读写并发度需求
依据读写并发度需求,设置合理的Region数量
为表定义合理的Schema
既然HBase号称”schema-less”的数据存储系统,那何来的是schema? 的确,在数据库范式的支持上,HBase非常弱,这里的Schema,主要指如下一些信息的设置:
-
NameSpace设置
-
Column Family的数量
-
每一个Column Family中所关联的一些关键配置:
-
Compression
HBase当前可以支持Snappy,GZ,LZO,LZ4,Bzip2以及ZSTD压缩算法
- DataBlock Encoding
HBase针对自身的特殊数据模型所做的一种压缩编码
- BloomFilter
可用来协助快速判断一条记录是否存在
- TTL
指定数据的过期时间
- StoragePolicy
指定Column Family的存储策略,可选配置有:
“ALL_SSD”,”ONE_SSD”,”HOT”,”WARM”,”COLD”,”LAZY_PERSIST”
HBase中并不需要预先设置Column定义信息,这就是HBase schema-less设计的核心。
Client发送建表请求到Master
建表的请求是通过RPC的方式由Client发送到Master:
-
RPC接口基于Protocol Buffer定义
-
建表相关的描述参数,也由Protocol Buffer进行定义及序列化
Client端侧调用了Master服务的什么接口,参数是什么,这些信息都被通过RPC通信传输到Master侧,Master再依据这些接口\参数描述信息决定要执行的操作。2.0版本中,HBase目前已经支持基于Netty的异步RPC框架。
关于HBase RPC框架
早期的HBase RPC框架,完全借鉴了Hadoop中的实现,那时,Netty项目尚不盛行。
Master侧接收到Client侧的建表请求以后,一些主要操作包括:
-
生成每一个Region的描述信息对象HRegionInfo,这些描述信息包括:Region ID, Region名称,Key范围,表名称等信息
-
生成每一个Region在HDFS中的文件目录
-
将HRegionInfo信息写入到记录元数据的hbase:meta表中。
说明
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
金三银四马上就到了,希望大家能好好学习一下这些技术点
学习视频:
大厂面试真题:
x-1711938800187)]
[外链图片转存中…(img-OPgh17MS-1711938800188)]
[外链图片转存中…(img-neEqHdTZ-1711938800188)]
[外链图片转存中…(img-nzXnz6qx-1711938800189)]
[外链图片转存中…(img-oBy9P6li-1711938800189)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-z7iNHGTC-1711938800189)]
最后
金三银四马上就到了,希望大家能好好学习一下这些技术点
学习视频:
[外链图片转存中…(img-EfdE9ssx-1711938800190)]
大厂面试真题:
[外链图片转存中…(img-jXf3zKTe-1711938800190)]