1、hbase框架简单介绍
hbase是一个分布式、面向列的开源数据库,它适合于存储非结构化数据,基于列的模式,一行数据可以对应一个或者多个列族。在分布式环境中需要运行在hdfs上作为其存储设施。hbase主要是由Hmaster与hregionserver组成。hbase中有这样几个概念分别介绍下rowkey这个是用来检索的主键,检索时分为单个rowkey,范围rowkey以及全表扫描,rowkey存储时默认按照字段顺序排序存储。列族,hbase中每个列都归属某个列族,列族是表的schema的一部分,必须在使用表之前就定义好。访问控制、磁盘和内存的使用统计都是在列族层面进行的。在实际应用中,列族上的控制权限能帮助我们管理不停类型的应用(比如我们允许一些应用可以添加新的基本数据、一些应用可以读取基本数据)。时间戳,hbase中通过row和columns确定的为一个存储单元称为cell。每个cell都保存着同一份数据多个版本,而版本就是通过时间戳来进行索引。每个cell中按照不同版本的时间倒叙排序,即最新的数据排在最前面。时间戳可以设置保存n个版本,也可以按照时间保存某个时间段内的版本,可以根据每个列族进行设置。cell,这个是{row key, column( =<family> + < label>), version}
2、hbase的ROOT表与META表
Hbase的所有region元数据都被存储在META表中,随着region的增多,META表中的数据也会增大,并分裂成多个新的region。为了定位meta表中的各个region的位置,把meta表中所有的region的元数据保存在ROOT表中,最后由zookeeper记录root表的位置信息。当客户端访问数据时,需要先访问zookeeper或者root的位置,然后访问root表获得met表的位置,最后根据met表中的信息确定用户数据存放位置。如下图:

root表永远不会被分割,它只有一个region,这样可以保证最多三次跳转就可以定位到任意一个region。为了加快访问速度,meta表的所有region全部保存在内存中。客户端会将查询过得位置信息缓存起来,且缓存不会主动失效。首选是如果客户端根据缓存信息还访问不到数据,则询问相关meta表的region服务器。试图获取数据的位置,如果还是失败,则询问root表相关的meta表在哪里。最后如果前面的信息全部失效,则通过zookeeper重新定位region的信息。所以因此也就是说如果客户端上的缓存信息全部丢失的话,需要进行6次网络来回才能定位到正确的region

3、高可用性
(1)WAL保障数据高可用
先理解下hlog的作用,hbase中的Hlog机制是WAL的一种实现,而WAL是事务机制中常见的一致性的实现方式。每个regionserver中都会有一个Hlog的实例,注意不是每个region,是每个regionserver维护一个。相对多个region维护多个的话这样读取一个文件比读取多个文件可以减少磁盘的寻址次数,提高性能。但是带来的麻烦也是有的,如果regionserver下线,为了恢复其上的region需要将regionserver上的log进行拆分,然后分发到其他的regionserver上进行恢复。,regionserver会将更新操作先记录到WAL也即是Hlog中,然后将其写到store中的memstore,当memstore达到一定大小就会将数据写入到持久化的Hfile中(memstore达到内存配置的阈值)。这样就保证了hbase的写的可靠性。如果没有WAL,当regionserver宕掉的时候,memstore还没写入到hfile,或者storeFile还没保存,数据就会丢失。当然在此不考虑Hfiel的可靠新,毕竟这个是由hdfs来保证的,其默认有三份。其实再往细化了看Hfile由很多个块组成,并且有一个固定的结尾块。其中的数据块是由一个Header和多个key-value的键值对组成。在结尾块中包含了数据相关的索引信息,系统也是通过结尾的索引信息找到hfile中的数据。
(2)各组件的容错机制
首先zookeeper就是多节点 的,hmaster也是双主热备,并且当master挂掉,数据的读取仍旧正常,但是region的切分、负载均衡等无法进行而已。regionserver本身多节点,通过心跳机制被监听,如果某个节点出现问题,master会自动将regionserver上的数据重新分配到其他的regionserver上,失效服务器上预写的日志由主服务器进行分割并派送给新的regionserver;
4、hbase的读写流程

上图是,regionserver的数据存储关系图,上文提到,hbase使用memstore和storefile存储对表的更新,数据在更新时候首先写入WAL预写日志也就是Hlog中以及Memstore。memstore在内存中,数据是排序的,当memstore累计到一定阈值时,就会创建一个新的memstore,并且将老的memstore添加到flush队列,由单独的线程flush到磁盘上也就是storefile或者较多hfile。于此通同时,系统会在zookeeper上记录一个checkpoint,表示这个时刻之前的数据变更已经持久化了。当系统出现意外时,可能导致memstore中的数据丢失,此时使用Hlog来恢复数据,就是恢复checkpoint之后的这一段数据。storefile是只读的,一旦创建后就不可以再修改,因此hbase的更新其实是不断地追加操作。当一个store中的storefile达到一定的阈值后,就会进行一次合并操作,将对同一个key的修改合并到一起,形成一个大的storefile。当storefile的大小达到一定的阈值后,又会对storefile进行分割操作,等分为两个storefile,在这个过程当中通过变相的实现了数据的更新操作。
(1)读流程
一、hbase的读操作:
ZooKeeper---root-meta--regionserver--region--memstore--storefile
1、首先从zookerper找到root表,根据root表找到meta表存放信息,进而从meta表获取region的位置,然后读取meta表中的数据。而meta中又存储了用户表的region信息
2、根据namespace、表名和rowkey根据meta表中的数据找到写入数据对于的region信息
3、然后找到对应的regionserver
4、查找对应的region
5、先从Memstore找数据,如果没有,再到StoreFile上读

(2)写流程
ZooKeeper---meta--regionserver--1、Hlog 1、MemStore--storefile
1、首先从zookerper找到meta表的region的位置,然后读取meta表中的数据。而meta中又存储了用户表的region信息
2、根据namespace、表名和rowkey根据meta表中的数据找到写入数据对于的region信息
3、然后找到对于的regionserver
4、把数据分别写到Hlog和memstore各一份
4.1当memstore达到阈值后把数据刷成一个storefile文件,当compact后,逐渐形成越来越大的storefile后触发spilt,
把当前的StoreFile分成两个,这里相当于把一个大的region分割成两个region
4.2若MemStore中的数据有丢失,则可以从HLog上恢复,当多个StoreFile文件达到一定的大小后,会触发Compact合并操作,
合并为一个StoreFile,这里同时进行版本的合并和数据删除

参考博客:
https://www.cnblogs.com/csyuan/p/6543018.html
https://www.cnblogs.com/yfb918/p/10416906.html
5、物理存储
talbe中的所有行是按照rowkey的字典顺序列式存储,table在行的方向上分割为多个region

region按大小分割的,每个表一开始只有一个region,随着数据的不断插入,region不断增大,当增大到一定阀值的时候,region就会等分分割,当tabel中的行不断增多的时候,就会有越来越多的region

hregion是hbase上分布式存储的最小单元。最小单元就是表示不同的region可以分布在不同的regionserver上。但是一个region是不会拆分到多个server上的。

hregion虽然是分布式存储的最小单元,但是并不是存储的最小单元,事实上,hregion由一个或者多个store组成,每个store保存一个columns family,每个store 又由一个memstore和0到多个storefile组成。如下图

hfile的格式为:
Hfile分为六部分:
data block段保存表中的数据,这部分可以被压缩;metablock段保存用户自定义的kv对,也可以被压缩。;file info 段hfile的元信息不被压缩,用户也可以在这一部分添加自己的元信息。Data block index段 data block的索引。每条索引的key是被索引的block的第一条记录的key。metablockindex段 metablock的索引。trailer这段是定长的,保存了每一段的偏移量,读取一个Hfile时首先会读取trailer,trailer保存了每个段的起止位置,然后DataBlockIndex会被读取到内存中,这样,当检索某个key是不需要扫描整个hfile,而只需从内存中找到key所在的block,通过一次磁盘IO将整个block读取到内存中,在找到对应的key。而datablock中基本也是采用压缩方式减少空间占用。trailer -> dataindex -> datablocks。
6、系统架构

client:包含访问hbase的接口,client维护一些cache来加快对hbase的访问,比如region的位置信息
zookeeper:保证hmaster的唯一性,存储所有region的寻址入口root与meta表都存在zookeeper上;监听regionserver的状态信息,存储hbase的schema,包括有哪些table,每个table有哪些columnfamily
master:为regionserver分配region,负责均衡regionserver的负载均衡,监听regionserver发现失效regionserver之后进行region的数据重分配,以及hlog的转移,GFS上的垃圾回收;
regionserver:维护master分配给它的region,处理数据真正的读写操作;负责切分在运行过程中变得过大的region;并且client访问hbase上数据的过程并不需要master参与,寻址访问zookeeper和regionserver,数据读取访问regionserver。master仅仅维护table和region的元数据信息,负载很低。
其中master的作用是协调多个regionserver,监听各个regionserver的状态、平衡负载。为regionserver分配region。可以多个master共存但是需要zookeeper协调分主备,只有主在提供服务。regionserver中包含了多个region,数据的具体读写操作都是在regionserver上进行其中region是分布式存储的最小单位,并且如果多个列族会分为多个region。zookeeper首先是master的HA的保证,负责region与regionserver的注册,zookeeper已经成为分布式大数据框架中容错性的标准框架。
7、region定位
client首先会访问zookeeper里面保存的root表,进而查到meta表信息,meta表里面存放了具体的region的信息。

rootregion永远不会被split也就是说root表只有一个region。开发人员认为其已经够大,这也变相保证三次跳转定位region。meta表中每行保存一个region位置信息,rowkey采用表名+标的最后一样编码而成。为了加快访问,meta表的全部region都保存在内存中。假设meta表的一行在内存中大约占用1kb,并且每个region限制为128M(新版本默认每个region的分裂大小是10G,可手动设置。)那么上面的三层结可以保存的region数目为(128MB/1KB) * (128MB/1KB) = = 2(34)个region;client会将查询过得位置信息缓存起来,缓存信息不回主动失效。因此即使全部失效也是需要6次网络来回就可以定位到region信息(其中三次用来发现缓存失效,另外三次用来获取位置信息)。
8、读写流程整理
上文中提到,hbase使用memstore和storefile存储对表的更新。数据在更新时首先写入Hlog和memstore中,memstore中的数据是培训的,当memstore达到一定阀值时,就会常见一个新的memstore,并且将老的memstore天较大flush队列,有单独的线程flush到磁盘上,成为一个storefile也就是hfile。于此同时,系统会在zookeeper中记录一个redo point,表示这个时刻之前的变化已经更新了。当系统出现意外的时候也只是需要恢复memstore中丢失的那部分数据,也就是介于hfile这个checkpoint之后的与hlog之间差值的数据。并且storefile其实就是hfile是只读的,一旦创建之后就不可以再修改,因此hbase的更细其实是不断追加的操作。当storefile达到一定阀值的时候会进行分裂为两个storefile然后分裂后的storefile达到一定大小之后也会再次进行合并,这个合并的过程中会进行major compact,这个操作会对同一个key的value进行合并到一起,再后面这个新合并的storefile,当大的达到一定大小的时候会再分裂。由于对表的更新时不断追加的,处理读请求时,需要访问store中全部的memstore和storefile,将他们的key按照rewkey合并,由于storefile和memstore都是进行过排序的,并且storefile带有内存中索引,合并过程还是比较快的。
写流程整理
client向regionserver提出写请求,regionserver找到目标region,region检查数据是否与schema一直,如果客户端没有指定版本,则获取当前系统时间作为数据版本,将更新写入hlog,将更新写入memstore,判断memstore的是否需要flush为store文件。
9、其他流程
region分配:任何时刻,一个region只能分配给一个regionserver。master记录了档期啊有哪些可用的regionserver。以及当前哪些region分配给了哪些regionserver,哪些region还没分配。当存在未分配的region,并且有一个regionsever上有可用空间时,master就给这个regionserver发送一个装载请求,把regionserver分配给这个regionserver。regionserver得到请求后就可以对此region提供服务。
regionserver上线:master使用zookeeper来跟踪regionserver状态,当某个regionserver启动时,会首先在zookeeper上的server目录下创建代表自己的文件,并获得该文件的独占锁。由于master订阅了server目录上的变更消息,当server目录下的文件出现新增或者删除操作时,master可以得到来自zookeeper的实时通知。因此一旦regionserver上线,master能马上得到消息。
regionserver下线:当regionserver下线时,他和zookeeper的会话断开,zookeeper而自动释放代表这台server的文件上的独占锁。而master不断轮询server目录下文件的锁状态。如果master发现某个regionserver丢失了它自己的独占锁,或者master连续几次和regionserver通信都无法成功,master就尝试去获取代表这个regionserver的读写锁,一旦成功就可以确定:regionser和zookeeper之间的网络断开了;regionserver挂了的其中一种情况发生,无论哪种,regionserver都无法继续为他的region提供服务了,此时master会删除server目录下代表这台regionserver的文件,并将这台regionserver 的region分配给其他还活着的节点。如果网络短暂出现了断连问题,那么regionserver重新连接到zookeeper之后只要代表它的文件还在他就会不断尝试获取这个文件上的锁,一旦获取到了,就可以继续提供服务。
master上线:master上线从zookeeper上获取唯一一个代码master的锁,用来阻止其他的master成为master。扫描zookeeper上的server目录,获得当前可用的regionserver列表;和2中的每个regionserver通信,获得当前已分配的regionserver和region的对应关系;扫描meta.region的集合,计算得到当前还未分配的region,奖他么放入待分配的region列表。
master下线:由于master 只维护表和region的元数据,而不参与表数据的io的过程,master下线仅导致所有元数据的修改被冻结(无法创建删除表,无法修改表的schema,无法进行region的负载均衡,无法处理region上下线,无法进行region的合并,唯一例外的是region的split可以正常进行,因为只有regionserver参与)表的数据读写还可以正常进行。因此master下线短时间内对整个hbase的集群没有影响。从上线过程中可以看到,master保存的信息全是可以冗余信息(都可以从系统其它地方收集到或者计算出来),因此,一般hbasa集群中总是有一个master在提供服务,还有一个以上的master在等待时机抢占它的位置。
参考链接:
https://www.iteye.com/blog/jiajun-899632
本文深入介绍了HBase的架构原理,包括其分布式、面向列的特性,以及如何通过rowkey、列族和时间戳进行数据存储与检索。文章详细阐述了HBase的高可用性机制,如WAL保障数据完整性和组件的容错设计。此外,还解析了读写流程、物理存储结构及系统架构,帮助读者全面理解HBase的工作机制。


被折叠的 条评论
为什么被折叠?



