1、Hbase是什么
2、Hbase架构
3、Hbase数据模型
4、Hbase和hive的区别
5、Hbase特点
6、数据同样存在HDFS,为什么HBase支持在线查询,且效率比Hive快很多
7、Hbase适用场景
8、RowKey的设计原则
9、HBase中scan和get的功能以及实现的异同?
10、Scan的setCache和setBatch
11、HBase 写流程
12、HBase 读流程
13、HBase中Zookeeper的作用
14、StoreFile(HFile)合并
15、Hbase协处理器
16、WAL机制
17、Memstore
18、BloomFilter
19、BlockCache读缓存
20、Region拆分
21、Region合并
22、Region 负载均衡
23、Region预分区
24、一张表中定义多少个 Column Family 最合适
25、为什么不建议在 HBase 中使用过多的列族
26、直接将时间戳作为行健,在写入单个region时会发生热点问题,为什么
27、HBase中region太小和region太大的影响
28、每天百亿数据如何写入Hbase
29、HBase集群安装注意事项?
30、Hbase数据热点问题
31、HBase宕机恢复流程
32、HBase性能优化
Hbase架构图:
Zookeeper: Master 的高可用、RegionServer 的监控、元数据的入口以及集群配置的维护等
HDFS: 提供底层数据支撑
Master
RegionServer
Region: 实际存储数据,HBase表会根据RowKey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region
Hlog: 预写日志,用于记录HBase的修改记录,写数据时,数据会首先写入内存经MemStore排序后才能刷写到StoreFile,有可能引起数据丢失,为了解决这个问题,数据会先写入Hlog,然后再写入内存。在系统故障时,数据可以Hlog重建。
Store: StoreFile存储在Store中,一个Store对应HBase表中的一个列族。
MemStore: 写缓存,由于StoreFile中的数据要求是有序的,所以数据是先存储在MemStore中,排好序后,等到达刷写时机才会刷写到StoreFile,每次刷写都会形成一个新的StoreFile。StoreFile过多会影响性能,此时可进行compact操作
StoreFile: 这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。StoreFile是以Hfile的形式存储在HDFS的。每个 Store 会有一个或多个StoreFile,数据在每个 StoreFile 中都是有序的(按照Rowkey的字典顺序排序)。
数据模型图:
物理模型图:
类似于关系型数据库的 DatabBase 概念,每个命名空间下有多个表。HBase有两个自带的命名空间,分别是 hbase 和 default,hbase 中存放的是 HBase 内置的表,default 表是用户默认使用的命名空间。
HBase 表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要。
HBase 表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要。
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,其值为写入 HBase 的时间。
HBase 中通过 row 和 columns 确定的为一个存贮单元称为 cell。由{rowkey, 列族:列, time Stamp} 唯一确定的单元。cell 中的数据是没有类型的,全部是字节码形式存贮(byte[]数组)。
Hbase和Hive在大数据架构中处在不同位置,Hbase主要解决实时数据查询问题,Hive主要解决海量数据处理和计算问题,一般是配合使用。
Hbase:Hadoop database 的简称,也就是基于Hadoop数据库,是一种NoSQL数据库,主要适用于海量明细数据(十亿、百亿)的随机实时查询,如日志明细、交易清单、轨迹行为等。
Hive:Hive是Hadoop数据仓库,严格来说,不是数据库,主要是让开发人员能够通过SQL来计算和处理HDFS上的结构化数据,适用于离线的批量数据计算。
rowkey在设计上保证其唯一性。rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。
rowkey是一个二进制码流,可以是任意字符串,最大长度 64kb ,实际应用中一般为10-100bytes,以byte[] 形式保存,一般设计成定长。建议越短越好,不要超过16个字节,原因如下:数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。目前操作系统都是64位系统,内存8字节对齐,控制在16个字节,8字节的整数倍利用了操作系统的最佳特性。
如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。
rowkey是按照字典序存储,设计rowkey时可以将经常一起读取的数据rowkey相邻,在物理存储时可以落在同一个region中,避免读写多个Region。
scan 方法:按指定的条件获取一批记录
get方法:按指定RowKey 获取唯一一条记录。Get 的方法处理分两种:
在HBase中,每当memstore的数据flush到磁盘后,就形成一个storefile,当storefile的数量越来越大时,会严重影响HBase的读性能 ,HBase内部的compact处理流程是为了解决MemStore Flush之后,storefile数太多,导致读数据性能大大下降的一种自我调节手段,它会将文件按照策略进行合并,提升HBase的数据读性能。
HBase中实现了两种compaction的方式:
Minor操作只用来做部分文件的合并操作以及超过生存时间TTL的数据,删除标记数据、多版本数据不进行清除。
触发条件:
把所有的文件都遍历一遍之后每一个文件都去考虑。符合条件而进入待合并列表的文件由新的条件判断:该文件 < (所有文件大小总和 - 该文件大小) * hbase.store.compaction.ratio比例因子。
Major操作是对Region下的Store下的所有StoreFile执行合并操作,顺序重写全部数据,重写过程中会略过做了删除标记的数据,最终合并出一个HFile文件,并将原来的小文件删除。会占用大量IO资源。
触发条件:
Major是Minor升级而来的。如果本次Minor Compaction包含所有文件,且达到了足够的时间间隔,则会被升级为Major Compaction。判断时间间隔根据以下两个配置项:
hbase.hregion.majorcompaction:major Compaction发生的周期,单位是毫秒,默认值是7天。
hbase.hregion.majorcompaction.jitter majorCompaction:周期抖动参数,0~1.0的一个指数。调整这个参数可以让Major Compaction的发生时间更灵活,默认值是0.5。
虽然有以上机制控制Major Compaction的发生时机,但是由于Major Compaction时对系统的压力还是很大的,所以建议关闭自动Major Compaction,采用手动触发的方式。
合并流程
Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和、计数、排序等操作。比如,在0.92版本前,统计总行数需要使用Counter方法,执行一次MapReduce Job才能得到。虽然 HBase 在数据存储层中集成 了 MapReduce,能够有效用于数据表的分布式计算。然而在很多情况下,做一些简单的相加或者聚合计算的时候,如果直接将计算过程放置在regionServer端,能够减少通讯开销,从而获得很好的性能提升。于是,HBase在0.92之后引入了协处理器(coprocessors),能够轻易建立二次索引、复杂过滤器、求和、计数以及访问控制等。协处理器包括observer和endpoint
类似于传统数据库中的触发器,当数据写入的时候会调用此类协处理器中的逻辑。主要的作用是当执行被监听的一个操作的时候,可以触发另一个我们需要的操作,比如说监听数据库数据的增删过程,我们可以在hbase数据库插入数据或者删除数据之前或之后进行一系列的操作。二级索引基于此触发器构建。
类似传统数据库中的存储过程,客户端可以调用Endpoint执行一段 Server 端代码,并将 Server 端代码的结果返回给客户端进一步处理,常用于Hbase的聚合操作。min、max、avg、sum、distinct、group by
协处理器的加载方式有两种,我们称之为静态加载方式(Static Load)和动态加载方式 (Dynamic Load)。静态加载的协处理器称之为 System Coprocessor,动态加载的协处理器称 之为 Table Coprocessor
静态加载:通过修改 hbase-site.xml 这个文件来实现,启动全局 aggregation,能过操纵所有的表上的数据。只需要添加如下代码:
<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>
为所有 table 加载了一个 cp class,可以用”,”分割加载多个 class注意: 该方法因为是全局的,所以在实际应用中并不是很多,而另一种方法用的会更多一些
动态加载启用表 aggregation,只对特定的表生效。通过 HBase Shell 来实现。
①disable 指定表。hbase> disable ‘table名’;
②添加 aggregation
hbase> alter 'mytable', METHOD => 'table_att','coprocessor'=>
'|org.apache.Hadoop.hbase.coprocessor.AggregateImplementation||'
③重启指定表 hbase> enable ‘table名’
数据在写入HBase的时候,先写WAL,再写入缓存。通常情况下写缓存延迟很低,WAL机制一方面是为了确保数据即使写入缓存后数据丢失也可以通过WAL恢复,另一方面是为了集群之间的复制。默认WAL机制是开启的,并且使用的是同步机制写WAL。
如果业务不特别关心异常情况下部分数据的丢失,而更关心数据写入吞吐量,可考虑关闭WAL写,这样可以提升2~3倍数据写入的吞吐量。
如果业务不能接受不写WAL,但是可以接受WAL异步写入,这样可以带了1~2倍性能提升。
HBase中可以通过设置WAL的持久化等级决定是否开启WAL机制、以及HLog的落盘方式。
WAL的持久化等级分为如下四个等级:
除了在创建表的时候直接设置WAL存储级别,也可以通过客户端设置WAL持久化等级,代码:put.setDurability(Durability.SYNC_WAL);
hbase为了保证随机读取的性能,所以storefile的数据按照rowkey的字典序存储。当客户端的请求在到达regionserver之后,为了保证写入rowkey的有序性,不能将数据立刻写入到hfile中,而是将每个变更操作保存在内存中,也就是memstore中。memstore能够保证内部数据有序。当某个memstore达到阈值后,会将Region的所有memstore都flush到hfile中(Flush操作为Region级别),这样能充分利用hadoop写入大文件的性能优势,提高写入性能。
由于memstore是存放在内存中,如果regionserver宕机,会导致内存中数据丢失。所有为了保证数据不丢失,hbase将更新操作在写入memstore之前会写入到一个WAL中。WAL文件是追加、顺序写入的,WAL每个regionserver只有一个,同一个regionserver上所有region写入同一个的WAL文件。这样当某个regionserver失败时,可以通过WAL文件,将所有的操作顺序重新加载到memstore中。
如果一个 HRegion 中 MemStore 过多(Column family 设置过多),每次 flush 的开销必然会很大,并且生成大量的 HFile 影响后续的各项操作,因此建议在进行表设计的时候尽量减少 Column family 的个数。
用户可以通过shell命令分别对一个 Table 或者一个 Region 进行 flush:
hbase> flush 'TABLENAME'
hbase> flush 'REGIONNAME'
hbase.hregion.memstore.flush.size
默认值:128M MemStore 最大尺寸,当 Region 中任意一个 MemStore 的大小(压缩后的大小)达到了设定值,会触发 MemStore flush。
hbase.hregion.memstore.block.multiplier
默认值:2 Region 级别限制,当 Region 中所有 MemStore 的大小总和达到了设定值(hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size,默认 2* 128M = 256M),会触发 MemStore flush。
hbase.regionserver.global.memstore.upperLimit
默认值:0.4 Region Server 级别限制,当一个 Region Server 中所有 MemStore 的大小总和达到了设定值(hbase.regionserver.global.memstore.upperLimit * hbase_heapsize,默认 0.4 * RS堆内存大小),会触发Region Server级别的MemStore flush。
hbase.regionserver.global.memstore.lowerLimit
默认值:0.38 与 hbase.regionserver.global.memstore.upperLimit 类似,区别是:当一个 Region Server 中所有 MemStore 的大小总和达到了设定值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize,默认 0.38 * RS堆内存大小),会触发部分 MemStore flush。
Flush 顺序是按照 Region 的总 MemStore 大小,由大到小执行,先操作 MemStore 最大的 Region,再操作剩余中最大的 Region,直至总体 MemStore 的内存使用量低于设定值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize)。
hbase.regionserver.maxlogs
默认值:32 当一个 Region Server 中 HLog 数量达到设定值,系统会选取最早的一个 HLog 对应的一个或多个 Region 进行 flush。
当增加 MemStore 的大小以及调整其他的 MemStore 的设置项时,也需要去调整 HLog 的配置项。否则,WAL的大小限制可能会首先被触发。因而,将利用不到其他专门为Memstore而设计的优化。
需要关注的 HLog 配置是 HLog 文件大小,由参数 hbase.regionserver.hlog.blocksize 设置(默认512M),HLog 大小达到上限,或生成一个新的 HLog
通过WAL限制来触发Memstore的flush并非最佳方式,这样做可能会会一次flush很多Region,尽管“写数据”是很好的分布于整个集群,进而很有可能会引发flush“大风暴”。
hbase.regionserver.optionalcacheflushinterval
默认值:3600000 HBase 定期刷新 MemStore,默认周期为1小时,确保 MemStore 不会长时间没有持久化。为避免所有的 MemStore 在同一时间都进行 flush,定期的 flush 操作有 20000 左右的随机延时。
为了减少 flush 过程对读写的影响,HBase 采用了类似于两阶段提交的方式,将整个 flush 过程分为三个阶段:
布隆过滤器是hbase中的高级功能,它能够减少特定访问模式(get/scan)下的查询时间。不过由于这种模式增加了内存和存储的负担,所以被默认为关闭状态。
hbase支持如下类型的布隆过滤器:
如果用户随机查找一个rowkey,位于某个region中两个开始rowkey之间的位置。对于hbase来说,它判断这个行键是否真实存在的唯一方法就是加载这个region,并且扫描它是否包含这个键。当我们get数据时,hbase会加载很多块文件。
采用布隆过滤器后,它能够准确判断该StoreFile的所有数据块中,是否含有我们查询的数据,从而减少不必要的块加载,增加hbase集群的吞吐率。
1、布隆过滤器的存储在哪
开启布隆后,HBase会在生成StoreFile时包含一份布隆过滤器结构的数据,称其为MetaBlock;MetaBlock与DataBlock(真实的KeyValue数据)一起由LRUBlockCache维护。所以,开启bloomfilter会有一定的存储及内存cache开销。大多数情况下,这些负担相对于布隆过滤器带来的好处是可以接受的。
2、采用布隆过滤器后,如何get数据
在读取数据时,hbase会首先在布隆过滤器中查询,根据布隆过滤器的结果,再在MemStore中查询,最后再在对应的HFile中查询。
3、采用ROW还是ROWCOL
一个RegionServer只有一个BlockCache。用来优化读取性能,不是数据存储的必须组成部分。
BlockCache名称中的Block指的是HBase的Block。BlockCache的工作原理跟其他缓存一样:读请求到HBase之后先尝试查询BlockCache,如果获取不到就去StoreFile和 Memstore中去获取。如果获取到了则在返回数据的同时把Block块缓存到BlockCache中。BlockCache默认是开启的。BlockCache的实现方案有以下几种:
近期最少使用算法。读出来的block会被放到BlockCache中待 下次查询使用。当缓存满了的时候,会根据LRU的算法来淘汰block。
这是一种堆外内存的解决方案。不属于JVM管理的内存范围,说白了,就是原始的内存区域了。回收堆外内存的时候JVM几乎不会停顿,可以避免GC过程中遇见的系统卡顿与异常。
BucketCache借鉴SlabCache也用上了堆外内存。不过它以下自己的特点:
把不同类型的Block分别放到 LRUCache和BucketCache中。Index Block和Bloom Block会被放到LRUCache中。Data Block被直接放到BucketCache中,所以数据会去LRUCache查询一下,然后再去 BucketCache中查询真正的数据。其实这种实现是一种更合理的二级缓存,数据从一级缓存到二级缓存最后到硬盘,从小到大,存储介质也由快到慢。考虑到成本和性能的组合,比较合理的介质是:LRUCache使用内存->BuckectCache使用SSD->HFile使用机械硬盘。
在开启此功能后,数据块会以它们on-disk的形式缓存到BlockCache。与默认的模式不同点在于:默认情况下,在缓存一个数据块时,会先解压缩然后存入缓存。而lazy BlockCache decompression 直接将压缩的数据块存入缓存。
如果一个RegionServer存储的数据过多,无法适当的将大部分数据放入缓存,则开启这个功能后,可以提升50%的吞吐量,30%的平均延迟上升,增加80%垃圾回收,以及2%的整体CPU负载。
压缩默认关闭,若要开启,可以在hbase-site.xml文件里设置 hbase.block.data.cachecompressed 为 true
一个Region就是一个表的一段Rowkey的数据集合。一旦 Region 的负载过大或者超过阈值时,它就会被分裂成两个新的 Region。Region的拆分分为自动拆分和手动拆分。自动拆分可以采用不同的策略。
在这里插入图片描述
这个过程是由 RegionServer 完成的,其拆分流程如下。
Region的自动拆分主要根据拆分策略进行,主要有以下几种拆分策略:
调用hbase shell的 split方法,split的调用方式如下:
split 'regionName' # format: 'tableName,startKey,id'
比如:
split 'test_table1,c,1476406588669.96dd8c68396fda69'
这个就是把test_table1,c,1476406588669.96dd8c68396fda69这个 Region从新的拆分点999处拆成2个Region。
如果有很多Region,则MemStore也过多,数据频繁从内存Flush到HFile,影响用户请求,可能阻塞该Region服务器上的更新操作。过多的 Region 会增加服务器资源的负担。当删了大量的数据,或Region拆分过程中产生了过多小Region,这时可以Region合并,减轻RegionServer资源负担。
合并通过使用org.apache.hadoop.hbase.util.Merge类来实现。例如把以下两个Region合并:
test_table1,b,1476406588669.39eecae03539ba0a63264c24130c2cb1.
test_table1,c,1476406588669.96dd8c68396fda694ab9b0423a60a4d9.
就需要在Linux下(不需要进入hbase shell)执行以下命令:
hbase org.apache.hadoop.hbase.util.Merge test_table1
test_table1,b,1476406588669.39eecae03539ba0a63264c24130c2cb1.
test_table1,c,1476406588669.96dd8c68396fda694ab9b0423a60a4d9.
此方式需要停止整个Hbase集群,所以后来又增加了online_merge(热合并)。
hbase shell提供了一个命令叫online_merge,通过这个方法可以进行热合并,无需停止整个Hbase集群。
假设要合并以下两个Region:
test_table1,a,1476406588669.d1f84781ec2b93224528cbb79107ce12.
test_table1,b,1476408648520.d129fb5306f604b850ee4dc7aa2eed36.
online_merge的传参是Region的hash值。只需在hbase shell 中执行以下命令:
merge_region
'd1f84781ec2b93224528cbb79107ce12', 'd129fb5306f604b850ee4dc7aa2eed36'
当 Region 分裂之后,Region 服务器之间的 Region 数量差距变大时,Master 便会执行负载均衡来调整部分 Region 的位置,使每个 Region 服务器的 Region 数量保持在合理范围之内,负载均衡会引起 Region 的重新定位,使涉及的 Region 不具备数据本地性。
Region 的负载均衡由 Master 来完成,Master 有一个内置的负载均衡器,在默认情况下,均衡器每 5 分钟运行一次,用户可以配置。负载均衡操作分为两步进行:首先生成负载均衡计划表, 然后按照计划表执行 Region 的分配。
执行负载均衡前要明确,在以下几种情况时,Master 是不会执行负载均衡的。
Master 内部使用一套集群负载评分的算法,来评估 HBase 某一个表的 Region 是否需要进行重新分配。这套算法分别从 Region 服务器中 Region 的数目、表的 Region 数、MenStore 大小、 StoreFile 大小、数据本地性等几个维度来对集群进行评分,评分越低代表集群的负载越合理。
确定需要负载均衡后,再根据不同策略选择 Region 进行分配,负载均衡策略有三种,如下表所示。
策略 | 原理 |
---|---|
RandomRegionPicker | 随机选出两个 Region 服务器下的 Region 进行交换 |
LoadPicker | 获取 Region 数目最多或最少的两个 Region 服务器,使两个 Region 服务器最终的 Region 数目更加平均 |
LocalityBasedPicker | 选择本地性最强的 Region |
根据上述策略选择分配 Region 后再继续对整个表的所有 Region 进行评分,如果依然未达到标准,循环执行上述操作直至整个集群达到负载均衡的状态。
Hbase建表时默认单region,所有数据都会写入此region,超过阈值(hbase.Region.max.filesize,默认10G)会此region会进行拆分,分成2个region。在此过程中,会产生三个问题:
基于此我们可以在建表时进行预分区,创建多个空region,减少由于split带来的资源消耗,从而提高HBase的性能。预分区时会确定每个region的起始和终止rowky,rowkey设计时确保均匀的命中各个region,就不会存在写热点问题。当然随着数据量的不断增长,该split的还是要进行split。
Column Family划分标准一般根据数据访问频度,如一张表里有些列访问相对频繁,而另一些列访问很少,这时可以把这张表划分成两个列族,分开存储,提高访问效率。
HBase 中每张表的列族个数建议设在1~3之间,列族数过多可能会产生以下影响:
对Flush的影响在 HBase 中,数据首先写入memStore 的,每个列族都对应一个store,store中包含一个MemStore。列族过多将会导致内存中存在越多的MemStore;而MemStore在达到阈值后会进行Flush操作在磁盘生产一个hFile文件。列族越多导致HFile越多。
由于Flush操作是Region 级别的,即Region中某个MemStore被Flush,同一个Region的其他MemStore也会进行Flush操作。当列族之间数据不均匀,比如一个列族有100W行,一个列族只有10行,会产生很多很多小文件,而且每次 Flush 操作也涉及到一定的 IO 操作。 此外列族数过多可能会触发RegionServer级别的Flush操作;这将会阻塞RegionServer上的更新操作,且时间可能会达到分钟级别。
对Split的影响当HBase表中某个Region过大会触发split拆分操作。如果有多个列族,且列族间数据量相差较大,这样在Region Spli时会导致原本数据量很小的HFil文件进一步被拆分,从而产生更多的小文件。
对 Compaction 的影响目前HBase的Compaction操作也是Region级别的,过多的列族且列族间数据量相差较大,也会产生不必要的 IO。
对HDFS的影响HDFS 其实对一个目录下的文件数有限制的。列族数过多,文件数可能会超出HDFS的限制。小文件问题也同样会出现。
对RegionServer内存的影响一个列族在RegionServer中对应于一个 MemStore。每个MemStore默认占用128MB的buffer。如果列族过多,MemStore会占用RegionServer大量内存。
region 中的 rowkey 是有序存储,若时间比较集中。就会存储到一个 region 中,这样一个 region 的数据变多,其它的 region 数据很少,加载数据就会很慢,直到 region 分裂,此问题才会得到缓解。
hbase.hregion.max.filesize:此参数定义了单个region的最大数据量。
hbase数据会首先写入MemStore,超过配置后会flush到磁盘成为StoreFile,当StoreFile的数量超过配置之后,会启动compaction,将他们合并为一个大的StoreFile。
当合并后的Store大于max.filesize时,会触发分隔动作,将它切分为两个region。hbase.hregion.max.filesize不宜过大或过小,经过实战, 生产高并发运行下,最佳大小5-10GB!
推荐关闭某些重要场景的hbase表的major_compact!在非高峰期的时候再去调用major_compact,这样可以减少split的同时,显著提供集群的性能,吞吐量、非常有用。
解决思路:
一、出现热点问题原因
二、如何解决热点问题
宕机分为 Master 宕机和 regionServer 宕机
1、Master主要负责实现集群的负载均衡和读写调度,没有单点问题,所以集群中可以存在多个Master节点。2、通过热备方式实现Master高可用,并在zookeeper上进行注册 3、active master会接管整个系统的元数据管理任务,zk以及meta表中的元数据,相应用户的管理指令,创建、删除、修改,merge region等
集群中一台RegionServer宕机并不会导致已经写入的数据丢失,HBase采用WAL机制保证,即使意外宕机导致Memstore缓存数据没有落盘,也可以通过HLog日志恢复。RegionServer宕机一定程度上会影响业务方的读写请求,因为zookeeper感知到RegionServer宕机事件是需要一定时间的,这段时间默认会有3min。
引起RegionServer宕机的原因各种各样,Full GC、网络异常、官方Bug导致(close wait端口未关闭)等。
一旦RegionServer发生宕机,Zookeeper感知后会通知Master,Master首先会将这台RegionServer上所有Region移到其他RegionServer上,再将HLog分发给其他RegionServer进行回放,完成之后再修改路由,业务方的读写才会恢复正常。整个过程都是自动完成的,并不需要人工介入。
宕机原因1、Full Gc引起长时间停顿超过心跳时间 2、HBase对Jvm堆内存管理不善,未合理使用堆外内存 3、Jvm启动参数配置不合理 4、业务写入或吞吐量太大 5、网络异常导致超时或RegionServer断开集群连接
宕机检测通过Zookeeper实现, 正常情况下RegionServer会周期性向Zookeeper发送心跳,一旦发生宕机,心跳就会停止,超过一定时间(SessionTimeout)Zookeeper就会认为RegionServer宕机离线,并将该消息通知给Master。
具体流程
Hbase基于HDFS存储,首先需要进行HDFS的相关优化。优化内容详见《大数据面试题整理-HDFS篇》
HTable.setWriteBufferSize(writeBufferSize); // 设置缓存大小
HTable.setAutoFlush(false);//关闭自动提交