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