总体流程图
就绪区:
这部分的核心实现类是MasterProcedureScheduler,主要的作用就是对Procedure进行调度;
从排队的角度看,可以认为存在三层队列调度;
type队列:
type包含meta、server、table,,三者之间存在优先级:meta>server>table,这里需要注意的是,所谓type队列是逻辑上来说的,具体实现上,worker在获取任务时会按优先级依次进行尝试;
entity队列:
上述每种类型都对应一个FairQueue,该队列中的元素代表与某个实体相关的一组proc,这里称为proc队列,worker获取任务时,是从entity队列中获取的,所以只有存在于entity队列中的proc队列才有运行机会;
proc队列:
这个队列中存放的就是具体的proc了,队列内部元素数量和锁状态的变化,决定了其是否存在于entity队列中,也即是否有运行机会,以下时机会对此产生影响;
将proc队列放入entity队列的时机:
- 往proc队列里面添加proc;
- worker执行完一个proc;
将proc队列从entity队列删除的时机:
- worker获取并尝试执行一个proc;
以上说的是时机,具体是否放入或删除,需要看锁需求和锁状态,基本上就是读写锁的逻辑:如果写锁被获取,那么需要该锁的proc会阻塞,如果读锁被获取,那么需要写锁的proc会阻塞,而其它需要读锁的proc则不会阻塞;
执行区:
每个proc都定义了一组state,worker从初始状态开始,依次执行状态对应的动作直到结束,或者因故挂起等待;
等待区:
proc可能会由于一些执行条件不满足,而处于等待状态,主要有以下几种情况;
等待锁:
每个proc队列都会对应一个LockAndQueue,对于正在等待锁的proc,会暂时放在其里面的队列中;
等待某事件:
处于此类等待中的proc会放在一些ProcedureEvent中,这些ProcedureEvent实例会放在与之相关的实体中,主要有以下三种;
- region rit:RegionStateNode
- meta assign/load:AssignmentManager
- master initialized:HMaster
等待子proc完成:
处于此类等待中的proc没有进行特殊的保存,当subProc运行完成,会根据childrenCountDown判断它是否是最后一个,如果是的话,则根据其携带的parentProcId从ProcedureExecutor的procedures中获取parentProc,将其唤醒;
回滚区:
不存在parentProc的proc都会对应一个RootProcedureState,内部通过一个subprocStack来保存已执行的proc及其状态,回滚时按顺序执行rollBack,这里值得注意的是,同一个proc如果已经被执行了多个步骤,那么在stack中会有多个引用变量指向它;
持久区:
当前的实现类是WALProcedureStore,数据存放在hdfs的MasterProcWALs目录;
由于这部分的实现与region的写入过程比较相似,在社区比较新的版本中,已经改为RegionProcedureStore,数据组织上跟region类似,只是目录为MasterProcs;