分布式框架中的Master-Slave类型,Slave节点负责工作的具体执行,Master负责任务的分发或者相关元数据的存储等。一般情况下,一个Master节点都会对应多个Slave节点,Master在分配任务时需要知道当前有哪些Slave节点是可以接受自己所发的命令的(Slave节点有可能因为各种原因挂掉),因此需要在其内部维持一个链表来保存所有还活着的Slave节点。HBase的HMaster是这样、HDFS的NameNode是这样、Tachyon的Master节点也是这样。Slave节点通过不断的心跳汇报(HeartBeat)来和Master通信,Master把收到心跳汇报的Slave节点看做是目前存活的,否则就说明Slave节点挂掉了。除了维持存活性以外,Master节点通常还会把需要执行的命令通过心跳返回给Slave节点,Slave节点接收到后执行Master发来的命令,完成一次交互。
Master是核心,它要是挂掉了对整个系统都是致命的影响,单点问题是每个分布式框架都要考虑的问题。应用和实现了Paxos算法的Zookeeper,是解决一致性问题的利器。HDFS、Storm、HBase等都采用Zookeeper作为元数据信息HA的载体,Tachyon也不例外。
Tachyon的Worker节点,通过不断心跳向Master汇报当前Worker中已使用的内存大小和准备删除的数据块信息,Master接受心跳汇报后返回给Worker节点相关的执行命令,这些命令可以是Register、Free等,也可以是Nothing。
其中,需要说明的地方如下:
(1)Worker心跳的时间间隔默认为1秒,由参数tachyon.worker.to.master.heartbeat.interval.ms设定。
(2)Worker心跳的超时时间默认为10秒,由参数tachyon.worker.heartbeat.timeout.ms设定。
(3)Master返回给Worker的命令主要有五种,分别是:Unknown、Nothing、Register、Free、Delete。Nothing命令什么都不做;Register命令执行Worker向Master的注册,Master会返回WorkerId存储在Worker本地;Free命令要释放Worker内存中存储的数据;Delete命令则既要删除内存中的数据也要删除磁盘上的数据。
(4)心跳的具体执行是调用的WorkerStorage的heartbeat方法。
(5)CheckStatus则会检查当前Worker节点所管理的内存使用情况。
其中,需要说明的地方如下:
(1)首先获取所有需要从当前Worker节点的内存中移除的Block的信息,Block被移除一般有如下几种情况,当Master发来Free命令时、WorkerStorage初始化时、内存不够时需要使用LRU算法换入换出。
(2) 调用MasterClient的worker_heartbeat方法进行心跳汇报给Master,此处的MasterClient会通过MasterService.Client对象调用Master的Thrift服务进行消息传递,类似于HDFS中的RPC通信的动态代理。
(3)连接建立是调用的MasterClient类的connect方法,其主要目的是为了创建MasterService.client对象,即Thrift服务的客户端。步骤如下:
Step1:调用cleanConnect方法,主要是关闭thrift的transport端口、并且将当前的HeartbeatThread线程停止掉如果其对象不为null的话,则将mIsShutdown设置为true,并且会抛出TException。首次进行clean的话,几乎没有什么要做的事情。
Step2:clean之后,进入while循环,准备获取master地址进行建立连接,while循环的条件为tries ++ < MAX_CONNECT_TRY && !mIsShutdown,默认重试5次。
Step3:获取Master的当前地址,使用getMasterAddress方法,在ZK中查找leader目录下的所有节点,根据节点的创建时间,找到最新的那个节点作为当前需要连接的Active Master节点。
Step4:初始化Thrift客户端和服务端通信的协议,此处为TBinaryProtocol。
Step5:初始化Thrift客户端MasterService.Client对象。
Step6:打开协议的Transport,就是数据传输通道,准备进行读写,如果打开失败,则会抛出TTransportException,接着停止用于维持连接的心跳线程HeartbeatThread,并且sleep1秒钟后进入while的失败重试,达到失败次数上限,抛出TException。
Step7:初始化一个心跳线程HeartbeatThread,不断的和服务端进行心跳,超时时间为tachyon.user.master.client.timeout.ms配置的属性值,默认10秒,用于保持上面已建立的Thrift连接的存活,如果期间心跳超时,会触发调用cleanConnect方法,此时就会关闭Thrift数据传输通道,终止此维持连接心跳线程。
(4) connect连接成功后,会调用MasterService.client的worker_heartbeat方法进行心跳处理,结果返回的是Command。其中worker_heartbeat的处理步骤如下:
Step1:首先调用send_worker_heartbeat方法,主要是设置workerId、已使用的内存大小、worker已删除的blockId。
Step2:创建一个worker_heartbeat_result对象,worker_heartbeat_result是MasterService中的静态内部类,这里面会定义两种Field,SUCCESS_FIELD_DESC值为0,E_FIELD_DESC为1。
Step3:通过Thrift服务发送给Master端,由MasterInfo的workerHeartbeat方法负责处理。如果Master节点找不到心跳汇报的Worker信息,则返回给Worker节点CommandType.Register命令。如果有需要释放的内存,则Master返回给Worker节点CommandType.Free命令。否则返回给CommandType.Nothing命令给Worker节点。
在TachyonWorker心跳汇报过程中,可能会出现两种主要的异常:BlockInfoException和TException异常。
(1)如果出现BlockInfoException,则在TachyonWorker中调用WorkerStorage.checkStatus()方法,如果此时继续心跳的条件仍然成立,即mStop为false,则继续循环进行心跳汇报。
(2)如果出现TException,则在TachyonWorker中调用WorkerStorage的resetMasterClient方法进行重置MasterClient对象,利用connect方法连接Thrift服务端。需要注意的是,Worker心跳超时判断,默认超时时间为10秒,如果超时,则抛出RuntimeException,心跳线程直接就挂掉了;如果没有心跳超时,则继续进行WorkerStorage的checkStatus,重新检查心跳条件,进入下次心跳。
Master节点在初始化的时候会创建Journal目录,如果底层文件系统是HDFS的话,那就直接在HDFS上创建对应的目录,并且需要格式化(这里的格式化实际上是创建一个空的文件用于标注Format完毕)。
Tachyon的文件系统信息依靠Edits日志 + Fsimage镜像保存(分别是image.data文件和log.data文件),Edits日志是Tachyon文件系统的元数据信息的增量Log,Fsimage是在某个时刻的快照。Tachyon Master在启动时会首先从Fsimage文件中读取文件系统元数据信息,即各种数据节点(文件、目录、Raw表、Checkpoint、依赖关系等)信息,然后再从继续Edits(可能多个)中读取增量操作记录,Edits日志的内容基本对应于Tachyon文件系统Client的一些相关操作,包括文件的添加,删除,重命名,数据块的添加等。但是这里的Edits日志不包括实际的文件内容数据,只是元数据信息,当Cache中的文件内容丢失,而又没有持久化,也没有绑定相关lineage信息时,对应的文件的内容就会丢失。搞定完这些,Tachyon Master会先把当前的元数据信息写出为新的Fsimage。
采用Zookeeper作为Master的HA实现机制的时候,处于Standby角色的Master会定期将Editlog合并,并创建Standby的Fsimage,如果没有Standby的Master则只有在启动过程中,才会通过合并EditsLog产生新的Fsimage。
Master的Active选举,通过LeaderSelectorClient类来完成,如果当前Master被选举为Leader,则停止EditsLog的滚动,调用MasterInfo的init方法进行初始化相关参数,进而启动Web的服务UIWebServer(Standby状态的Master没有WebUI服务),接着初始化Master的服务处理对象MasterServiceHandler并启动Thrift服务。
需要注意的是:
(1) JOURNAL的路径、格式化文件前缀、service和web的ip及端口的设定都是在MasterConf类中设置的;
(2) MasterInfo的init方法会依次做如下事情:
Step1:加载EditsLog文件到内存
Step2:创建新的镜像文件
Step3:创建新的EditsLog日志文件
Step4: 创建心跳汇报器MasterInfoHeartbeatExecutor并启动
Step5: 创建文件丢失恢复器RecomputationScheduler并启动
(3)Master也有心跳,只不过是做周期性的系统状态检查
Step1:获取超时的worker列表BlockingQueue,从Master端的Worker存储列表中删除
Step2:尝试从超时worker列表中恢复丢失的文件
Step3:重启所有超时的worker列表,这一点很重要!
(4)Master在Zookeeper中会创建两个节点,分别是election节点,在其下面子节点是CreateMode.EPHEMERAL_SEQUENTIAL类型的,即临时节点;leader节点,在其下的子节点是CreateMode.PERSISTENT类型的,用于维护当前存活的Master节点信息。
(5) 由于当前Active Master可能是变化的,所以Worker进行选择Master进行通信的时候,需要首先从Zookeeper中的leader目录下取出所有的Master节点进行遍历,如果只有一个Master,则直接返回,否则,查找出cTime最大的那个Master作为当前的Active节点,由Worker节点负责和它通信。而Worker端在进行心跳汇报的时候,会重试五次,仍然失败则抛出异常TException,由TachyonWorker的run方法catch,调用resetMasterClient方法进行重新设置,每次connect的时候都会从Zookeeper中获取最新的Active Master地址,如果一段时间后仍然连接不上master,则停止心跳,通过调用cleanConnect方法。
-------------------------------------------------------------------------------
如果您看了本篇博客,觉得对您有所收获,请点击右下角的 [推荐]
如果您想转载本博客,请注明出处
如果您对本文有意见或者建议,欢迎留言
感谢您的阅读,请关注我的后续博客