zl程序教程

您现在的位置是:首页 >  工具

当前栏目

HDFS源码分析之编辑日志编辑相关双缓冲区EditsDoubleBuffer

日志源码HDFS 分析 相关 编辑 缓冲区
2023-09-27 14:29:33 时间

        EditsDoubleBuffer是为edits准备的双缓冲区。新的编辑被写入第一个缓冲区,同时第二个缓冲区可以被flush。为edits准备的双缓冲区。新的编辑被写入第一个缓冲区,同时第二个缓冲区可以被flush。在其内部,有两个重要的缓冲区成员变量,如下:

 // 当前被写入的缓冲区bufCurrent

 private TxnBuffer bufCurrent; // current buffer for writing

 // 正在进行flush的缓冲区bufReady

 private TxnBuffer bufReady; // buffer ready for flushing

 // 初始化缓冲区大小initBufferSize

 private final int initBufferSize;
        其中,bufCurrent是当前被写入的缓冲区,当前被写入的缓冲区是正在进行flush的缓冲区,而initBufferSize则是初始化缓冲区大小。我们再看下EditsDoubleBuffer的构造函数,如下:

 // 构造函数

 public EditsDoubleBuffer(int defaultBufferSize) {

 // 根据入参赋值initBufferSizeinitBufferSize

 initBufferSize = defaultBufferSize;

 // 创建当前被写入的缓冲区bufCurrent

 bufCurrent = new TxnBuffer(initBufferSize);

 // 创建正在进行flush的缓冲区bufReady

 bufReady = new TxnBuffer(initBufferSize);

 }
        根据入参赋值initBufferSizeinitBufferSize,然后分别创建上述两个缓冲区:创建当前被写入的缓冲区bufCurrent、创建正在进行flush的缓冲区bufReady。

        而EditsDoubleBuffer最基本的写入功能有两个,一个是用于写入操作符的writeOp()方法,另外一个就是用于写入事务的writeRaw()方法,代码分别如下:

 // 写入操作符至bufCurrent

 public void writeOp(FSEditLogOp op) throws IOException {

 bufCurrent.writeOp(op);

 // 写入事务至bufCurrent

 public void writeRaw(byte[] bytes, int offset, int length) throws IOException {

 bufCurrent.write(bytes, offset, length);

 }
        均是将操作符或事物写入bufCurrent缓冲区。而在准备flush前,需要先调用setReadyToFlush()方法,设置缓冲区可以进行flush,代码如下:

 // 设置双缓冲区为可以进行flsuh

 public void setReadyToFlush() {

 // 确保之前的数据已经被flush完毕,调用isFlushed()方法判断bufReady的大小是否为0即可

 assert isFlushed() : "previous data not flushed yet";

 // 交换bufReady、bufCurrent

 TxnBuffer tmp = bufReady;

 bufReady = bufCurrent;

 bufCurrent = tmp;

 }
        它首先会确保之前的数据已经被flush完毕,调用isFlushed()方法判断bufReady的大小是否为0即可,然后交换bufReady、bufCurrent。

        接着,我们需要调用flushTo()方法,将bufReady的内容写入指定输出流,并清空bufReady。此时不交换任何缓冲区,代码如下:

 /**

 * Writes the content of the "ready" buffer to the given output stream,

 * and resets it. Does not swap any buffers.

 * 将bufReady的内容写入指定输出流,并清空bufReady。此时不交换任何缓冲区。

 public void flushTo(OutputStream out) throws IOException {

 bufReady.writeTo(out); // write data to file

 bufReady.reset(); // erase all data in the buffer

 }
        而bufCurrent、bufReady都是一个TxnBuffer类型的缓冲区,这个TxnBuffer是对DataOutputBuffer的一个封装,保存了第一个事务艾迪firstTxId、事务数量numTxns、写入者writer等变量,它主要的两个方法,一个是写入操作符的writeOp()方法,实现如下:

 // 写入操作符

 public void writeOp(FSEditLogOp op) throws IOException {

 // 首次事务艾迪firstTxId被赋值为操作符的事务ID

 if (firstTxId == HdfsConstants.INVALID_TXID) {

 firstTxId = op.txid;

 } else {

 // 之后确保操作符的事务ID永远大于首次事务ID

 assert op.txid firstTxId;

 // 调用writer写入操作符

 writer.writeOp(op);

 // 事务数量numTxns累加

 numTxns++;

 }
        首次事务艾迪firstTxId被赋值为操作符的事务ID,之后确保操作符的事务ID永远大于首次事务ID,然后调用writer写入操作符,并将事务数量numTxns累加。







Hhadoop-2.7.0中HDFS写文件源码分析(二):客户端实现(1)       HDFS写文件是整个Hadoop中最为复杂的流程之一,它涉及到HDFS中NameNode、DataNode、DFSClient等众多角色的分工与合作。       首先上一段代码,客户端是如何写文件的: Configuration conf = new Configuration(); FileSystem fs = FileSystem.
HDFS源码分析之FSImage文件内容(一)总体格式         FSImage文件是HDFS中名字节点NameNode上文件/目录元数据在特定某一时刻的持久化存储文件。它的作用不言而喻,在HA出现之前,NameNode因为各种原因宕机后,若要恢复或在其他机器上重启NameNode,重新组织元数据,就需要加载对应的FSImage文件、FSEditLog文件,并在内存中重做FSEditLog文件中的事务条目。
HDFS源码分析数据块校验之DataBlockScanner         DataBlockScanner是运行在数据节点DataNode上的一个后台线程。它为所有的块池管理块扫描。针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独的线程中,为该块池扫描、校验数据块。
        数据块的复制当然需要一个源数据节点,从其上拷贝数据块至目标数据节点。那么数据块复制是如何选取复制源节点的呢?本文我们将针对这一问题进行研究。         在BlockManager中,chooseSourceDatanode()方法就是用来选取数据块复制时的源节点的,它负责解析数据块所属数据节点列表,并选择一个,用它作为数据块的复制源。
        ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列。其定义及作为线程核心的run()方法如下: * Periodically calls computeReplicationWork().