hbase的高可用

什么是hbase的高可用?
指的是:让master节点能够有多个,当节点宕机后,能够有备份的节点顶的上来,此时认为master形成了高可用状态

如何实现hbase的主节点的高可用呢?环境为VMware 三台虚拟机

  1. 在hbase的conf目录下,创建backup-master文件,并添加如下内容:
node1中执行:
	cd /export/server/hbase-2.1.0/conf/
	vim backup-masters
内容如下:
	node2.itcast.cn
	node3.itcast.cn
  1. 将这个文件发送到node2和node3中
node1执行:
	cd /export/server/hbase-2.1.0/conf/
	scp backup-masters node2:$PWD
	scp backup-masters node3:$PWD
  1. 启动hbase:
3.1) 先启动zookeeper
3.2) 接着启动 hadoop集群
3.3) 启动hbase
  1. 启动后, 可以将主节点进行宕机, 然后检测其他的节点是否升级为主节点操作, 如果可以, 说明高可用配置成功了
思考: 为什么第一次启动 每一次都node1成为主节点呢? 
	在启动过程中, node1往往是第一个先启动, 导致具有抢先权限, 导致node1往往是主节点

hbase的集群架构

hbase的高可用 hbase高可用原理_读取数据


hbase的高可用 hbase高可用原理_hbase_02

Hbase的原理

hbase的读取流程

hbase的高可用 hbase高可用原理_读取数据_03


读取数据的流程:(注:防手机端看不清图片文字)

1. 客户端发起读取数据的请求,首先会连接zookeeper
2. 从zookeeper中获取hbase:meta表 被那个regionServer所管理着   
	(hbase:meta表Lhbase的元数据表,此表中主要适用于存储用户创建的表元数据信息,
		包含有哪些表,每个表有哪些region,每个region被那些regionServer所管理,以及每个
		region详细的信息数据。    如果执行get操作,只能返回一个regionServer地址,如果执行
		scan操作,将这个表对应的所有regionServer地址返回)
3.  连接meta表对应regionServer,从meta表中获取当前读取的这个表对应的region被哪个regionServer所管理
4. 连接对应的regionServer,开始读取数据
5. 首先现行memstore--》blockCache(块缓存)--》storeFile --》大Hfile   
	注:如果执行scan扫描操作,块缓则没有实际意义

数据的写入流程

hbase的高可用 hbase高可用原理_读取数据_04


写入数据的流程:(注:防手机端看不清图片文字)

1. 客户端发起写入数据的请求,首先会连接zookeeper
2. 从zookeeper中获取hbase:meta表被哪个regionServer所管理着
3. 连接meta表对应的regionServer,从meta表获取当前要写入的表对应的region已经regionServer地址是什么
	(只能返回一个regionServer地址)
4. 连接对应要写入数据的regionServer,开始进行数据的写入操作,将数据会写入到这个regionServer的Hlog和
	对应的memStore(数据量大的话会有多个)中,当这两个位置都写入成功后,客户端就会认为数据写入完成
-------以上操作是hbade客户端写入流程------------
异步流程:
5. 随着客户端不断的写入数据,memStore中数据会越来越多,当memStore中到达一定阈值(128M / 1h)后,
	就会触发flush刷新机制,将memStore的数据最终写入到HDFS上形成一个StoreFile文件
6. 随着不断的flush刷新,在HDFS上storeFile会越来越多,当storeFile达到一定阈值(3个及以上)后,就会触发
	compact合并压缩的机制,将多个storeFile最终合并为一个大的HFile
7. 随着不断的合并,大的Hfile会越来越大,当这个Hfile达到一定的阈值(最终10GB)后,就会触发split切割机制,
	将这个大的Hfile进行一分为二的操作,同时管理的region也会被一分为二,形成两个新的Hfile和两个新的region,
	一个region管理一个Hfile,当分裂完成后,原有的就region和Hfile将下线并被删除

Hbase的原理及其相关的工作机制

Hbase的flush刷新机制(溢写合并机制)
flush刷新机制:
		当客户端不断想memStore写入数据,memStore中数据达到一定的阈值后,就会触发这个flush的刷新机制,
		最终将数据刷新到HDFS上,形成一个storeFile文件
		
		阈值:128M  /   1h
		
		flush内部的流程机制:
			 1. 当memStore达到阈值后,首先会将当前这个memStore空间关闭,然后开启一个新的memStore接着进行写入操作
			 2. 将这个已经关闭的空间的数据(segment片段)防止到一个pipeLine管道中,pipeLine管道是一个只读管道,
			 	等待进行flush到HDFS操作
			 	hbase2.X以上架构:
			 			存储在pipeLine中数据会尽可能晚的舒心到HDFS上,让更多的数据能够存储在pipeLine管道中,
			 			以提升查询的效率,减少后续的IO读写操作
			 			当整个region内存空间达到阈值,此时一次性将pipeLine管道中的全部数据写入到HDFS上,
			 			在写入过程中,会将多个片段数据进行内存合并操作,将其合并为一个storeFile写入到HDFS上
				hbae1.X架构
						一旦数据达到pipeLine管道后,flush子线程检测到pipeLine管道中有数据,
						直接将其flush到磁盘上形成一个storeFIle文件
	注意:虽然说在hbase2.x提供了内存合并的方案, 但是这种方案默认情况下是没有开启的,
	 也就意味着在默认情况和hbase1.x是一样的

如何修改默认触发的阈值: hbase-site.xml

hbase的高可用 hbase高可用原理_数据_05


如何配置内存合并的操作

在内存合并的时候,主要可以采取三种合并方案:
	basic(基础型):
		在进行内存合并的时候,并不关心内存中数据是否有出现过期版本或者已经标记删除数据,
		直接进行合并即可。
		此种操作合并效率比较高
	
	eager(饥渴型):
		在进行内存合并的时候,观察数据是否已经发生过期,或者这条数据是否已经出现被打伤删除标记信息,
		如果发现有,在合并的时候,直接将这些过滤掉,可以保证合并的文件更小,
		而且当前这个文件也没有过期的数据了。
		适用于:数据经常过期的场景,比如购物车
		此种操作,效率比较低
	
	adaptive(适应型):
		在进行合并的时候,会校验整个数据集过期的数据是否比较多,如果比较多,自动采用饥渴型解决,
		如果发现没有太多过期数据,采用基础型方案

	在实际生产中,一般使用 basic 或者 eager  根据实际数据的特点选择对应的方案

配置方式:

  1. 全局配置: hbase-site.xml中 所有的表都会按照这种方式进行内存合并
  • 默认值: none (不开启)

hbase的高可用 hbase高可用原理_HDFS_06

  1. 针对某个表来设置:
  • 默认值: none
  • hbase的高可用 hbase高可用原理_hbase的高可用_07

HBase的storeFile的合并机制
compact合并机制: 
	当flush不断的被触发, 在HDFS上就会形成越来越多的storeFile文件, 当storeFile达到一定的阈值后, 
	就会触发compact合并压缩的机制操作
	

minor: 将多个小的storeFile合并为一个较大的Hfile过程 
	触发阈值: 达到3个及以上 或者在启动Hbase的时候进行检测
	注意:
		minor在合并过程中, 仅在数据进行排序操作, 并不关心数据是否存在过期以及已经打上删除标记
		minor在执行合并效率比较高
		
	在合并的时候, 也是需要将这些数据边读取到内存, 然后边通过追加的方式合并到HDFS上

major: 将这个较大的Hfile合并之前大的Hfile进行合并成最终一个大的Hfile过程
	触发阈值: 7天 或者在启动Hbase的时候检测
	
	注意: 
		major在进行合并操作的时候, 会将之前较大的Hfile和当前的这个大的Hfile进行最终合并为一个Hfile操作, 
		此时由于可以拿到region下所有的数据, 所以在合并过程中, 如果发现有些版本数据已经过期, 或者说已经被标记删除了, 
		在合并的过程中将处理清洗掉, 保证大的Hfile中不存在过期或者标记删除的数据
		
	由于此操作需要处理的数据量比较庞大, 整个执行对当前regionServer影响比较高, 一般建议关闭自动触发, 
	改为手动(在不是很繁忙的时候触发执行即可)


hbase和HDFS存在一些矛盾关系:  hdfs不支持随机读写, 但是基于HDFS的hbase却支持高效的随机读写
	1) 在进行写入 修改 删除操作的时候, 对于hbase都是一种添加数据的操作, 而且都是将数据添加到内存中 
	(从而提升写入数据性能)
	2) 那么一旦修改后, 或者删除后, 之前的版本的数据可能就会过期, 这些过期的时候就要分为二个阶段来处理: 
		第一个阶段: 内存合并阶段  此阶段只能将当前在内存中过期数据清除掉
		第二个阶段: major合并阶段  此阶段将会进行完整的清除工作
	3) 所有在写入到HDFS的数据都是采用追加的方式进行写入操作
	4) hbase为了提供读取数据的性能, 专门定义一种hbase独有的文件格式: HFile 此文件中存储大量的索引信息数据, 
	从而保证能够更快检索数据, 同时每个region定义存储数据范围 , 能够快速找到对应的文件

hbase的高可用 hbase高可用原理_数据_08

Hbase的split机制(region分裂)

默认情况下, 当一个region所管理的Hfile文件达到10GB的时候, 就会触发split分裂机制, 此时会将region进行一分为二,
形成两个新的region, 而region对应管理Hfile也会进行一分为二,形成两个新的Hfile,
这个两个hfile与两个新的region一一对应管理即可, 一旦分裂完成后, 旧的region和对应数据就会下线并删除

思考: 默认情况下, 创建一个表只有一个region, 一个region最终也只能被一个regionServer所管理,
当我们对这个表进行大量的读写请求操作的时候, 所有的请求将全部打向到这一个regionServer上 ,
此时对这个regionServer会产生什么影响呢?

答:
	会导致这个regionServer整个读写的效率的下降, 甚至出现宕机风险

如何解决呢? 
	如果可以让这个表尽早的进行分裂为多个region, 一旦一个表有个多个region, 不同region可以被不同的regionServer所管理, 
	此时在执行读写请求操作的时候, 相当于有多个regionServer一同来承担读写请求, 从而减轻了单台节点的压力

但是 如果默认是10GB的化, 那么从 0~10GB操作貌似有点太长了, 所以这样也是不合适的, hbase为了解决这个问题, 
专门提供了一个算法公式, 来计算何时进行分裂操作:
		Min(R^2 * "hbase.hregion.memstore.flush.size", "hbase.hregion.max.filesize")
		说明: R 表示一个表的region数量
	基于以上公式, 可以看出分裂的时间:
		第一次: 当region达到128M的时候, 就会触发一次的region的分裂操作
		第二次: 当region达到512M的时候, 救护粗发一次region的分裂操作
		第三次:   . .....
		依次类推,知道region的数量达到9个的时候, 此时min计算后的值就是10GB  在以后即使按照10GB 进行分裂

hbase的高可用 hbase高可用原理_hbase_09

region server的上线和下线流程:

hbase的高可用 hbase高可用原理_HDFS_10

master的上线和下线

hbase的高可用 hbase高可用原理_HDFS_11


当master称为active节点后, 如何进行region的管理分配操作呢?

1) 当master启动后, 首先会先和各个从节点进行通信, 让各个从节点汇报自己的目前所管理的region信息
2) master会再去读取meta表, 从中获取到所有的region信息
3) 根据meta表中region信息 以及各个 从节点汇报上来region 进行比对, 查找出那些region还没有分配, 
或者说那个从节点管理的region数量过多
4) 将那些没有分配的region进行重新分配给那些管理region数量比较少的从节点, 
同时在这个过程需要保证各个从节点管理region数量的负载均衡(底层还需要一个表中多个region被不同regionServer所管理)


	在整个hbase启动过程中, compact合并机制在此时也会进行校验, 首先会先校验是否可以触发minor,
	 如果可以 直接触发执行, 执行后, 接着在判断是否可以进行major操作, 如果满足阈值, 也会触发执行, 
	 因为这个时候执行操作是最佳执行时间

注意: 由于master只对表和region的元数据进行管理操作, 并不会参与表数据的IO工作,
所以说短暂master下线并不会影响整个hbase的集群(大部分的操作都是表数据读写)

当master宕机后, 主要会影响什么呢? 主要会影响需要修改元数据的操作
	比如: 创建表 修改表 删除表 清空表 , 执行负载均衡, 分配region的操作
	唯独region分裂是可以正常执行的, 因为region的分裂master并不会参与
HBase的Bulk Load 批量加载操作

思考:

当我们需要将一大批数据往Hbase的表中进行添加的时候, 一般采用的方案通过JAVA API 一条一条的将数据写入到HBase中, 整个写入操作, 先将数据写入到memStore中, 然后在flush到HDFS上形成storeFile, 然后storeFile在合并为一个大的Hfile, 最后这个大的Hfile进行分裂形成多个region, 依次不断的处理即可

在此流程中, 如果数据量比较大, 写入操作会占用时间也会比较长, 同时由于写入操作一直在高效的写入, 此时对网络对服务器中资源都会进行大量的占用, 主要是带宽, 当写入操作将网络带宽占用过大, 就会导致读取数据操作性能会严重下降,甚至出现无法读取数据.
对于服务器由于不断传输数据, 可能服务器也会无法承载长时间高占用处理, 也会宕机

思考: 如何解决这个问题呢?
发现写入过程中, 数据最终就是落在HDFS上, 形成了一个Hfile文件格式数据, 那么依然如此, 那么是否可以将这一大批数据直接转换为对应Hfile格式数据,然后将这个数据直接放置对应表的对应HDFS的目录下

而这种解决思路, 就是BulkLoad方案
第一步: 将数据转换为HFile文件格式数据: MapReducer
第二步: 将这个HFile文件格式数据加载到对应的表中

适用于:
需要一次性写入一大批数据到HBase的场景

hbase的高可用 hbase高可用原理_读取数据_12