汪迎春 2012-08-30
原文请参:
https://issues.apache.org/jira/browse/HDFS-1580
https://issues.apache.org/jira/secure/attachment/12481883/EditlogInterface.3.pdf
https://issues.apache.org/jira/secure/attachment/12474635/generic_wal_iface.pdf
1、接口定义
abstract class JournalFactory {
JournalFactory(Configuration conf);
void close();
boolean available();
void format();
// get past logfiles
List<URI> getLogs(long sinceTransactionId);
// Streams
EditLogInputStream getInputStream(URI);
EditLogOutputStream getOutputStream(URI);
}
class EditLogOutputStream {
...
void beginRoll(long txid) throws IOException;
void endRoll() throws IOException;
abstract void write(long txid, byte op, Writable ... writables) throws IOException;
}
class EditLogInputStream {
...
void getLayoutVersion() throws IOException;
}
JournalFactory负责管理StrorageDevice(SD),SD可以存储多个Wal。例如:目录edits_dir可以存储edits,edits.new,在hdfs-1073之后,还可以存储edits.{txid-txid}。
FileJournalFactory管理文件SD,容许client访问Storage中的logs
URI可以定位logs,client可以使用URI来打开。
FSEditLog包含一个EditLogOutputStream列表,这个列表都是从JournalFactory中构建出来的
1、1 format()
FSEditLog.format()负责将所有URI指定的dir进行初始化,但是它是通过调用所有URI的factory的format来进行初始化的,以便底层的Storage可以创建流进行logging日志。如果是FileJournalFactory,其format是一个stun,具体参加IMAGE-AND_EDITS问题部分。
1、2 Versioning
Editlog的格式也在不断的变化,所以在EditLogInputStream中加入了一个getLayoutVersion()来获取这个信息。
1、3 Error handling
当底层的Storage出错时,该Stream会被删除,一般过程是,EditLogOutputStream在写入时,抛出异常,Editlog接受异常并将stream从activeStreams中删除。FSEditLog会在roll的时候尝试读取该删除的流
1、4 Rolling
EditLogOutputStream.roll()会保证所有所有的txid在roll之前都已经提交了
2 Configuring custom WAL
目前NN通过dfs.namenode.edits.dir来指定一个URI列表作为Editlog的目录,而使用dfs.namenode.edits.plugin.<PLUGIN>来指定一个JournalFactory的实现去初始化这个URI指定的目录。
<property>
<name>dfs.namenode.edits.dir</name>
<value>mywal://foobar/etc/etc</value>
<description>Location of editlog.</description>
</property>
<property>
<name>dfs.namenode.edits.plugin.mywal</name>
<value>com.mycompany.hdfs.MyWalJournalFactory</value>
<description>Journal Factory implementation.</description>
</property>
Factory的构造函数中需要conf和URI列表两个
3 FileJournalManager
FileJournalManager作为一个特殊用例对待,当URI的sechma是file://开始的时候
4 Transferring logs to checkpointer
现在的Checkpointer需要通过http下载image和edits,在这个设计之后,只需下载image即可。当需要load edits的时候,JournalFactory.getLogs将会返回一个URI列表,然后通过使用JournalFactory.getInputStream()来打开,如果是FileJournalFactory,getInputStream会来检查该URI是本地还是remote的,如果是remote的会先通过http下载到本地
5 Modifications to FSImage
5、1 format
FSImage增加一个format方法,用来format一下NNStorage和Editlog
5、2 loadFSImage()
目前loadFSImage会遍历所有的SD获取他们的Checkpoint time。在这个设计之后,loadFSImage只会到IMAGE类型的SD并且调用FSEditLog.getLogs(),并将返回的URI加载到Namesystem。
5、3 recoverInterruptedCheckpoint
这个先留着,本意是通过家产edits.new的存在性来判断Checkpointing过程是否在完成之前被中止了。HDFS-1073将会包这个给干掉,它通过将文件上传到一个零时文件,然后原子性的重命名。
6 The IMAGE_AND_EDITS problem
FileJournalFactory.format()仅仅是一个stub,因为现在的FSImage有一种IAMGE_AND_EDITS的SD,如果FSImage格式化所有的IMAGE类型的SD,FSEdit格式化所有的EDITS类型的SD,那么两者都会format上述的IMAGE_AND_EDITS的SD。所以这个事情留给FSImage去做。
7 Backup namenode functionallity
当前BN在FSImage and FSNamesystem,都有一些特殊的对待,这个设计中也先不管了。
BN的stream初始化和清理都在logJSpoolStart和releaseBackupStream中完成。
FSEditLog遍历所有的EDITS目录来做roll,有了close和获取新stream的方法之后,BackupStreams显然没有必要也去遍历。
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。以上实例中 7、5 和 12 是操作数。关系运算符用于计算结果是否为 true 或者 false。逻辑运算符用于测定变量或值之间的逻辑。