我刚刚开始讨论实时流数据处理框架的主题,我有一个问题,到目前为止还找不到任何结论性的答案:
常见的嫌疑犯(Apache的Spark、Kafka、Storm、Flink等)是否支持处理事件时间分辨率为纳秒(甚至皮秒)的数据?
大多数人和文档都在谈论毫秒或微秒的分辨率,但我无法找到一个确切的答案,如果有更多的分辨率或问题的话。我推断唯一有能力的框架是influxData的Kapacitor框架,因为他们的TSDB influxDB似乎以纳秒分辨率存储时间戳。
这里有人能对此提供一些见解,甚至提供一些知情的事实吗?提供此功能的替代解决方案/框架?
任何东西都将不胜感激!
谢谢和问候,
Simon
我的问题背景:我在一个拥有大量数据存储和处理专有实现的环境中工作,目前正在考虑一些组织/优化。我们正在用许多不同的诊断/测量系统以不同的采样率进行等离子体物理实验,现在的采样率高达"每秒千兆样本以上"。在我们的系统中,一个常见的事实/假设是,每个样本都有一个以纳秒分辨率记录的事件时间。当试图使用已建立的流(或批处理)处理框架时,我们必须保持这种时间戳分辨率。或者更进一步,因为我们最近在一些系统中突破了1Gsps的阈值。因此,我提出了这个问题。
如果这一点不清楚,您应该注意事件时间和处理时间之间的差异:
事件时间-在源生成事件的时间
处理时间-处理引擎内事件执行的时间
src:Flink docs
AFAIK Storm不支持事件时间,Spark的支持有限。这就需要考虑卡夫卡流和Flink。
Flink使用长类型作为时间戳。文档中提到,该值是自1970-01-01T00:00:00Z以来的毫秒数,但AFAIK,当您使用事件时间特征时,唯一衡量进度的指标是事件时间戳。因此,如果你能将你的价值观纳入长期范围,那么这应该是可行的。
编辑:
通常,水印(基于时间戳)用于测量窗口、触发器等中事件时间的进度。因此,如果您使用:
-
AssignerWithPeriodicWatermarks则在处理时域的配置中定义的间隔(自动水印间隔)中发出新的水印,即使使用了事件时间特征。有关详细信息,请参见例如
org.apache.flink.streaming.runtime.operators.TimestampsAndPeriodicWatermarksOperator#open()
方法,其中注册了处理时间中的计时器。因此,如果自动水印设置为500ms,则每500ms的处理时间(从System.currentTimeMillis()
获取)就会发出一个新的水印,但水印的时间戳基于事件的时间戳。 -
带有标点水印的Assigner则可以在文档中找到
org.apache.flink.streaming.api.datastream.DataStream#assignTimestampsAndWatermarks(org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks<T>)
:的最佳描述
为数据流中的元素分配时间戳,并根据元素本身创建水印以表示事件时间进度。
此方法纯粹基于流元素创建水印对于通过
AssignerWithPunctuatedWatermarks#extractTimestamp(Object, long)
处理的每个元素,如果返回的水印值为非负且大于上一个水印,则会调用AssignerWithPunctuatedWatermarks#checkAndGetNextWatermark(Object, long)
方法,并发出新的水印。当数据流嵌入水印元素,或者某些元素携带可用于确定当前事件时间水印的标记时,此方法非常有用此操作使程序员能够完全控制水印的生成用户应该意识到,过于激进的水印生成(即每秒生成数百个水印)可能会降低一些性能。
要了解水印是如何工作的,强烈建议阅读以下内容:Tyler Akidau on Streaming 102
虽然Kafka Streams使用毫秒分辨率,但运行时实际上有点不可知。最后它只是很长。
话虽如此,"问题"在于时间窗口的定义。如果指定的时间窗口为1分钟,但时间戳分辨率小于毫秒,则窗口将小于1分钟。作为一种变通方法,您可以将窗口设置得更大,例如1000分钟或1000000分钟,以获得微秒/纳秒的分辨率。
另一个"问题"是,代理只了解毫秒分辨率,而保留时间正是基于此。因此,您需要将保留时间设置得更高,以"欺骗"代理并避免它过早删除数据。