HBASE(架构+读写流程)

在这里插入图片描述
HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文《Bigtable》一个结构化数据的分布式存储系统"。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力(低延迟的数据查询能力)。HBase是Apache的Hadoop项目的子项目。HBase不同于一般的关系数据库,Hbase同BigTable一样,都是NoSQL数据库,即非关系型数据库,此外,HBase和BigTable一样,是基于列的而不是基于行的模式。

HBASE基本概念
HBase以表的形式存储数据。表有行和列族组成。列族划分为若干个列
在这里插入图片描述

1)Row Key
hbase本质上也是一种Key-Value存储系统。Key相当于RowKey,Value相当于列族数据的集合。
与nosql数据库们一样,row key是用来检索记录的主键。访问hbase table中的行,只有三种方式:
1 通过单个row key访问
2 通过row key的range
3 全表扫描
Row key行键 (Row key)可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。
存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性)
注意:
字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用0作左填充。

2)列族(列簇)
hbase表中的每个列,都归属与某个列族。列族是表的schema的一部分(而列不是),列族必须在使用表之前定义。列名都以列族作为前缀。例如courses:history , courses:math 都属于 courses 这个列族。
访问控制、磁盘和内存的使用统计都是在列族层面进行的。实际应用中,列族上的控制权限能 帮助我们管理不同类型的应用:我们允许一些应用可以添加新的基本数据、一些应用可以读取基本数据并创建继承的列族、一些应用则只允许浏览数据(甚至可能因 为隐私的原因不能浏览所有数据)。

3)Cell与时间戳
由{row key, column( = + < label>), version} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮。
每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,hbase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。

Hbase系统架构
Hbase与Hadoop架构图
在这里插入图片描述

HBase架构组成
HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由以下类型节点组成:
1.HMaster节点
2.HRegionServer节点
3.ZooKeeper集群
4.Hbase的数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等。RegionServer和DataNode一般会放在相同的Server上实现数据的本地化(避免或减少数据在网络中的传输,节省带宽)。

HMaster节点
1.管理HRegionServer,实现其负载均衡。
2.管理和分配HRegion,比如在HRegion split时分配新的HRegion;在HRegionServer退出时迁移其内的HRegion到其他HRegionServer上。
3.实现DDL操作(Data Definition Language,namespace和table的增删改,column familiy的增删改等)。
4.管理namespace和table的元数据(实际存储在HDFS上)。
5.权限控制(ACL)。

HRegionServer节点
1.存放和管理本地HRegion。
2.读写HDFS,管理Table中的数据。
3.Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)。

ZooKeeper集群
1.存放整个 HBase集群的元数据以及集群的状态信息。以及RS服务器的运行状态
2.实现HMaster主备节点的failover。

下图更全面展示了Hbase于Hadoop的体系图
在这里插入图片描述
HBase Client通过RPC方式和HMaster、HRegionServer通信;一个HRegionServer可以存放1000个HRegion(1000个数字的由来是来自于Google的Bigtable论文);底层Table数据存储于HDFS中,而HRegion所处理的数据尽量和数据所在的DataNode在一起,实现数据的本地化;数据本地化并不是总能实现,比如在HRegion移动(如因Split)时,需要等下一次Compact才能继续回到本地化。

Hbase写流程
当客户端发起一个Put请求时,首先它从hbase:meta表中查出该Put数据最终需要去的HRegionServer。然后客户端将Put请求发送给相应的HRegionServer,在HRegionServer中它首先会将该Put操作写入WAL日志文件中(Flush到磁盘中)。
在这里插入图片描述
写完WAL日志文件后,然后会将数据写到Memstore,在Memstore按Rowkey排序,以及用LSM-TREE对数据做合并处理。HRegionServer根据Put中的TableName和RowKey找到对应的HRegion,并根据Column Family找到对应的HStore,并将Put写入到该HStore的MemStore中。此时写成功,并返回通知客户端。
在这里插入图片描述
HBase读的实现

我们先来分析一下相同的Cell(数据)可能存在的位置:首先对新写入的Cell,它会存在于MemStore中;然后对之前已经Flush到HFile中的Cell,它会存在于某个或某些StoreFile(HFile)中;最后,对刚读取过的Cell,它可能存在于BlockCache中。既然相同的Cell可能存储在三个地方,在读取的时候只需要扫瞄这三个地方,然后将结果合并即可(Merge Read),在HBase中扫瞄的顺序依次是:BlockCache、MemStore、StoreFile(HFile)(这个扫描顺序的目的也是为了减少磁盘的I/O次数)。其中StoreFile的扫瞄先会使用Bloom Filter(布隆过滤算法)过滤那些不可能符合条件的HFile,然后使用Block Index快速定位Cell,并将其加载到BlockCache中,然后从BlockCache中读取。我们知道一个HStore可能存在多个StoreFile(HFile),此时需要扫瞄多个HFile,如果HFile过多又是会引起性能问题。
在这里插入图片描述
扩展:LSM-TREE
概述
众所周知传统磁盘I/O是比较耗性能的,优化系统性能往往需要和磁盘I/O打交道,而磁盘I/O产生的时延主要由下面3个因素决定:
1)寻道时间(将磁盘臂移动到适当的柱面上所需要的时间,寻道时移动到相邻柱面移动所需时间1ms,而随机移动所需时间位5~10ms)
2)旋转时间(等待适当的扇区旋转到磁头下所需要的时间)
3)实际数据传输时间(低端硬盘的传输速率为5MB/ms,而高速硬盘的速率是10MB/ms)

近20年平均寻道时间改进了7倍,传输速率改进了1300倍,而容量的改进则高达50000倍,这一格局主要是因为磁盘中运动部件的改进相对缓慢和渐进,而记录表面则达到了相当高的密度。对于一个块的访问完全由寻道时间和旋转延迟所决定,所以花费相同时间访问一个盘块,那么取的数据越多越好。

磁盘I/O瓶颈可能出现在seek(寻道)和transfer(数据传输)上面。
根据磁盘I/O类型,关系型存储引擎中广泛使用的B树及B+树,而Bigtable的存储架构基础的会使用Log-Structured Merge Tree。

B- Tree和B+Tree
如果没有太多的写操作,B+树可以工作的很好,它会进行比较繁重的优化来保证较低的访问时间。而写操作往往是随机的,随机写到磁盘的不同位置上,更新和删除都是以磁盘seek的速率级别进行的。RDBMS通常都是Seek型的,主要是由用于存储数据的B树或者是B+树结构引起的,在磁盘seek的速率级别上实现各种操作,通常每个访问需要log(N)个seek操作

LSM-Tree
而LSM-tree工作在磁盘传输速率的级别上,可以更好地扩展到更大的数据规模上,保证一个比较一致的插入速率,因为它会使用日志文件和一个内存存储结构,将随机写操作转化为顺序写。

在传输等量数据场景下,随机写I/O的时延大部分花费在了seek操作上,数据库对磁盘进行零碎的随机写会产生多次seek操作;而顺序存取只需一次seek操作,便可以传输大量数据,针对批量写入大量数据的场景,顺序写比随机写具有明显的优势。

The Log-Structured Merge-Tree(LSM-Tree)的一个重要思想就是通过使用某种算法,该算法会对索引变更进行延迟及批量处理,并通过一种类似于归并排序的方式高效地将更新迁移到磁盘,进行批量写入,利用磁盘顺序写性能远好于随机写这一特点,将随机写转变为顺序写,从而保证对磁盘的操作是顺序的,以提升写性能,同时建立索引,以获取较快的读性能,在读和写性能之间做一个平衡。
插入100亿条数据,每条数据大约100kb。
比如更新1%的数据,如果用B-tree,用时100天
如果用LSM-TREE,用时1天。

LSM-Tree原理
在这里插入图片描述
c0 Tree 是存在内存的的树结构,可以是(B-树,B+树,二叉树,跳跃表)
c1 Tree 是存在磁盘上的文件(本身也是一个树结构)
写入或者更新某条记录时,首先会预写日志,用于数据写入失败时进行数据恢复。之后
该条记录会被插入到驻留在内存中的C0树,在符合某个条件的时候从被移到磁盘上的C1树中。
C0树不一定要具有一个类B-树的结构。HBase中采用了线程安全的ConcurrentSkipListMap数据结构。

向内存中的C0树插入一个条目速度是非常快的,因为操作不会产生磁盘I/O开销。然而用于C0的内存成本要远高于磁盘,通常做法是限制它的大小。采用一种有效的方式来将记录迁移到驻留在更低成本的存储设备上的C1树中。为了实现这个目的,在当C0树因插入操作而达到接近某个上限的阈值大小时,就会启动一个rolling merge过程,来将某些连续的记录段(保证是顺序写)从C0树中删除,并merge到磁盘上的C1树中。

在这里插入图片描述
磁盘上的C1树是一个类似于B-Tree的数据结构,但是它是为顺序性的磁盘访问优化过的。

HBase的实现
MemStore
MemStore是HBase中C0的实现,向HBase中写数据的时候,首先会写到内存中的MemStore,当达到一定阀值之后,flush(顺序写)到磁盘,形成新的StoreFile(HFile),最后多个StoreFile(HFile)又会进行Compact。

memstore内部维护了一个数据结构:ConcurrentSkipListMap,数据存储是按照RowKey排好序的跳跃列表。跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。
在这里插入图片描述
HFile
HFlile是lsm tree中C1的实现

猜你喜欢

转载自blog.csdn.net/weixin_42644102/article/details/85679617