传统消息代理和流数据


13

根据Kafka网站

Kakfa用于构建实时数据管道和流应用程序。

在广泛的互联网上搜索,我发现以下“ 流数据 ”是什么?

  • 流数据是通过网络从源连续地流到目的地的数据。和
  • 流数据本质上不是原子的,这意味着流的数据流的任何部分都是有意义的和可处理的,与文件的字节相反,除非您拥有全部字节,否则它什么都没有。和
  • 流数据可以随时启动/停止;和
  • 消费者可以随意附加和分离数据流,并只处理他们想要的部分数据

现在,如果我上面所说的任何内容不正确,不完整或完全错误,请先纠正我!假设我或多或少都在轨道上,那么...

现在,我了解了什么是“流数据”,然后,我了解了Kafka和Kinesis在将自己称为具有流数据的应用程序的处理/中介中间件时的含义。但这激起了我的兴趣:可以/应该像传统的消息代理一样,将Kafka或Kinesis之类的“流中间件”用于非流数据吗?反之亦然:是否可以/应该使用RabbitMQ,ActiveMQ,Apollo等传统MQ来传输数据?

让我们以一个示例为例,其中应用程序将发送其后端常量的需要处理的JSON消息,并且处理过程相当复杂(验证,数据转换,过滤,聚合等):

  • 情况1:消息是电影的每一帧;每个视频帧包含一个JSON消息,其中包含帧数据和一些支持的元数据
  • 情况2:消息是时间序列数据,可能是某人的心跳随时间变化的函数。因此,发送了#1表示我在t = 1时的心跳,消息#2包含了我在t = 2时的心跳,依此类推。
  • 情况3:数据是完全不同的,并且按时间或作为任何“数据流”的一部分不相关。可能随着数百名用户导航应用程序的单击按钮并采取措施而引发的审核/安全事件

根据Kafka / Kinesis的结算方式以及我对“流数据”的理解,它们似乎是案例1(连续的视频数据)和案例2(连续的时间序列数据)的明显候选者。但是,我看不出任何原因,如RabbitMQ之类的传统消息代理也无法有效地处理这两种输入。

在案例3中,仅向我们提供了一个已发生的事件,我们需要处理对该事件的反应。所以对我来说,这意味着需要像RabbitMQ这样的传统经纪人。但是,也没有理由不能让Kafka或Kinesis也不能处理事件数据。

因此,基本上,我正在寻求建立一个表述:我有具有Y特征的X数据。我应该使用像Kafka / Kinesis这样的流处理器来处理它。或者,相反,它可以帮助我确定:我拥有具有Z特征的W数据。我应该使用传统的消息代理来处理它。

因此,我想问:关于数据的哪些因素(或其他因素)有助于指导流处理器或消息代理之间的决策,因为两者都可以处理流数据,并且两者都可以处理(非流)消息数据?

Answers:


5

Kafka处理原子消息的有序日志。您可以像查看pub/sub消息代理的方式那样查看它,但是具有严格的排序功能,并且能够在过去的任何时候重播或查找消息流,这些消息仍然保留在磁盘上(可能永远存在)。

Kafka的流媒体风格与Thrift或HTTP等远程过程调用以及Hadoop生态系统中的批处理相反。与RPC不同,组件是异步通信的:从发送消息到收件人唤醒并对其采取行动之间可能要花费数小时或数天的时间。在不同的时间点可能有许多收件人,或者也许没有人会费心使用一条消息。多个生产者可以在没有消费者知识的情况下生产同一主题。Kafka不知道您是否已订阅,或是否已使用邮件。一条消息只是提交给日志,任何感兴趣的人都可以在其中阅读。

与批处理不同,您不仅对大量邮件感兴趣,而且对单个邮件感兴趣。(尽管将Kafka消息归档到HDFS上的Parquet文件中并作为Hive表进行查询并不罕见)。

情况1:Kafka没有在生产者和消费者之间保留任何特殊的时间关系。由于允许Kafka放慢速度,加快速度,进行试穿和启动等操作,因此它不适合流式传输视频。对于流式媒体,我们希望平衡整体吞吐量,以换取较低的(更重要的是)稳定的延迟(否则称为低抖动)。卡夫卡还付出了巨大的努力,以永不丢失任何信息。对于流式视频,我们通常使用UDP,并且内容在此处和此处丢帧以保持视频正常运行。由Kafka支持的过程中的SLA在正常情况下通常为数秒至数分钟,在正常情况下为数小时至数天。流媒体上的SLA以数十毫秒为单位。

Netflix可以使用Kafka在内部系统中移动帧,该系统每小时可以对TB级视频进行转码并将其保存到磁盘上,但不能将其发送到屏幕上。

情况2:绝对如此。我们以这种方式在我的雇主处使用Kafka。

情况3:您可以将Kafka用于此类事情,我们也可以,但是您要付出一些不必要的开销来保持订购。由于您不关心订单,因此您可能会从其他系统中挤出更多性能。但是,如果您的公司已经维护了Kafka集群,则最好重用它,而不要承担另一个消息系统的维护负担。


1
感谢@closeparen(+1)-除了一个大的例外,我大部分都明白。在您以“ Kafka的流媒体风格反对... ” 开头的段落中,我倾向于认为我可以将“ Kafka”一词的大多数实例替换为“ RabbitMQ”,因此该句子将成立。对于RabbitMQ:生产者可以发送一条消息,而消费者可以将其拉下来并在数小时/天后对其进行处理。消费者可以随时随地附加到队列,因此对于RabbitMQ,在不同的时间点可以有许多不同的收件人。
smeeb

1
将Kafka视为具有特殊的面向日志结构的数据库引擎。生产者附加,消费者阅读。阅读不会以任何方式影响卡夫卡的状态。使用者可以维护一个递增的游标以创建与RabbitMQ pub / sub相同的语义,这是一个常见的用例,但不是唯一的用例。
closeparen

1
将RabbitMQ视为内存队列数据结构的分布式版本。一旦您将某些东西从队列中弹出,它就不再在队列中了。当然,您可能有一个拓扑,已将其复制到其他队列中以利于其他使用者,但通常无法说出“给我我之前处理过500条消息的消息”或“将队列B作为副本启动”昨天队列A所在的队列A的位置。”
closeparen

2
基于Kafka的系统是宽容的。如果您不喜欢程序的行为,可以推送代码更改,然后倒回其输入。您可以在不影响生产者的情况下停止RabbitMQ消费者,但是您将无法回顾过去。
closeparen

1
啊哈:lightbulb:谢谢(所有3个都为+1)!因此,这绝对是卡夫卡一个令人信服的案例:重新审视过去的能力。我认为必须要有一些上限或截断吗?否则,卡夫卡的记忆总是会不断攀升。即使数据溢出到磁盘上,存储主题数据的文件也会很快填满磁盘,是吗?
smeeb

5

Kafka / Kinesis被建模为流。流具有与消息不同的属性。

  • 流具有上下文。他们有秩序。您可以在流上应用窗口功能。尽管流中的每个项目都是有意义的,但围绕它的上下文可能更有意义
  • 因为流有顺序,所以您可以使用它来对处理的语义做出某些陈述。例如,从Kafka流中消费时,Apache Trident应当具有一次语义。
  • 您可以将功能应用于流。您可以转换流而不实际消耗它。您可以懒惰地消费流。您可以跳过流的一部分。
  • 您可以固有地在Kafka中重播流,但是您不能(没有其他软件)重播消息队列。当您甚至不知道要使用数据做什么时,这将很有用。这对于训练AI也很有用。

通常,将Kafka用于脱机流处理,将消息队列用于实时客户端-服务器消息。

关键的用例示例:

Kafka:网站活动跟踪,指标,日志聚合,流处理,事件源和提交日志

RabbitMQ:通用消息传递...,通常用于允许Web服务器快速响应请求,而不是在用户等待结果时被迫执行占用大量资源的过程。当您需要使用现有协议(例如AMQP 0-9-1,STOMP,MQTT和AMQP 1.0)时使用

有时同时使用两者可能很有用!例如,在用例2中,如果这是来自起搏器说的数据流,我将让起搏器将心跳数据传输到RabbitMQ消息队列(使用像MQTT这样的很酷的协议),并立即将其处理为看看来源的心脏是否仍在跳动。这可以为仪表板和紧急响应系统供电。消息队列还将时间序列数据存储到Kafka中,以便我们可以分析随时间变化的心跳数据。例如,我们可能会通过注意到心跳流中的趋势来实现一种检测心脏病的算法。


1
感谢@Samuel(+1)-这是一个很棒的答案,可以帮助您更好地理解环境。实际上,我有几个后续问题(如果您不介意的话),但是它们全都取决于我需要进行的初步澄清:当您说“ 您可以将函数应用于流。可以转换流而不实际使用它... ”,这些功能/转换是在Kafka上执行的,还是在通过功能/转换处理流之前需要先使用它们?
smeeb

1
意思是,你有KafkaProducerKafkaKafkaConsumer。假设KafkaProducer生活在Java应用程序中,并且该KafkaConsumer应用程序在某些Ruby应用程序/后端上运行。KafkaProducer发送Message1到Kafka,需要通过进行转换Function1Function1代码在哪里?在Kafka上(正确)还是在KafkaConsumerRuby应用程序内部?
smeeb

2
您无法在Kafka本身中执行功能或进行任何处理。Apache Spark Streaming和Apache Storm是两个可从Kafka使用的分布式流处理框架。他们在Kafka之外运行,并像连接数据库一样连接到它。这些框架公开了有用的功能,例如拆分,聚合,开窗等。您可以在Ruby使用者中实现基本功能,但是我强烈建议您使用其中一种框架。spark.apache.org/streaming storm.apache.org/releases/2.0.0-SNAPSHOT/Trident-tutorial.html
塞缪尔

1
好的,谢谢,再加上+1- 如果Kafka可以对流本身进行处理,那真是太棒了!因此,扮演恶魔的拥护者,您能否不能仅让RabbitMQ使用者将消息从队列中拉出,基于时间戳(或实际上是任何其他条件/属性)对其进行汇总,并执行相同的窗口并将功能转换为Spark数据流或风暴提供?
smeeb

1
是的,我认为您可以使用RabbitMQ做到这一点,因为RabbitMQ可以保证消息顺序。您可能无法对每个消息队列执行此操作。而且构建起来很复杂。例如,如果您正在聚合的RabbitMQ使用者崩溃了怎么办?使用Kafka,您可以跟踪流中处理的位置,因此可以在您离开的那一刻开始使用您的消费者
Samuel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.