1,hbase读流程
首先通过meta表找到要读数据的region所在的RegionServer,然后去BlockCash中读取,如果没有就去Memstore中读取,如果也没有,那就去Hfile中去读
(1) 客户端访问Zookeeper,获取存放目标数据的Region信息,从而找到对应的RegionServer。
(2) 通过RegionServer获取需要查找的数据。
(3) Regionserver的内存分为MemStore和BlockCache两部分,MemStore主要用于写数据,BlockCache主要用于读数据。读请求先到BlockCache中查数据,查不到就到MemStore中查,再查不到就会到StoreFile上读,并把读的结果放入BlockCache。
寻址过程:client-->Zookeeper-->.META.表-->RegionServer-->Region-->client
2,hbase写流程
1,首先找到要写数据的region所在的RegionServer,然后先将数据写入到WAL中,再将数据写到Menstore中等待刷新,最后回复客户端写入完成
2,当客户端发起一个Put请求时,首先它从hbase:meta表中查出该Put数据最终需要去的
HRegionServer。然后客户端将Put请求发送给相应的HRegionServer,在HRegionServer中它首先会将该Put操作写入WAL日志文件中(Flush到磁盘中)。
3,访问hbase中行的三种方式
与nosql数据库们一样,row key是用来检索记录的主键。只有3中方式:
1 通过单个row key访问(get访问单行数据)
2 通过row key的range(访问某个区间内的rowkey,访问多行数据)
3 全表扫描 (scan访问全本的数据)
4, rowkey设计的三大要点
1,长度:rowkey是一个二进制码流,最大长度是64kb,内部存储为字节数组。如果太大的话,会浪费空间,一般是越短越好。一般不要超过16个字节。
2, 散列:Hbase中的数据是按照RowKey的字典顺序排列的; rowkey由两部分组成,高位是程序自动生成的无规律+自己设计的递增规则。散列就是让rowkey分散在集群的各个机器上,尽量不要让它集中在一个地方。因为不管你设计的是何种自增,递增的部分都是有规律的,如果把他放高位,就会不可避免的出现热点,所以才把程序生成部分放在rowkey高位,低位放例如时间字段。热点排序是Hbase的一大缺点,一般会让集群失效。
3,唯一性:需要用其来定位数据,必须唯一。
5, Hbase基本概念
1, RowKey(行键)
相当于关系型数据库中的主键,具有唯一性,在内部被存为字节数组,最大不超过64k,一般是16个字节(一个汉字=2个字母=2个字节(Byte)=8个bit位),1kb=1024Byte;按照字典序排列,注意避免数据热点问题
2, Column Family(列族)
是表Schema的一部分,包含一个或者多个列,是列的前缀,Hbase中每个列都归属于某个列族,需要在创建表的时候就需要指定好;一个Schema一般有一到三个列族;一个列族包含的所有列在物理存储上都是在同一个底层的存储文件当中。
3,Cell(单元格)
一个单元格就是由前面说的行键、列标示、版本号唯一确定的字节码
Hbase表的索引是行键、列族、列限定符和时间戳
4,Version Number(版本号)
默认是时间戳,降序排列,最后写入的值会被优先读取
5,HRegion
Table在行的方向上分割为多个HRegion,Hregion是按照大小分割的,每个表一开始只有一个Hregion,随着数据不断插入表,它越来越大,默认10G,达到阈值的时候会分裂split为两个HRegion;HRegion是Hbase扩展和负载均衡的基本单元,是分布式存储的最小单元;不同的HRegion分布到不同的RegionServer上;
一个HRegion有一个或者多个HStore组成,每一个HStore保存一个列族;每个HStore又是有一个MemStore和0或多个HFile组成,Memstore是存储在内存中,HFile存储在HDFS上,数据都会先写入到MemStore上,一旦MenStore达到阈值,就会持久化到HFile中去;
6,三大组件
Client: 它包含访问Hbase的接口,维护这一些缓存来加快对hbase的访问,比如缓存中记录着Region的位置信息
Master节点: 主要为各个RegionServer分配Region,负责RegionServer的负载均衡,管理用户对Table的CRUD操作
RegionServer节点: 维护Region,处理Region的IO请求,负责在运行过程中变得过大的Region进行拆分
6, Hbase特点
1,扩展性好
去掉关系型数据库的关系特性,数据之间是弱关系,非常容易扩展,
2,面向列
只访问查询涉及的列,去掉冗余列,大量降低IO;而且支持动态添加列
对于为Null的列,不占用存储空间,表可以设计的非常稀疏
列存储每一列数据类型一致,而行存储在一行记录中保存了多种类型的数据,数据解析需要在多种数据类型之间频繁转换,影响性能,增加时间
3,以Hdfs作为文件存储系统,支持分布式的海量存储,达到PB级别
4,并发性能好
通过MapReduce支持大并发处理,海量数据;在大数据量下具有非常好的读写性能,
7, Hbase数据热点 (读)
热点:检索habse的记录首先要通过row key来定位数据行。当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求过多、负载过大,而其他region server负载却很小,就造成了“热点”现象
HBase中,表会被划分为1…n个Region,被托管在RegionServer中。Region有二个重要的属性:StartKey与EndKey表示这个Region维护的rowKey范围,当我们要读/写数据时,如果rowKey落在某个start-end key范围内,那么就会定位到目标region并且读/写到相关的数据。
8, Hbase数据倾斜 (写)
数据倾斜:Hbase中数据是按照字典顺序排列的,当大量连续的rowkey集中写在某一个Hregion上,各个Hregion之间数据就会分布不均匀
默认的情况下,创建一张表是,只有1个region,start-end key没有边界,所有数据都在这个region里装,然而,当数据越来越多,region的size越来越大时,大到一定的阀值,hbase认为再往这个region里塞数据已经不合适了,就会找到一个midKey将region一分为二,成为2个region,这个过程称为分裂(region-split)。而midKey则为这二个region的临界(这个中间值这里不作讨论是如何被选取的)。
此时,我们假设假设rowkey小于midKey则为会被塞到1区,大于等于midKey则会被塞到2区,如果rowkey还是顺序增大的,那数据就总会往2区里面写数据,而1区现在处于一个被冷落的状态,而且是半满的。2区的数据满了会被再次分裂成2个区,如此不断产生被冷落而且不满的Region,当然,这些region有提供数据查询的功能。
这种设计是分布式系统一个很大的弊端,而且这样导致数据倾斜和热点问题,从而导致集群的资源得不到很好的利用。
解决:预分区,加盐,哈希,反转