HBase是一种分布式,可扩展,支持海量数据存储的NOSQL数据库
存储数据稀疏,数据存储多维,不同的行具有不同的列。
数据存储整体有序,按照RowKey的字典序排列,RowKey为Byte数组
HBase的底层物理存储结构(k-v)
RowKey—行键Hbase自带(唯一)
很多列分组----列族(可动态增加)
行序(唯一 如果不唯一 则覆盖)----字典序(按位比较)
把横向切分的叫Region-----表的切片
Storefile
不同版本(version)的数 据根据timestamp进行区分
对于删除操作,其类型为Delete
命名空间,类似于关系型数据库的database概念,每个命名空间下有多个表。Hbase有两个自带的命名间,分别是hbase和default,hbase中存放的是HBase内置的表,default表是用户默认使用的命名空间
类似于关系型数据库的表概念.不同的是,HBase定义表时只需要声明列族即可,不需要声明具体的列。这意味着,往HBase写入数据时,字段可以动态、按需指定。因此,和关系型数据厍相比,HBase能够轻松应对字段变更的场景。
HBase表中的每行数据都由一个RowKey和多个Column(列)组成,数据是按照RowKey的字典顺序存储的,并且查询数据时只能根据RowKey进行检索,所以RowKey的设计十分重要
HBase中的每个列都由Column Family(列族)和Column Qualifier(列限定符)进行限定 例如info:name,info:age.建表时,只需指明列族,而列限定符无需预先定义
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,其值为写入HBase的时间
由{rowkey,column Family:column Qualifier,time Stamp)唯一确定的单元.cell中的数据是没有类型的,全部是字节码形式存贮
实现类为 HMaster,负责监控集群中所有的 RegionServer 实例。主要作用如下:
(1)管理元数据表格 hbase:meta,接收用户对表格创建修改删除的命令并执行
(2)监控 region 是否需要进行负载均衡,故障转移和 region 的拆分。
通过启动多个后台线程监控实现上述功能:
①LoadBalancer 负载均衡器
周期性监控 region 分布在 regionServer 上面是否均衡,由参数 hbase.balancer.period 控
制周期时间,默认 5 分钟。
②CatalogJanitor 元数据管理器
定期检查和清理 hbase:meta 中的数据。meta 表内容在进阶中介绍。
③MasterProcWAL master 预写日志处理器
把 master 需要执行的任务记录到预写日志 WAL 中,如果 master 宕机,让 backupMaster
读取日志继续干。
全称 hbase:meta,只是在 list 命令中被过滤掉了,本质上和 HBase 的其他表格一样。
RowKey:
([table],[region start key],[region id]) 即 表名,region 起始位置和 regionID。
列:
info:regioninfo 为 region 信息,存储一个 HRegionInfo 对象。
info:server 当前 region 所处的 RegionServer 信息,包含端口号。
info:serverstartcode 当前 region 被分到 RegionServer 的起始时间。
如果一个表处于切分的过程中,即 region 切分,还会多出两列 info:splitA 和 info:splitB,
存储值也是 HRegionInfo 对象,拆分结束后,删除这两列。
注意:在客户端对元数据进行操作的时候才会连接 master,如果对数据进行读写,直接连接
zookeeper 读取目录/hbase/meta-region-server 节点信息,会记录 meta 表格的位置。直接读
取即可,不需要访问 master,这样可以减轻 master 的压力,相当于 master 专注 meta 表的
写操作,客户端可直接读取 meta 表。
在 HBase 的 2.3 版本更新了一种新模式:Master Registry。客户端可以访问 master 来读取
meta 表信息。加大了 master 的压力,减轻了 zookeeper 的压力。
Region Server 实现类为 HRegionServer,主要作用如下:
(1)负责数据 cell 的处理,例如写入数据 put,查询数据 get 等
(2)拆分合并 region 的实际执行者,有 master 监控,有 regionServer 执行。
写缓存,由于 HFile 中的数据要求是有序的,所以数据是先存储在 MemStore 中,排好
序后,等到达刷写时机才会刷写到 HFile,每次刷写都会形成一个新的 HFile,写入到对应的
文件夹 store 中。
由于数据要经 MemStore 排序后才能刷写到 HFile,但把数据保存在内存中会有很高的
概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做 Write-Ahead logfile 的文件
中,然后再写入 MemStore 中。所以在系统出现故障的时候,数据可以通过这个日志文件重
建。
读缓存,每次查询出的数据会缓存在 BlockCache 中,方便下次查询。
HBase 通过 Zookeeper 来做 master 的高可用、记录 RegionServer 的部署信息、并且存储
有 meta 表的位置信息。
HBase 对于数据的读写操作时直接访问 Zookeeper 的,在 2.3 版本推出 Master Registry
模式,客户端可以直接访问 master。使用此功能,会加大对 master 的压力,减轻对 Zookeeper
的压力。
HDFS 为 Hbase 提供最终的底层数据存储服务,同时为 HBase 提供高容错的支持。
Hbase读比写慢的过程
写流程:
(1)首先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server;
(2)访问对应的 Region Server,获取 hbase:meta 表,将其缓存到连接中,作为连接属
性 MetaCache,由于 Meta 表格具有一定的数据量,导致了创建连接比较慢;
之后使用创建的连接获取 Table,这是一个轻量级的连接,只有在第一次创建的时候会
检查表格是否存在访问 RegionServer,之后在获取 Table 时不会访问 RegionServer;
(3)调用Table的put方法写入数据,此时还需要解析RowKey,对照缓存的MetaCache,
查看具体写入的位置有哪个 RegionServer;
(4)将数据顺序写入(追加)到 WAL,此处写入是直接落盘的,并设置专门的线程控
制 WAL 预写日志的滚动(类似 Flume);
(5)根据写入命令的 RowKey 和 ColumnFamily 查看具体写入到哪个 MemStory,并且
在 MemStory 中排序;
(6)向客户端发送 ack;
(7 )等达到 MemStore 的刷写时机后,将数据刷写到对应的 story 中
(1)创建 Table 对象发送 get 请求。
(2)优先访问 Block Cache,查找是否之前读取过,并且可以读取 HFile 的索引信息和
布隆过滤器。
(3)不管读缓存中是否已经有数据了(可能已经过期了),都需要再次读取写缓存和
store 中的文件。
(4)最终将所有读取到的数据合并版本,按照 get 的要求返回即可。
Memstore的刷写时机
Memstore刷写由多个线程控制,条件相互独立
主要的刷写规则是控制刷写文件的大小,在每一个刷写线程中都会进行监控
(1)当某个memstroe的大小达到了hbase.hregion.memstore.flush.size(默认值128M),
其所在region的所有memstore都刷写。
当memstore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M)
*hbase.hregion.memstore.block.multiplier(默认值4)
时,会刷写同时阻止继续往该memstore写数据(由于线程监控是周期性的,所有有可能面对数据洪峰,尽管可能性比较小)
(2)由HRegionServer中的属性MemstoreFlusher内部线程FlushHandler控制。标准为LOWER_MARK(低水位线)和HIGH_MARK(高水位线),意义在于避免写缓存使用过多的内
存造成OOM
当regionserver中memstore的总大小达到低水位线
java_heapsize
*hbase.regionserver.global.memstore.size(默认值0.4)
*hbase.regionserver.global.memstore.size」ower.limit(默认值 0.95),
region会按照其所有memstore的大小顺序(由大到小)依次进行刷写。直到regionserver中所有memstore的总大小减小到上述值以下。
当regionserver中memstore的总大小达到高水位线
java_heapsize
*hbase.regionserver.global.memstore.size(默认值 0.4)
时,会同时阻止继续往所有的 memstore 写数据
(3)为了避免数据过长时间处于内存之中,到达自动刷写的时间,也会触发 memstore
flush。由 HRegionServer 的属性 PeriodicMemStoreFlusher 控制进行,由于重要性比较低,5min才会执行一次。
自动刷新的时间间隔由该属性进行配置 hbase.regionserver.optionalcacheflushinterval(默认1 小时)
(4)当 WAL 文件的数量超过 hbase.regionserver.max.logs,region 会按照时间顺序依次进行刷写,直到 WAL 文件数量减小到 hbase.regionserver.max.log 以下(该属性名已经废弃,现无需手动设置,最大值为 32)。
由于 memstore 每次刷写都会生成一个新的 HFile,文件过多读取不方便,所以会进行文件的合并,清理掉过期和删除的数据,会进行StoreFile Compaction。
Compaction 分为两种,分别是 Minor Compaction 和 Major Compaction。Minor Compaction会将临近的若干个较小的 HFile 合并成一个较大的 HFile,并清理掉部分过期和删除的数据,有系统使用一组参数自动控制,Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉所有过期和删除的数据,由参数 hbase.hregion.majorcompaction控制,默认 7 天。
参与到小合并的文件需要通过参数计算得到,有效的参数有 5 个
(1)hbase.hstore.compaction.ratio(默认 1.2F)合并文件选择算法中使用的比率。
(2)hbase.hstore.compaction.min(默认 3) 为 Minor Compaction 的最少文件个数。
(3)hbase.hstore.compaction.max(默认 10) 为 Minor Compaction 最大文件个数。
(4)hbase.hstore.compaction.min.size(默认 128M)为单个 Hfile 文件大小最小值,小于这个数会被合并。
(5)hbase.hstore.compaction.max.size(默认Long.MAX_VALUE)为单个 Hfile 文件大小最大值,高于这个数不会被合并。
小合并机制为拉取整个 store 中的所有文件,做成一个集合。之后按照从旧到新的顺序遍历。
判断条件为:
① 过小合并,过大不合并
② 文件大小/ hbase.hstore.compaction.ratio < (剩余文件大小和) 则参与压缩。所有把比值设
置过大,如 10 会最终合并为 1 个特别大的文件,相反设置为 0.4,会最终产生 4 个 storeFile。
不建议修改默认值
③ 满足压缩条件的文件个数达不到个数要求(3 <= count <= 10)则不压缩。
下一篇:Qt中使用