2017-07-15 45 views
0

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

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

记录2: “{” ID “:” some_compound_key”, “结果”: “PASS”, “域”: “B”}

你可以看到,不仅是架构不同,但它实际上是冲突的(id是第一个记录中的一个整数,第二个中是一个字符串)。

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

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

1)继续使用Logstash - 可以对每个域需要的转换管道进行建模,使用一组Logstash过滤器和条件。
由于Logstash在运行时定期重新加载配置,所以维护和部署也很容易,所以要更改/添加转换逻辑,我们只需要在conf目录中放置一个新的配置文件。
但是,不利的一面是,使用Logstash从外部来源丰富数据非常困难。

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

3)使用Spark Streaming - 我们已经使用Spark进行批处理,所以如果我们可以使用Spark进行流式传输以保持我们的堆栈尽可能简单,那将是非常好的。
但是,我不确定Spark是否甚至可以支持没有单个模式的流式数据,也不能确定是否可以按行执行转换。
我见过的所有例子(以及我们自己的Spark批处理经验)都假设数据有一个定义良好的模式,这不是我们的用例。

任何人都可以通过Spark Streaming(或Structured Streaming)了解我们需要的是否可能,或者我们应该坚持Logstash/Kafka Streams吗?

回答

1

声明:我是Kafka Streams的积极贡献者。

我对Logstash并不熟悉,但从您所描述的内容来看,它似乎是最不具吸引力的解决方案。

关于Spark Streaming。即使我不是它的忠实粉丝,我相信你可以做你想做的处理。根据我的理解,结构化数据流无法工作,因为它需要固定的模式,但Spark Streaming应该更加灵活。然而,与Kafka Streams相比,使用Spark Streaming并不会让它更简单(但最有可能更难)。我没有在生产中运行Spark Streaming的个人经验,但我听到很多关于不稳定性的抱怨等。

关于您指出的Kafka Streams的“缺点”。 (1)我不确定为什么你需要代码生成等等。(2),为什么Spark Streaming中的这些有什么不同?你需要在两种情况下编写你的转换逻辑,如果你想改变它,你需要重新部署。我也相信,与Spark Streaming相比,通过“滚动反弹”更新Kafka Streams应用程序更容易,并且允许零停机时间,您需要停止它们之间的处理。

这将有助于了解什么是“在运行时修改代码”,以便在此处给出更详细的答案。

+0

就可管理性而言,Kafka Streams和Spark Streaming之间没有什么区别 - 两者都需要重新编译应用程序并重新部署它 - 这是我们希望尽可能避免的,并找到一种方法来支持添加新的lambda函数例如,运行时。 我同意Kafka Streams更灵活 - 因为每个流应用程序都是独立的,所以我们可以通过添加更多的容器化实例来轻松地扩展/缩小它们,这是我们无法轻松使用Spark的。 关于滚动反弹,你也提出了一个很好的观点 - 我没有考虑它:-) 谢谢! –