Apache spark 使用无模式数据的Spark流

Apache spark 使用无模式数据的Spark流,apache-spark,spark-streaming,apache-kafka-streams,Apache Spark,Spark Streaming,Apache Kafka Streams,我们目前有一个数据管道设置,使用Logstash从单个卡夫卡主题中读取原始数据,并将其写入ElasticSearch。 本主题中的数据是JSON格式的,但每一行可以属于完全不同的业务域,因此可能具有完全不同的模式。例如: 记录1:“{”id:1,“model”:“model2”,“updated”:“2017-01-1T000:00:00.000Z”,“domain”:“A”} 记录2:“{”id:“某些复合键”,“结果”:“通过”,“域”:“B”} 您可以看到,模式不仅不同,而且实际上是冲突的

我们目前有一个数据管道设置,使用Logstash从单个卡夫卡主题中读取原始数据,并将其写入ElasticSearch。
本主题中的数据是JSON格式的,但每一行可以属于完全不同的业务域,因此可能具有完全不同的模式。例如:

记录1:“{”id:1,“model”:“model2”,“updated”:“2017-01-1T000:00:00.000Z”,“domain”:“A”}

记录2:“{”id:“某些复合键”,“结果”:“通过”,“域”:“B”}

您可以看到,模式不仅不同,而且实际上是冲突的(id在第一条记录中是一个整数,在第二条记录中是一个字符串)

只有两个保证-每个记录都是有效的JSON记录,并且每个记录都有一个“域”字段。即使具有相同域值的记录有时也可能具有不同的模式

我们现在需要在数据通过管道时对其进行丰富和转换(而不是稍后使用ETL),我们正在研究几种实现方法。需要注意的是,由于数据没有统一的模式,因此需要逐行进行转换:

1) 继续使用Logstash-可以使用一组Logstash筛选器和条件对每个域所需的转换管道进行建模。
由于Logstash在运行时定期重新加载配置,因此维护和部署也很容易,因此要更改/添加转换逻辑,我们只需要在conf目录中放置一个新的配置文件。
然而,缺点是很难用外部来源的日志来丰富数据

2) 使用Kafka流-这似乎是一个明显的选择,因为它与Kafka集成良好,允许连接来自多个流(或外部源)的数据,并且没有架构要求-很容易逐行转换数据。
这里的缺点是很难在运行时修改转换逻辑-我们需要重新编译和重新部署应用程序,或者使用一些API在运行时生成和编译Java代码,或者其他一些复杂的解决方案来包装它

3) 使用Spark流式处理-我们已经在使用Spark进行批处理,因此如果我们也可以将其用于流式处理,以使堆栈尽可能简单,那就太好了。
但是,我不确定Spark是否能够支持没有单一模式的流式数据,也不确定是否能够在每行的基础上执行转换。
我看到的所有示例(以及我们自己的Spark批处理经验)都假设数据具有定义良好的模式,这不是我们的用例

谁能告诉我们,我们需要的是Spark流媒体(或结构化流媒体)还是Logstash/Kafka流媒体

免责声明:我是卡夫卡流的积极贡献者

我不熟悉Logstash,但从您描述的情况来看,它似乎是最没有吸引力的解决方案

关于火花流。即使我不是它的超级粉丝,我相信你可以用它做你想做的处理。根据我的理解,结构化流式传输不起作用,因为它需要一个固定的模式,但Spark流式传输应该更加灵活。然而,与卡夫卡流相比,使用Spark流并不会使它更简单(但很可能更难)。我个人没有在制作中运行Spark Streaming的经验,但我听到很多关于不稳定等的抱怨

关于你指出的卡夫卡流的“缺点”。(1) 我不知道你为什么需要代码生成等(2),为什么这会在火花流有任何不同?在这两种情况下,您都需要编写转换逻辑,如果您想更改它,则需要重新部署。我还相信,通过“滚动反弹”更新Kafka Streams应用程序比Spark Streaming更容易,并允许零停机时间,而Spark Streaming则需要在其间停止处理


了解什么是“运行时代码修改”会很有帮助为了给出更详细的答案,您需要这样做。

Kafka Streams和Spark Streams在可管理性方面没有区别-都需要重新编译应用程序并重新部署它-这是我们希望尽可能避免的事情,并找到一种支持在运行时添加新lambda函数的方法,例如我同意Kafka Streams更灵活——因为每个流应用程序都是独立的,我们可以通过添加更多的容器化实例来轻松地放大/缩小它们,而使用Spark则无法做到这一点。关于滚动反弹,您也提出了一个很好的观点-我还没有考虑:-)谢谢!“spark结构化流媒体需要架构”是有争议的。我们在prod上部署了对架构完全不可知的管道。@疑难解答如何实现?@VictorIronde,如果您不需要反序列化有效负载(请注意,您可以使用JSON库检查有效负载中的任何字段),则任何spark管道都可以使架构不可知。对于JSON,我们使用io.gatling.jsonpath来查找消息中的特定字段,从Spark的角度来看,这已经足够了。