zoukankan      html  css  js  c++  java
  • Spark Streaming揭秘 Day32 WAL框架及实现

    Spark Streaming揭秘 Day32

    WAL框架及实现

    今天会聚焦于SparkStreaming中非常重要的数据安全机制WAL(预写日志)。

    设计要点

    从本质点说,WAL框架是一个存储系统,可以简单的认为是一个文件系统,其作用类似于BlockManager,
    我们首先看一下官方的说明:
    Snip20160710_53

    这里有三个要点:

    1. 总体上,sparksteaming是用WAL去保存接收到的数据,并且在写入数据后,要把元数据汇报给Driver,这样失败了才能恢复起来。
    2. 每当写入一个log,就返回一个handle,handle包含所有的从写入后的记录中恢复回原来数据的所有信息,和blockManager是一样的,使用时间来索引record,所以在sparkstreaming,WAL是顺序读写的。这个时间也方便我们进行清理(会有一个自己的超时时间)。具体的子类,必须确保数据是可持久化和可读取的。
    3. 为什么选择顺序写,是因为在数据备份的时候,效率会比较高。当读的时候,采用一块一块的读,而不是一条一条的读,找数据的时候,需要找到起始点,并结合数据长度来批量读取,而不是读一条,找一条。可以极大的节省读取的时间。

    总体结构

    WriteAheadLog作为一个抽象类,主要提供一些操作的方法,并没有说明如何对数据本身如何进行操作。因为具体的操作往往会涉及底层的存储系统。这种写法,可以使客户端依赖于抽象,而不是依赖于具体,既方便使用者,也方便开发者。最为关键的是下面三个方法:
    Snip20160710_54

    1. write方法,输入一个ByteBuffer,ByteBuffer只是个很简单的java类,里面封装了一个字节数组。
    2. read方法,基于handle,读取我们要读取的记录。
    3. clean方法,threshTime是一个阀值,在之前的数据会被清理掉。

    那handle里是啥呢,其实非常简单,WriteAheadLogRecordHandle也是抽象的。具体实现在FileBasedWriteAheadLogSegment:
    Snip20160710_55
    这是个case class,只是保存了三个信息,数据文件路径、位置以及数据长度。

    WriteAheadLog实现

    FileBasedWriteAheadLog是WriteAheadLog一般情况下的实现。

    让我们看下说明,在管理WAL文件时,会把数据周期性的写入日志文件中。当失败时,会从文件中恢复数据。
    这里的关键是rolling的管理方式,这是写数据的一种特征,写log的时候,每隔一段时间,就把已经在写的文件关闭掉,再产生新的文件保存新的数据。这种方式的好处是:

    1. 写的文件,单个文件不会太大。
    2. 删除数据比较方便。

    Snip20160710_56

    currentLogWriter是WAL中的关键,专门来写数据到log file中,一个文件会对应一个writer,产生新的文件就会有新的writer。实际存数据时是放在checkpoint Directory下的。
    Snip20160710_57

    write方法,是写入数据到hadoop支持的文件系统中,并且会确保数据已经到了文件系统中。其中会根据时间获取writer来写入数据。
    Snip20160710_58

    其中,getLogWriter放大,会根据时间,生成writer,从代码看,会按照时间分段来生成新文件。这是实现rolling方式的关键。
    Snip20160710_59

    read方法,根据file segment来读数据,所以实际读数据时是一批一批读的。
    Snip20160710_60

    intitializeOrRecover方法也是关键,在启动时调用,会根据文件信息恢复pastLogs,也就是说在记录log文件时,文件是自解释的,包含开始时间、结束时间和路径。
    Snip20160710_61

    Writer和Reader实现

    FileBasedWriteAheadLogWriter负责将数据写入日志文件中。

    Snip20160710_62

    每次把数据写完的时候,都会记录offset和length。flush会调用文件系统的方法,优先使用hflush方法,否则使用sync方法。

    FileBasedWriteAheadLogRandomReader是reader的默认实现,会根据给定handle返回block。

    Snip20160710_63

    首先会使用seek方法跳到索引位置,此后采用原生字节操作进行读取,同时会加锁,返回时用HeapByteBuffer封装起来。

    除了random的方式,还有一种顺序读的方式FileBasedWriteAheadLogReader,采用了迭代器来封装,数据在hasNext中产生,next方法只是读取结果。

    WAL触发机制

    那么,WAL机制在SparkStreaming框架中是如何触发的呢?

    首先,在接收数据后,会判断是不是要进行WAL操作。
    Snip20160710_64

    在构造时,createLog方法默认情况,就是创建了FileBasedWriteAheadLog,需要注意的是在WAL方式下数据副本只能有一个。
    Snip20160710_65

    storeBlock方法中实际触发操作,这里构建了一个future(和blockManager是并行执行),将数据写入WAL,在执行后会返回了handle并进行登记。
    Snip20160710_67

    总结的来说,WAL比普通的文件操作,增加了时间的维度和索引位置两个因素,两个加起来形成了WAL框架。

    欲知后事如何,且听下回分解!

    DT大数据每天晚上20:00YY频道现场授课频道68917580

  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/dt-zhw/p/5658501.html
Copyright © 2011-2022 走看看