文章目录
目录
1、Hbase架构原理
1)、hdfs数据是不能随机修改的,但是hbase却能做到修改数据?
当向store写入一个修改值的时候,她并没有直接删除原数据增加新数据,store里面其实是一个内存+磁盘的混合体,内存(MemStore)中存最新的数据,每次我们写数据的时候,先写入内存中,当内存满了后再落盘到磁盘中成为一个StoreFile,StoreFile再存于hdfs上。所以在内存中是可以修改的。
2)、内存可以修改,那落盘后的数据怎么修改呢?
会在内存中写一条新的数据,要修改的数据不删除,读取的时候以内存的数据为准。
3)、内存数据不安全,有什么保障呢?
引入HLog文件,将写的动作追加,所以写数据先写入HLog,写完再往MemStore写,当MemStore落盘,HLog默认就会删除一批,HLog在hdfs上面。
2、Hbase的写流程
1)、客户端获取元数据信息
client要知道表的元数据(比如:这个表有几个region,region由几个regionserver管理),元数据表的信息(meta)的位置信息放在了zookeeper中,所以客户端首先要向zookeeper请求meta的位置信息,zookeeper会返回该表元数据的所在节点。客户端拿到节点信息后就去该regionserver请求元数据信息,该节点返回meta,客户端因此获取到信息,获取到该信息后就会做一个本地缓存(Meta cache)(因为第二次查表就不用这么麻烦,有了缓存,client会先去缓存中寻找,没有找到再去执行上述的操作)。
2)、执行写操作
这个写的操作就同上面的架构操作一样,先写HLog再写入memstore,最后再落盘写入storeFile。
3)、提问:由于一个表的region有多个,可能存储在多个节点上,那么客户端在获取了元数据后该向哪个regionserver上发起put请求呢?
回答:每个region有一个范围的Rowkey,因此当我们put的时候指定了rowkey,这就等价于我们知道要去哪个regionserver上去做写操作。
4)、补充
纵观整个写的过程,没有master的参与,因此即使在此阶段master挂了,也不影响。
3、MemStore Flush
1)、MemStore刷写时机
①、当某个memstroe的大小达到了hbase.hregion.memstore.flush.size(默认值128M),其所在region的所有memstore都会刷写。
当memstore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M)
* hbase.hregion.memstore.block.multiplier(默认值4)
时,会阻止继续往该memstore写数据。
这种的刷写方式会出现隐患:
可能在刷写一个128M的memStore的时候,另外一个memStore才几K,这样就会出现小文件。②的方式可以有效防止这种隐患。
②、当region server中memstore的总大小达到
java_heapsize
*hbase.regionserver.global.memstore.size(默认值0.4)
*hbase.regionserver.global.memstore.size.upper.limit(默认值0.95)
region会把其他的所有region按照其所有memstore的大小顺序(由大到小)依次进行刷写。直到region server中所有memstore的总大小减小到hbase.regionserver.global.memstore.size.lower.limit以下。
当region server中memstore的总大小达到
java_heapsize*hbase.regionserver.global.memstore.size(默认值0.4)
时,会阻止继续往所有的memstore写数据。
提问:如果regionserver有过多的region会怎么样?
可能会出现很多的小文件然后走②过程
③、到达自动刷写的时间,也会触发memstore flush。自动刷新的时间间隔由该属性进行配置hbase.regionserver.optionalcacheflushinterval(默认1小时)。
4、Hbase的读流程
1)、客户端获取元数据信息
同hbase的写流程
2)、发送get请求
客户端获取rowkey范围内的region位置后,立刻向该位置的regionserver发送get请求,regionserver就会把数据返回给客户端
3)、regionserver是如何查找元数据的?
regionserver收到get请求后,首先,client会向该regionsever的一个region请求读数据,regionserver先会在blockCache(读缓存)内尝试查找请求的数有没有,查找就直接给,没找到就会去store里面查找数据,先在memstore里面查找数据,如果memstore里面没有,则会遍历所有的storeFile进行数据查找,查找到后会先把数据放在blockcache内,然后再返回给客户端的数据。
5、StoreFile Compaction
本质上就是将多个storeFile合并成一个storeFile
1)、Compaction种类
Compaction分为两种,分别是Minor Compaction和Major Compaction。Minor Compaction会将临近的若干个较小的HFile合并成一个较大的HFile,但不会清理过期和删除的数据。Major Compaction会将一个Store下的所有的HFile合并成一个大HFile,并且会清理掉过期和删除的数据。
2)、触发时间
Minor Compaction默认3个就会触发,Major Compaction默认一星期触发一次,这个执行非常耗费性能,因此一般手动触发
因此hbase为了读写的效率,他不会真正的给你修改,而是标记修改,真正物理上的删除是在mapcompaction。
6、Region Split
默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的Region Server,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的Region Server。
1)、Region Split时机:
①、当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize,该Region就会进行拆分(0.94版本之前)。
②、当1个region中的某个Store下所有StoreFile的总大小超过Min(R^2 * “hbase.hregion.memstore.flush.size(128M)”,hbase.hregion.max.filesize"),该Region就会进行拆分,其中R为当前Region Server中属于该Table的个数(0.94版本之后)。
关于第二点的解释,为什么要这样分配?
我们可以设想一下假如我们的一个表的region存在三个regionserver上,第一个是3个region,第二和第三各是1个,则第一个分裂的大小大概为1G,第二个第三个各是128M,其实就是为了让这个表在各个regionserver上的分配尽量的平均。