Hbase总结03_数据管理

本文详细解析HBase的数据存储机制与Hadoop之间的数据交互流程。介绍HBase如何通过预写日志(HLog)和数据文件进行数据写入与持久化,以及flush、WAL、数据合并和拆分等关键概念。

存储

下图展示Hbase与Hadoop数据交互过程

Hbase处理文件类型有两种:预写日志(Hlog)和实际的数据文件

写数据流程

流程如图

1)Client 向 HregionServer 发送写请求;
2)HregionServer 将数据写到 HLog(write ahead log)。为了数据的持久化和恢复;
3)HregionServer 将数据写到内存(MemStore);
4)反馈 Client 写成功。

flush

1 当 MemStore 数据达到阈值(默认是 128M,老版本是 64M),将数据刷到硬盘,形成一个新的HFile;
2 将内存中的数据删除,同时删除 HLog 中的历史数据;
3 并将数据存储到 HDFS 中;
4 在 HLog 中做标记点。
备注:当region关闭前会进行预刷写,将数据刷写到磁盘上

WAL

HLog类

  • 实现了WAL的类叫做HLog
  • WAL是可选的,如果用户在执行一个离线的大批量导入数据的MapReduce作业的时候可以获得额外的性能,但是需要注意导入的时候有可能数据丢失(强烈建议不要关闭)
  • HLog被这台机器上的所有region共享

HLogKey类

WAL使用的是 Hadoop  的 SequenceFile。这种文件格式按照 key value存储数据,HLogKey 类作为key存储了,数据的归属,region和表名,写入时间,集群ID
LogSyncer类

管道写与多路写
sync()实现的是管道写,当写入的时候修改被发送到第一个datanode,处理完成后在被发送到下一个datanode,直到3个datanode都已经确认了写操作,客户端才被允许继续进行
多路写是写入同时被发送到3台主机上,当所有主机确认了写操作之后,客户端才可以继续
区别: 管道写延迟很高,但是可以更好的利用带宽。多路写有比较低的延迟,因为客户端只需要等待最慢的Datanode确认。

延迟日志刷写

deferred log flush ,默认是false,如果为true,修改会先被缓存在region服务器中,然后服务器上有一个 logSyncer类,每隔1秒来写入一次数据(hbase.regionserver.optionallogflushinterval 设定)
LogRoller

当日志出现 

2011-06-15 01:45:33,323 INFO org.apache.hadoop.hbase.region server.HLog: Too many hlogs: logs=130,maxlog=96;forcing flush of 8 region(s):.....

是因为需要保留的日志文件数超过了设置的最大日志文件数,但是仍有一些数据么有被更新。服务器会进入到一个特殊的模式来强制刷写内容中的更新数据,以减少需要保存的日志量。
其他控制日志滚动的参数有 

  • hbase.regionserver.hlog.blocksize(设置为文件系统默认的块大小或者 fs.local.block.size 默认为32M)
  • hbase.regionserver.logroll.multiplier (设为0.95) 表示当日志达到块大小的95%就会滚动日志
     

日志管理

单日志:使用单日志的原因是减少磁盘寻址,提高性能,但是会为恢复带来麻烦,要先日志拆分
日志拆分:两种日志需要被回放的情况,集群启动时和服务失效时
数据恢复

  • region启动的时候会先检查 recovered.edits 目录是否存在,如果存在就开始读取并恢复数据。
  • 当序列ID小于硬盘上的序列ID就会被忽略

Region生命周期

region的所有可能状态

  • Offline    region下线
  • Pending Open    打开region的请求已经发送到了服务器
  • Opening    服务器开始打开region
  • Open    region已经打开,可以使用
  • Pending Close    关闭region的请求已经被发送到了服务端
  • Closing    正在关
  • Closed    已关
  • Splitting    服务器开始拆分region
  • Split    region 已经被切分了
     

文件存储路径

Hbase使用Hdfs中可配置的根目录,默认为/hbase,可以通过hadoop fs -lsr /hbase 查看,目录结构如下

根级目录

  • /hbase根目录下存放的第一个文件夹为.log,里面存放有Hlog管理的WAL日志,每个regionserver对应一个log下的子目录;
  • 由于WAL文件刚刚被创建所以显示大小是0。这是因为在hdfs里面用append来写入此文件,只有等到文件达到一个完整的块时,文件对用户才是可见的。
  • WAL 文件会等到 hbase.regionserver.logroll.period (默认是60分钟)时间之后被滚动,紧接着它的下一个新日志文件大小又从0开始了
  • 滚动之后旧日志被放到 .oldlogs 下,并等到 hbase.master.logcleaner.ttl (默认是10分钟) 后被删除。检测间隔是 hbase.master.cleaner.interval 属性设置的。

表级文件

  • 在HBase中,每张表都有自己的目录,位于HBase根目录下。
  • 每张表目录包括一个名为 .tableinfo 的顶层文件,该文件对应序列化后的HTableDescription
  • .tmp目录中存放临时数据,如更新表时生成的临时数据

region文件

  • 每个region拥有自己的目录,位于表目录下
  • .regioninfo 对应HRegionInfo实例,位于region目录下
  • hbck  就是用 .regioninfo 来检查并生成元数据表中丢失的条目
  • region 如果超过了配置的最大值 hbase.hregion.max.filesize,会拆分,并创建一个 splits 目录
  • recovered.edits用来存放需要回放的WAL日志,没这个目录则代表没有回放

zookeeper中Hbase的数据目录

在zookeeper中Hbase存在的根节点 /hbase*  ,*代表多个字符,不同方式安装的Hbase可能具有不同的后缀。根目录下主要目录有:

  • hbaseid   当前集群的clusterID
  • master   服务器节点名
  • backup-masters   后备主节点信息
  • hbase/replication   副本信息
  • meta-region-server    meta 表所在region服务器的机器名
  • rs   这个是目录,每个子节点代表服务器的名称
  • splitWAL   协调日志拆分相关的的父节点
  • table   表状态目录,存放表状态 
     

数据合并和拆分

HFile合并

读取数据时需要加载磁盘上的HFile文件,当HFile文件过多时会引起多次寻址操作,降低了效率,为了提高读写效率,减少小文件数量,合并是必须的优化操作。Hbase包含两种合并方式:Minor compact 和 Major Compact
Minor compact 

  1. 可以用于把多个HFile文件进行合并,同时可以删除TTL过期的数据;
  2. 手动删除数据操作是不能被删除的,因为MemStore在LSM整理时,对于TTL过期只要不写入HFile文件就算是删除了,而对于手动删除数据操作则可能位于不同的HFile文件中,因此做不到删除;
  3. 每次flush后开始执行合并操作;
  4. 0.96版本后采用  ExploringCompaction 合并策略,合并过程如下
    1. 根据【该文件<(所有文件大小-该文件大小)*比例因子】公式,不再强调顺序性,而是把所有的文件都遍历一遍,若满足公式就把该文件放进待合并队列组合中;
    2. 根据 hbase.store.compaction.min(默认 3)和 hbase.store.compaction.max(默认 10)两个参数选出符号要求的文件;
  5. 其他策略有:
    1. FIFOCompationPolicy:适用TTL有值且比较小,BlockCache够大
    2. DateTieredCompactionPolicy :适用数据只存很少删除,且多数操作为读取最新数据
    3. StripeCompactionPolicy : 适合Region较大(大于2G),RowKey具有统一格式,可以依照rowkey均匀切分region

Major Compact

  • 是把一个Store中的HFile文件合并为一个HFile文件,而不是把一个Region内的所有HFile文件,因为一个Region可能有多个Column Family对应的Store。
  • 合并频率比较低,默认7天执行一次,并且性能消耗非常大,最后手动控制进行合并,防止出现在业务高峰期。

Region合并

通常在有大量数据删除后对Region的合并,并不是为了性能考虑而是处于维护的目的被创造出来的。

通过Merge类冷合并Region,合并的两个region必须已经下线

hbase org.apache.hadoop.hbase.util.Merge table_name table_name,a,147608089478.39erijidsfd8s098fen32j3i8d9. table_name,b,148893879502.48jfidnxoskd023843257822j3i.

通过online_merge热合并Region,需要进入hbase shell,online_merge的传参是Region的hash值

> merge_region '39erijidsfd8s098fen32j3i8d9','48jfidnxoskd023843257822j3i'
#通过hbase:meta查看Region合并后的信息

Region拆分

一个Region代表一个表的一段Rowkey的数据集合,当Region太大,Master会将其拆分。Region太大会导致读取效率太低,遍历时间太长,通过将大数据拆分到不同机器上,拆分后的子region大小相等,整个过程在zookeeper中有进行跟踪。Region可以手动和自动拆分。

1 自动拆分

包含多种策略,具体如下:

ConstantSizeRegionSplitPolicy:按照固定大小拆分,由 hbase.hregion.max.filesize 指定
IncreasingToUpperBoundRegionSplitPolicy:动态限制拆分策略,是新版本的默认策略,计算公式:
   Math.min(tableRegionsCount^3 * initialSize,defaultRegionMaxFileSize)
   tableRegionCount:当前表在所有RegionServer上拥有的所有的Region数量的总和
   initialSize:如果定义了hbase.increasing.policy.initial.size,则使用该值,否则用memstore刷写值得2倍,即hbase.hregion.memstore.flush.size*2。
   deffaultRegionmaxFileSize:ConstantSizeRegionSplitPolicy所用到的配置项,也就是Region的最大大小
   Math.min:取这两个数值的最小值
KeyPrefixRegionSplitPolicy:固定长度前缀拆分策略,是IncreasingToUpperBoundRegionSplitPolicy的子类,在其基础上增加了对拆分点(splitPoint,拆分点就是Region被拆分出的RwoKey)的定义,保证了有相同前缀的key不会被拆分到两个不同的Region中。
DelimitedKeyPrefixRegionSplitPolicy:分隔符前缀拆分策略,也是IncreasingToUpperBoundRegionSplitPolicy的子类,按照分隔符来判断是否进行拆分,比如定义了前缀分隔符为_,那么rowkey为test1_aaaaa,test2_bbbbb,这两个数据会被拆分到不同的Region中。
BusyRegionSplitPolicy: 热点拆分策略,这是唯一考虑到热点数据的拆分策略,如果数据库中的Region某些短时间内被访问很频繁,承载了很大压力,就是热点Region
   hbase.busy.policy.blockedRequests:请求阻塞率,即请求被阻塞的严重程度,范围0.0-1.0,默认0.2,20%请求被阻塞
   hbase.busy.policy.minAge:拆分最小年龄,当Region大于这个值才进行拆分,防止判断是否要拆分时候出现短时间的访问频率波分导致没必要拆分的region被拆分。而短时前的波峰可能会快就会恢复到正常水平,单位毫秒,默认值600000,10分钟。
   hbase.busy.policy.aggWindow:计算是否繁忙的时间窗口,单位毫秒,默认值300000,5分钟,用以控制计算的评率
DisabledRegionSplitPolicy: 手动拆分策略,当上述都失败时可以用采用的方式。

2 手动拆分

pre-splitting Region预拆分:在建表的时候就定义好拆分点的算法,使用org.apache.hadoop.hbase.util.RegionSplitter类来创建表,并传入拆分点算法,拆分点算法有:
    HexStringSplit:rowkye 为 “00000000”到“FFFFFFFF” 这种形式
    UniformSplit:rowkey 为 byte[]
手动制定拆分点(属于预拆分):create 'test_split2','mycf2','mysf2',SPLITS=>['AAA','BBB','CCC']
强制拆分:通过命令强制拆分,如下
    #将表table_name从1000出拆分为两个Region
    split 'table_name,c,1476405886999.96dd83893d683','1000'
    #其他调用方式有:
    split 'tableName'
    split 'namespace:tableName'
    split 'regionName'#format:'tableName,startKey,id'
    split 'tableName','splitKey'
    split 'regionName','splitKey'
  

读取过程

读数据流程如图

1)Client 先访问 zookeeper,从 meta 表读取 region 的位置,然后读取 meta 表中的数据。meta中又存储了用户表的 region 信息;
2)根据 namespace、表名和 rowkey 在 meta 表中找到对应的 region 信息;
3)找到这个 region 对应的 regionserver;
4)查找对应的 region;
5)先从 MemStore 找数据,如果没有,再到 BlockCache 里面读;
6)BlockCache 还没有,再到 StoreFile 上读(为了读取的效率);
7)如果是从 StoreFile 里面读取的数据,不是直接返回给客户端,而是先写入 BlockCache,再返回给客户端。

 

 

上一篇:Hbase安装                                                                                     下一篇:Hbase API

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值