在Provenance存储库中存储每个FlowFile的历史记录。此历史记录用于提供每个数据的数据沿袭(也称为产销监管链)。每次为FlowFile发生事件(创建,分叉,克隆,修改FlowFile等)时,都会创建一个新的Provenance事件。这个出处事件是流文件的快照,因为它看起来就是在那个时间点存在的流。创建Provenance事件后,它将复制所有FlowFile的属性和指向FlowFile内容的指针,并将其与FlowFile的状态(例如其与其他出处事件的关系)聚合到Provenance存储库里。该快照将不会更改,直到过期。根据“nifi.properties”文件中的指定,Provenance存储库将在完成后的一段时间内保留所有这些来源事件。
因为所有流文件属性和指向内容的指针都保存在Provenance存储库中,所以数据流管理器不仅能够查看该数据段的沿袭或处理历史,而且能够在以后查看数据本身,甚至从流中的任何点重放数据。一个常见的用例是当一个特定的下游系统声称没有收到数据时。数据沿袭可以准确地显示数据何时传递到下游系统、数据的外观、文件名以及数据发送到的URL,或者可以确认数据确实从未发送过。在这两种情况下,都可以通过单击按钮(或通过访问适当的http api)来重播Send事件,以便仅向特定的下游系统重新发送数据。或者,如果数据处理不当(可能应该先进行一些数据操作),则可以修复流,然后将数据重放到新流中,以便正确处理数据。
不过,请记住,由于Provenance并不是复制content Repo中的内容,而只是复制FlowFile指向该内容的指针,因此可以在删除引用该内容的Provenance事件之前删除该内容。这意味着用户以后将无法再看到内容或重放流文件。但是,用户仍然能够查看流文件的沿袭并了解数据发生了什么。例如,即使数据本身无法访问,用户仍然能够看到数据的唯一标识符、文件名(如果适用)、何时接收、从何处接收、如何操作、发送到何处等等。此外,由于FlowFile的属性是可用的,因此Dataflow管理器能够理解为什么数据按原来的方式处理,从而为理解和调试数据流提供了一个关键工具。
由于Provenance是流文件的快照,因为它存在于当前流中,因此对流的更改可能会影响以后重播源事件的能力。例如,如果从流中删除了连接,则无法从流中的该点重放数据,因为现在没有地方将数据排队等待处理。
每个Provenance都有两个map,一个用于事件之前的attributes,另一个用于更新后的attributes。一般来说,Provenance事件不存储属性的更新值,因为它们在发出事件时就存在,而是在提交会话时存储属性值(session.commit()
)。事件被缓存并保存,直到会话被提交为止,一旦会话被提交,当会话被提交时,事件将与流文件相关联的属性一起发出。此规则的例外是“SEND”事件,在这种情况下,事件包含的属性与事件发出时的属性相同。这样做是因为,如果还发送了属性本身,那么准确地知道发送了什么信息就很重要。
在运行NiFi时,会有16个Provenance日志文件的滚动组。发出事件源时,它们将被写入16个文件之一(有多个文件可提高吞吐量)。日志文件会定期滚动(默认时间范围是每30秒一次)。这意味着新创建的Provenance事件将开始写入由16个日志文件组成的新组,并且原始文件将被处理以进行长期存储。首先,将经过滚动的日志合并到一个文件中。然后,可以选择对文件进行压缩(由nifi.provenance.repository.compress.on.rollover
属性确定)。最后,使用Lucene
对事件进行索引并使其可用于查询。这种分批编制索引的方法意味着无法立即提供Provenance事件以进行查询,但是作为回报,这大大提高了性能,因为提交事务和建立索引是非常昂贵的任务。
一个单独的线程负责处理出处日志的删除。管理员可以设置两个条件来控制出处日志的删除,即可以占用的最大磁盘空间量和日志的最大保留期限。该线程按上次修改日期对存储库进行排序,并在超过其中一个条件时删除最旧的文件。
Provenance存储库使用了Lucene索引,分为多个碎片。这样做有多种原因。首先,Lucene使用32位整数作为文档标识符,因此限制了Lucene不分片支持的最大文档数量。其次,如果我们知道每个分片的时间范围,则可以轻松地使用多个线程进行搜索。而且,这种分片还允许更有效的删除。NiFi会等到计划删除某个分片中的所有事件,然后再从磁盘删除整个分片。这使得删除时我们不必更新Lucene索引。
Provenance Event Log File
中。发生这种情况时,我们会滚动日志,以便其他线程可以同时更新存储库。.toc
(目录表)文件保留为“压缩块偏移”的映射。此偏移量是此事件块开始的文件中的偏移量。这样,当我们为事件建立索引时,我们就可以为相关字段以及数据指针建立索引。指向数据的指针是数据存储在其中的源事件日志文件,事件ID和压缩块偏移量。结果,如果我们有一个Provenance Event Log File
,即压缩后为1 GB,并且想要从中获取特定记录,我们可以简单地查找到块偏移量(例如980,028,872),然后用GZIPInputStream包装FileInputStream。然后从那里开始阅读。我们将最多只能读取1 MB的(解压缩)数据。这使我们可以非常快速地访问这些记录。Provenance Event Log File
(压缩的事件日志文件),进行压缩并建立索引后,我们将删除原始日记文件。Provenance Event Log File
(相关性基于文件名),那么我们知道重新启动时我们正在对索引文件进行索引和合并,因此我们需要完成该工作。我们无法轻易知道我们从何处中断,因此我们只需要删除Provenance Event Log File
并删除该事件文件的索引中的任何记录即可。然后,我们重新开始合并文件建索引。Provenance Event Log File
中的最大事件ID。Provenance Event Log File
中,所以我们能够顺序写入事件。Provenance Event Log File
的名称应使文件名反映文件中第一个事件的事件ID。Provenance Event Log File
是否早于配置的最大时间限制。如果是这样,我们会将其标记为销毁。Provenance Event Log File
的事件。