`
ppg
  • 浏览: 15485 次
  • 来自: 上海
社区版块
存档分类
最新评论

HBase Snapshot 源码 流程

阅读更多
HBase自从0.94.6开始加入了Snapshot功能,原则是是尽可能的避免少的网络、磁盘开销而达到对于当前Table的Snapshot以及之后的Restore或者Clone.

一 以下是对Snapshot整个流程的初步整理:

SnapshotManager 在Master存在一个,控制所有Snapshots

Snapshot流程

1. HBaseAdmin.takeSnapshotAsyncRPC  ->  HMasterInterface.snapshot   RPC请求Master
1.1 checkSnapshotSupport ,hbase-site是否支持
1.2  get the snapshot information 获取SnapshotDescription(Proto)
1.3  Check isSnapshotCompleted 是否已经存在这个Snapshot的版本,通过Hdfs上是否存在此文件夹路径判断
1.4  Check 需要被snapshot的表是否存在,通过FSTableDescriptors 判断
1.5  call pre coproc hook   MasterCoprocessorHost.preSnapshot  通过coprocessor,预处理pre_snapshot事件
1.6  prepareToTakeSnapshot  确保同时只有一个snapshot在运行
1.7  通过Zookeeper保持的状态来确定该Table的状态
{
  如果是enable,启动分布式的snapshot
  如果是disable,只在Master上完成snapshot
}
1.8  SnapshotManager.snapshotEnabledTable  实例化EnabledTableSnapshotHandler
{
1.8.1 实例化 MasterSnapshotVerifier 对于Table状态确认的最后一道防线(如果在snapshot的时候发生了split等)
1.8.2 获取coordinator (ProcedureCoordinator)
}
1.9异步启动TakeSnapshotHandler.process()线程处理
{
   .tmp文件
   目录结构    
.snapshot/.tmp/{snapshotName}/.tmp
.snapshot/.tmp/{snapshotName}/.snapshotinfo
.snapshot/.tmp/{snapshotName}/.tableinfo.0000000001
   1.9.1  writeSnapshotInfo  在.snapshot/.tmp/{snapshotName}/.snapshotinfo 中写 snapshot description
   1.9.2  TableInfoCopyTask.call  copy表信息
1.9.2.1 writeTableDescriptor  在.snapshot/.tmp/{snapshotName}/tmp/.tableinfo.0000000001 中写入文件描述信息
1.9.2.2 将.tableinfo.0000000001 移出tmp到.snapshot/.tmp/{snapshotName}/ 下

   1.9.3  通过CatalogTracker 扫.META.表获取  regionsAndLocations
   1.9.4  EnabledTableSnapshotHandler.snapshotRegions  执行各个Region的snapshot
          其中,由ProcedureCoordinator来调度所有的Procedure   see  http://140.211.11.40/r/8240/diff/2-4/
          Proceduer.java.call()  执行一个 barriered procedure
          通过zk 建立 /hbase/online-snapshot/reached/v2/3h_william-PC,47055,1370882110005  Node

  Procedure.sendGlobalBarrierStart    建立Acquired节点
          Procedure.sendGlobalBarrierReached  建立reached节点
   1.9.5  RegionServer 的  Zookeeper Watch收到要处理的Procedure简历subProducer
   1.9.6  调用FlushSnapshotSubprocedure
          1.  startRegionOperation 获取各种锁
  2.  flushcache 将Memstore flush到磁盘
  3.  将HFile的文件名写入

}
1.10 snapshot post处理



二  我们已经对对Table进行了Snapshot,那源码中是怎么Clone这个Table呢?


clonesnapshot

Client
1. 构建HSnapshotDescription(里面是protofub对象) Writable对象
2. HMaster.restoreSnapshot(HSnapshotDescription)

Server
1. HMaster.restoreSnapshot
   1. CheckSnapshot support
   2. get snapshotDir = file:/E:/tmp/hadoop/data/.snapshot/v1
   3. read snapshot information 通过.snapshot的文件,读取信息:
      1. SnapshotDescription   通过解析(.snapshotinfo)
      2. HTableDescriptor   通过解析 (.tableinfo)
   4. stop tracking completed restores 将SnapshotManager的restoreHandlers Map,清空
   5. CloneTableSchema -> HTableDescriptor 只替换需要clone table的表名
   6. preCloneSnapshot
      1. check ,确保同一时间只能对于同一个table进行clone
      2. CloneSnapshotHandler  构建 处理对象
         1. CreateTableHandler  创建表
            1.  在 {HBaseDir}/.tmp中创建基本信息
            2.  CloneSnapshotHandler.handleCreateHdfsRegions 将Snapshot的信息Copy到创建的表中
                1. 获取snapshotDir
                2.  RestoreSnapshotHelper.restoreHdfsRegions()
                    1. 获取snapshotRegionNames
                    2. 构建RestoreMetaChanges
                    3. 判断已存在的HRegin下是否有文件,即是重新回复还是新建
                    4.  cloneHdfsRegions
                        1. 重新构建所有 ReginName
                        2. ModifyRegionUtils.createRegions
                        2. 多线程对每个Region写入磁盘
                           1.RegionFillTask.fillRegion
                              其中RestoreSnapshotHelper.restoreStoreFile 触发HFileLink.create 对HFile和Snapshot中的文件对应创建link william=d5f30b31d1a0554d2615a220aebc4e0f-9ffae60195cb45a18519f2a21cf9b285
                              其中会在.archive中建立link。 E:\tmp\hadoop\data\.archive\william\d5f30b31d1a0554d2615a220aebc4e0f\f1\.links-9ffae60195cb45a18519f2a21cf9b285\9ba86ddb59d34942e2f21a27b5cc2399.william11
   7. postCloneSnapshot
 
2. 新的HRegion加载HStore时候
   1. StoreFile.StoreFile  加载StoreFile
      1.if (HFileLink.isHFileLink(p)) 判断HFile是link文件
      2.  将可能的link具体位置 /.tmp  或 /.archive  或 originPath 列出
      3. 加载

Q: 这里有个问题是,如果先做了snapshot,再clonetable,那么这个clone的table是一个指向引用,指向原有table,如果这个时候对原有的table进行split,则需要将原有table的HFile归档到.archive中,这个时候HRegion所加载的变不能释放

KeyClass
HFileLink


三   我们基本得知,Snapshot的思路是对于原来文件HFile的一个Reference的控制,但如果说在Reference情况下,发生了Split,那源码中又是怎么处理的呢?

当已经snapshot后,触发split/compact的处理机制

1. split 触发对于两个daughter Region的compact
   1. CompactionRequest.run() 每一个Daughter HRegion各自启线程并发处理
      1 . HRegion.compact(CompactRequest)
          1. Store.compact  majoy compact
             1.  Compactor.compact
                 1.  Reader = HalfStoreFileReader
                 2.  Scan and Write to DaughterRegion/.tmp 将Reference所指向的部分,写入到tmp中
                 3.  Store.completeCompaction
                     1. 将DaughterRegion/.tmp 下的HFile移动到DaughterRegion/{ColumnFamily}/下 此时,已经将top部分写完,但Reference部分还在
                     2. HFileArchiver.archiveStoreFiles  因为需要将原来的Compact文件一出掉,所以要进行归档处理
                     3. 在 {HBasedir}/.archive下建立需要存档的文件名,即{DaughterRegionName}
                     4. 将需要归档的文件归档到{HBasedir}/.archive/{tablename}/下   (目前是Reference文件)


Key class
1. HMaster.HFileCleaner 定期清理.archive下的文件
其中 [HFileLinkCleaner, SnapshotHFileCleaner, TimeToLiveHFileCleaner]会对SnapshotHFileCleaner进行排除
2 HMaster.CatalogJanitor 定期清理Parent Region,扫Meta表,如果获取的Parent Region,其Daughters没有Reference文件,则可以被清理,清理到.archive中
3. StoreFile getMaxSequenceIdInList
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics