目录
1.概述
1.1.前言
本文式作者大数据系列专栏中的一篇文章,按照专栏来阅读,循序渐进能更好的理解,专栏地址:
当前的分布式数据库其实都是参考的google的bigtable,所以学习分布式数据库之前先学一下bigtable会一通百通。专栏中有对bigtable进行介绍的前文:
【大数据】bigtable,分布式数据库的鼻祖-csdn博客
分布式数据库底层依托于分部署文件系统进行存储,分布式数据库更像在分布式文件系统上做了一层封装。就像bigtable底层依托于gfs一样,hbase底层依托于hdfs,专栏有专门介绍hdfs的文章:
1.2.数据模型
hbase中一个具体的数据由行键、列族、列限定符、时间戳组成。数据类型是不定的,统一存储为bytes数组。
之所以有时间戳是因为hbase底层是用的hdfs来做存储的,hdfs只支持追加写,所以hbase为了实现删除效果只能用时间戳来区分哪个数据是最新的。
列族是个很核心的概念,底层的物理存储以列族为单位进行存储,支持动态扩展,一个列族其实就是hdfs中的一个文件,同一列族下的数据一定是被存到hdfs中的一个文件中的。
1.3.列式存储的优势
大数据技术中为什么采用列式存储:
hdbase采用的这种存储模式叫列式存储,传统的关系型数据库采用的行式存储,大数据中普遍都采用列式存储。大数据中之所以采用列式存储是因为列式存储往往更有利于分析,当需要做指标统计的时候往往只需要访问一个列即可,而且列族在物理磁盘上是连续存储的,速度会很快。行式存储要进行指标统计的时候要访问很多无用的列,而且数据在物理磁盘上也不是连续存储的,性能不会很好。
比如数据表是这样:
行式和列式的区别会是:
2.实现原理
2.1.region
hbase最核心的概念!!!
hbase的架构直接参照bigtable即可,只是改了个名字。bigtable的核心是tablet,hbase的核心是region,存储region的服务器叫region server,对应bigtable中的tablet server。一个表会按照行键的字典序列进行排布,然后被分成多个region:
如何找到要的region?
hbase参照bigtable的三层结构也维护了一个类树状结构用来快速查找到要的region:
叶子节点是region、meta表负责维护树形的层级结构,一个meta对应多个region,root只有一个,对应多个meta。
层次 | 名称 | 作用 |
---|---|---|
第一层 | root表 | 记录了meta表的位置信息 |
第二层 | meta表 | 记录了region表的位置信息,meta表相当于一个集合,将region分块的管理,用来维护了层级结构 |
第三层 | 用户表 | 用来记录用户数据 |
2.2.lsm树
lsm树是一种专门针对海量数据读写而升的数据结构,前文中作者聊bigtable的时候单独写了一篇文章对lsm树进行过讲解,可移步:
【大数据】lsm树,专为海量数据读写而生的数据结构-csdn博客
同样hbase中也用了lsm树,也有类似于memtable和sstable的东西:
memstore->memtable
storefile->sstable
这里hbase和bigtable唯一有区别的就是bigtable的一个tablet里只会有一条线的memtable和sstable,而hbase由于支持多个列族所以会有多条线的memtable和sstable。
2.3.完整读写过程
写过程:
-
客户端发起写请求 客户端应用通过hbase客户端api(如java api)向hbase提交一个put请求,包含待写入的数据(包括rowkey、列族、列限定符、值以及可选的时间戳等)。
-
定位目标region 访问zookeeper:客户端首先访问zookeeper集群,先查询hbase:root表以获取hbase:meta表所在的region server位置。 缓存元数据:客户端将获取到的元数据信息(如hbase:meta表或目标region的位置)缓存在本地client cache中,以减少后续操作对zookeeper的依赖和网络开销。
-
查找目标region 查询元数据表:客户端使用缓存的信息连接到hbase:meta表所在的region server,根据待写入数据的rowkey在hbase:meta表中查找目标region的位置。这个过程可能涉及region的三层定位(namespace、表名、rowkey区间),确保找到正确的region负责处理该rowkey的数据。 更新缓存:客户端将查询到的目标region的位置信息(包括region server地址和region边界)更新到本地缓存中。
-
与目标region server交互 发送写请求:客户端根据缓存中的信息,向目标region server发送实际的put请求。
-
region server内部处理 追加写入hlog(wal,write ahead og):region server接收到put请求后,首先将写操作作为一条日志记录追加到hlog。hlog是一种预写式日志,用于保证在发生故障时能够恢复未持久化到磁盘的数据。 随机写入memstore:接着,region server将数据随机写入对应region的memstore。memstore是内存中的数据结构,用于临时存储待写入hfile(hbase的数据文件)的修改。
-
更新blockcache 读写加速:写入完成后,新写入的数据会被添加到region server的blockcache中。blockcache是一种基于lru(最近最少使用)策略的缓存,用于加速后续对相同数据块的读取。
读过程:
-
定位目标region 访问zookeeper:客户端首先访问zookeeper集群,查询hbase的元数据表(hbase:meta)的位置信息。这里同样可能存在旧版流程(先查询hbase:root表)和新版流程(直接查询hbase:meta表)的区别。 缓存元数据:客户端将获取到的元数据信息(如hbase:meta表或目标region的位置)缓存在本地client cache中,以减少后续操作对zookeeper的依赖和网络开销。
-
查找目标region 查询元数据表:客户端使用缓存的信息连接到hbase:meta表所在的region server,根据待读取数据的rowkey在hbase:meta表中查找目标region的位置。这一步确保客户端知道应该向哪个region server的哪个region发送读请求。 更新缓存:客户端将查询到的目标region的位置信息更新到本地缓存中。
-
与目标region server交互 发送读请求:客户端根据缓存中的信息,向目标region server发送实际的get请求。
-
region server内部处理 查询blockcache:region server首先在本地blockcache中查找是否有请求的数据。blockcache是一种基于lru(最近最少使用)策略的缓存,存储最近访问过的hfile数据块。如果数据在blockcache中命中,则直接返回给客户端,避免了磁盘i/o。 查询memstore:如果blockcache中未找到数据,region server接着在对应region的memstore中查找。memstore存储了尚未刷写到hfile的最新数据,如果请求的数据在这里存在且是最新的版本,则直接返回给客户端。 查询hfile:如果blockcache和memstore均未命中,region server将从磁盘上的hfile中读取数据。hfile是按rowkey排序的持久化存储文件,通过二分查找等高效算法快速定位数据。读取到的数据将返回给客户端,并可能被加入到blockcache中以供后续读取加速。 合并版本与过滤:对于同一rowkey的多个版本(依据时间戳区分),region server按照请求的时间戳范围或其他过滤条件(如列族、列限定符等)筛选并合并结果集,只返回满足条件的数据版本。
-
客户端接收响应 处理响应:客户端接收到region server返回的数据后,解析并呈现给应用程序。如果请求涉及多个列族或多行数据,客户端可能需要合并来自不同region server的响应。
数据flush与compaction:
memstore flush:当memstore达到一定大小阈值时,region server将其内容刷写到硬盘上的hfile中,并清空memstore。同时,对应的hlog记录可以被安全地截断(truncated),因为其数据已持久化。 compaction:随着时间推移,针对同一region可能会产生多个hfile。hbase后台会定期执行compaction操作,合并小文件、删除过期版本的数据,并可能进行压缩,以优化读性能和存储空间利用率。
合并没有什么好说的,和bigtable一样,值得注意的是一直合并下去,单体过大后又会分成小块来存储,这个分块存储的过程就会造成一个大region1分成一个个小region。
2.4.master的作用
master主要就是负责整个集群的管理:
-
通过master来对表进行增删改查
-
负责region的分布
-
负责不同region服务器的负载均衡,将负载较重的region服务器上的region重新分布到其它负载轻的region服务器上去。
-
region服务器故障失效后,借助master来将上面的region重新分配给其它服务器。
发表评论