发布时间:2025-12-11 00:09:28 浏览次数:13
HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的顶级项目来开发维护,用于支持结构化的数据存储。
HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBASE技术可在廉价PC Server上搭建起大规模结构化存储集群。
HBase的目标是存储并处理大型的数据,更具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。【非大勿用】
HBase是Google Bigtable的开源实现,但是也有很多不同之处。比如:Google Bigtable利用GFS作为其文件存储系统,HBase利用Hadoop HDFS作为其文件存储系统;Google运行MAPREDUCE来处理Bigtable中的海量数据,HBase同样利用Hadoop MapReduce来处理HBase中的海量数据;Google Bigtable利用Chubby作为协同服务,HBase利用Zookeeper作为对应。
简单粗暴的总结:就是一款NoSQL数据库,面向列存储,用于存储处理海量数据。
核心在于它是一个存数据的地方,可是在此之前学习过了HDFS和Mysql,那HBase为什么还会出现呢?
先说一下Mysql,我们都知道Mysql是一个关系型数据库,平时开发使用的非常频繁。一个网站或者系统最核心的表就是用户表,而当用户表的数据达到几千万甚至几亿级别的时候,对单条数据的检索将会耗费数秒甚至分钟级别。实际的清空可能更加复杂不堪。
看下边一张表:
假如根据id=1查询出来这条数据对应的用户姓名,很简单,会给我们返回zhangsan。但是,当我们查的时候,想一下,查名字的时候age和email会不会被查出来?答案是肯定的,Mysql的数据存储是以行为单位的,面向行存储。那问题就出现了,我只需要找出zhangsan的名字,却需要查询一整行的数据,如果列非常多,那么查询效率可想而知了。
查询的操作速度会受到以下两个因素的制约:
表被并发的插入、编辑以及删除操作。
查询语句通常不是简单的对一个表进行操作,有可能是多个表关联后的复杂查询,甚至有可能是group by或者order by操作,此时,性能下降很明显。
如果一张表的列过多,会影响查询效率,我们称这样表为宽表。怎么优化呢,拆开来,竖直拆分:
这样的情况下,我们要查找username的时候只需要查找user_basic表,没有多余的字段,查询效率就会很快。如果一张表的行过多,会影响查询效率,我们将这样的表称之为高表,可以采用水平拆表的方式提高效率:
这种水平拆分应用比较多的 场景就是日志表,日志信息每天产生很多,可以按月进行水平拆分,这样就实现了高表变矮。
ok,这种拆分方式貌似可以解决宽表和高表的问题,但是如果有一天公司的业务变了,比如原来没有微信,现在有了微信,需要加入用户的微信字段。这时候需要改变表的结构信息,该怎么办?最简单的想法是多加一列,像这样:
多考虑一下就知道这样做很不妥帖,比如说有些早期用户没有微信,这一列是设置默认值还是采取其他的做法就得权衡一下。如果需要扩展很多的列出来,而且不是所有的用户都有这些属性,那么拓展起来就更加复杂了。
这时候,想到了JSON格式的字符串,这是一种以字符串的形式表示的对象(将若干可选择填写信息汇总),而且属性字段可以动态拓展,于是有了下边这种做法,两种做法加以对比:
ok,这样存储数据它不挺好的嘛,HBase出来干嘛??Mysql有一点,数据达到一定的阈值(一般是500W),无论怎么优化,它都无法达到高性能的发挥。而大数据领域的数据,动辄PB级,这种存储应用明显是不能很好的满足需求的。针对上边的问题,HBase都有很好的解决方案~~
先不说为什么用,接着上边说到的几个问题:高表宽表,数据列动态扩展,把提到的几个解决办法:水平垂直切分,列扩展方法杂糅在一起。
有这么一张表,怕它又宽又高,又会动态扩展列,那么在设计之初,就把这个表给他拆开,为了列的动态拓展,直接存储JSON格式:
这样就解决了宽表问题,高表怎么办呢?一个表的两部分,各存一部分行:
解决了高表,宽表,动态扩展列的问题,如果还要进一步提高性能怎么办?Mysql->Redis !!! 缓存啊!
查询出来的数据放入到缓存中,下一次查询直接从缓存中拿数据。插入数据怎么办呢?也可以这样理解,我把要插入的数据放进缓存中,再也不用管了,直接由数据库从缓存拿数据插入到数据库。此时程序不需要等待数据插入成功,提高了并行工作的效率。
可是这样做有了很大的风险,服务器宕机的话,缓存中的数据没来得及插入到数据库中,那不就丢数据了嘛。参考Redis的持久化策略,可以给插入数据这个操作添加一个操作日志,用于持久化插入操作,宕机重启后从日志恢复。
这样设计架构就变成了这个样子:
上边这种解决方式,实际上就是HBase实现的大致思路,详细的内容会在后边慢慢说。
简单粗暴总结:HBase就是一个面向列存储的非关系型数据库。两者的区别主要是:
HBase是的存储时基于HDFS的,HDFS有着高容错性的特点,被设计用来部署在低廉的硬件上,而且它提供高吞吐量以访问应用程序的数据,基于Hadoop意味着HBase与生俱来的超强的扩展性和吞吐量。
HBase采用的时key/value的存储方式,这意味着,即使随着数据量的增大,也几乎不会导致查询性能的下降。HBase又是一个面向列存储的数据库,当表的字段很多时,可以把其中几个字段独立出来放在一部分机器上,而另外几个字段放到另一部分机器上,充分分散了负载的压力。如此复杂的存储结构和分布式的存储方式,带来的代价就是:即便是存储很少的数据,也不会很快。
HBase并不是足够快,而是数据量很大的时候它慢的不明显。什么时候使用HBase呢,主要是以下两种情况:
单表数据量超过千万,而且并发量很大;
数据分析需求较弱,或者不需要那么实时灵活。
官方网站:http://hbase.apache.org
HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Apache的顶级项目来开发维护,用于支持结构化的数据存储。
海量存储
Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。这与Hbase的极易扩展**息相关。正是因为Hbase良好的扩展性,才为海量数据的存储提供了便利。
列式存储
这里的列式存储其实说的是
列族存储,Hbase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。
极易扩展
Hbase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。
通过横向添加RegionSever的机器,进行水平扩展,提升Hbase上层的处理能力,提升Hbsae服务更多Region的能力。
备注:RegionServer的作用是管理region、承接业务的访问,这个后面会详细的介绍通过横向添加Datanode的机器,进行存储层扩容,提升Hbase的数据存储能力和提升后端存储的读写能力。
高并发
由于目前大部分使用Hbase的架构,都是采用的廉价PC,因此单个IO的延迟其实并不小,一般在几十到上百ms之间。这里说的高并发,主要是在并发的情况下,Hbase的单个IO延迟下降并不多。能获得高并发、低延迟的服务。
稀疏
稀疏主要是针对Hbase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。
在宏观架构图的最后一个RegionServer中可以看到 ,它的内部是多个Region的集合:
现在我们放大一下这个RegionServer的内部架构:
一个WAL:
跟HDFS中的edits文件存在的意义一样
WAL时
Write-Ahead Log的缩写,翻译为预写入日志。从名字大概也能猜出它的作用,当操作到达Region的时候,HBase先把操作写入到WAL中,然后把数据放入到基于内存实现的MemStore中,等到一定的时机再把数据刷写形成HFile文件,存储到HDFS上。WAL是一个保险机制,数据在写到MemStore之前,先写到WAL中,这样如果在刷写过程中出现事故,可以从WAL恢复数据。
多个Region:
Region已经多次提到了,它就时是数据库的一部分,每一个Region都有起始的rowkey和结束的rowkey,代表了它存储的row的范围。
我们再放大Region的内部结构:
从图中可以看的出来,一个Region包含 多个Store:一个Region有多个Store,一个Store就是对应一个列族的数据,如图就有三个列族。再从最后一个Store中我们又可以看出,Store是由MemStore和HFile组成的。
预写入日志就是设计来解决宕机之后的操作恢复问题的,WAL是保存在HDFS上的持久化文件。数据到达Region的时候,先写入WAL,然后被加载到MemStore中。这样就算Region宕机了,操作没来得及执行持久化,也可以再重启的时候从WAL加载操作并执行。
如何启用WAL?
WAL是默认开启的,也可以手动关闭它,这样增删改操作会快一点。但是这样做牺牲的是数据的安全性,所以不建议关闭。
关闭方法:
Mutation.setDurability(Durability.SKIP_WAL)
异步写入WAL
如果不惜通过关闭WAL来提高性能的话,还可以考虑一下折中的方案:异步写入WAL。
正常情况下,客户端提交的put、delete、append操作来到Region的时候,先调用HDFS的客户端写到WAL中。哪怕只有一个改动,也会调用HDFS的接口来写入数据。可以想象到,这种方式尽可能的保证了数据的安全性,代价这种方式频繁的消耗资源。
如果不想关闭WAL,又不想每次都耗费那么大的资源,每次改动都调用HDFS客户端,可以选择异步的方式写入WAL:
Mutation.setDurability(Durability.ASYNC_WAL)
这样设定以后,Region会等到条件满足的时候才将操作写到WAL。这里的条件指的是间隔多久,写一次,默认的时间间隔是1s。
如果异步写入数据的时候出错了怎么办呢?比如客户端的操作现在在Region内存中,由于时间间隔未到1s,操作还没来得及写入到WAL,Region挂了(邪门不?就差那么一丢丢不到1s)。出错了是没有任何事务可以保证的。
WAL滚动
之前学习过MapReduce的shuffle机制,所以猜得到WAL是一个唤醒的滚动日志数据结构,因为这种结构不会导致占用的空间持续变大,而且写入效率也最高。
通过wal日志切换,这样可以避免产生单独的过大的wal日志文件,这样可以方便后续的日志清理(可以将过期日志文件直接删除)另外如果需要使用日志进行恢复时,也可以同时解析多个小的日志文件,缩短恢复所需时间。
WAL的检查间隔由hbase.regionserver.logroll.period定义,默认值是一个小时。检查的内容是把当前WAL中的操作跟实际持久化到HDFS上的操作做比较,看哪些操作已经被持久化了,如果已经被持久化了,该WAL就会被移动到HDFS上的.oldlogs文件夹下。
一个WAL实例包含多个WAL文件。WAL文件的最大数量可以手动通过参数配置。
其它的触发滚动的条件是:
WAL的大小超过了一定的阈值。
WAL文件所在的HDFS文件块快要满了。
WAL归档和删除
归档:WAL创建出来的文件都会放在/hbase/.log下,在WAL文件被定为归档时,文件会被移动到/hbase/.oldlogs下
删除:判断:是否此WAL文件不再需要,是否没有被其他引用指向这个WAL文件
会引用此文件的服务:
TTL进程:该进程会保证WAL文件一直存活直到达到hbase.master.logcleaner.ttl定义的超时时间(默认10分钟)为止。
备份(replication)机制:如果你开启了HBase的备份机制,那么HBase要保证备份集群已经完全不需要这个WAL文件了,才会删除这个WAL文件。这里提到的replication不是文件的备份数,而是0.90版本加入的特性,这个特性用于把一个集群的数据实时备份到另外一个集群。如果你的手头就一个集群,可以不用考虑这个因素。
只有当该WAL文件没有被以上两种情况引用的时候,才会被系统彻底清除掉
解释完了WAL,放大一下Store的内部架构:
Store有两个重要的部分:
MemStore:
每个Store都有一个MemStore实例。数据写入到WAL之后就会被放入MemStore中。MemStore是内存的存储对象,只有到达一定的时机才会被刷写到HFile中去。
HFile:
在Store中有多个HFile,每次刷写都会形成一个HFile文件落盘在HDFS上。HFile直接跟HDFS打交道,它是数据存储的实体。
这里提出一点疑问:
客户端的操作到达Region时,先将数据写到WAL中,而WAL是存储在HDFS上的。所以就相当于数据已经持久化了,那么为什么还要从WAL加载到MemStore中,再刷写形成HFile存到HDFS上呢?
简单的说就是:数据进入HFile之前就已经被持久化了,为什么还要放入MemStore?
这是因为HDFS支持文件的创建、追加、删除,但是不能修改。对于一个数据库来说,数据的顺序是非常重要的。第一次WAL的持久化是为了保证数据的安全性,无序的。再读取到MemStore中,是为了排序后存储。所以MemStore的意义在于维持数据按照rowkey的字典序排列,而不是做一个缓存提高写入效率。
补一张图,对比着来看,关于MemStore刷写:
从图中可以看出Hbase是由Client、Zookeeper、Master、HRegionServer、HDFS等几个组件组成,并且如果做DML的操作是不需要关心HMaster的,只需要从ZK中获得必备meta数据地址,然后从RegionServer中增删查数据即可。下面来介绍一下几个组件的相关功能:
Client
Client包含了访问Hbase的接口,另外Client还维护了对应的cache来加速Hbase的访问,比如cache的.META.元数据的信息。
Zookeeper
HBase通过Zookeeper来做master的
高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。具体工作如下:
通过Zoopkeeper来保证集群中只有1个master在运行,如果master异常,会通过竞争机制产生新的master提供服务
通过Zoopkeeper来监控RegionServer的状态,当RegionSevrer有异常的时候,通过回调的形式通知MasterRegionServer上下线的信息
通过Zoopkeeper存储元数据的统一入口地址
Hmaster
master节点的主要职责如下:
为RegionServer分配Region
维护整个集群的负载均衡
维护集群的元数据信息
发现失效的Region,并将失效的Region分配到正常的RegionServer上
当RegionSever失效的时候,协调对应Hlog的拆分
HregionServer
HregionServer直接对接用户的读写请求,是真正的干活的节点。它的功能概括如下:
管理master为其分配的Region
处理来自客户端的读写请求
负责和底层HDFS的交互,存储数据到HDFS
负责Region变大以后的拆分
负责Storefile的合并工作
HDFS
HDFS为Hbase提供最终的底层数据存储服务,HBase底层用HFile格式(跟hadoop底层的数据存储格式类似)将数据存储到HDFS中,同时为HBase提供高可用(Hlog存储在HDFS)的支持,具体功能概括如下:
提供元数据和表数据的底层分布式存储服务
数据多副本,保证的高可靠和高可用性
“Hbase是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注本站网站,小编将为大家输出更多高质量的实用文章!