为什么我应该使用Amazon Kinesis而不是SNS-SQS?

228

我有一个使用情况,其中会有一系列的数据流进来,而我无法以相同的速度消耗它们,因此需要一个缓冲区。这可以使用SNS-SQS队列来解决。我了解到Kinesis也可以解决同样的问题,那么它们之间有什么区别?为什么应该选择(或不选择)Kinesis?

13个回答

97

请记住,此答案适用于2015年6月之前的情况

经过一段时间的研究后,我发现在大多数情况下,SQS(配合SNS)是首选,除非您对消息的顺序很重要(SQS无法保证消息的FIFO)。

Kinesis有两个主要优点:

  1. 你可以从几个应用程序中读取相同的消息
  2. 在需要时可以重新读取消息。

通过将SNS作为扇出到SQS来实现这两个优点。这意味着消息的生产者只向SNS发送一条消息,然后SNS将消息扇出到多个SQS,每个消费者应用程序一个SQS。这样,您可以拥有任意数量的消费者,而不必考虑分片容量。

此外,我们还添加了另一个SQS,它订阅了可保存14天的SNS消息。在正常情况下,没有人从此SQS中读取,但是如果存在使我们想要倒带数据的bug,则可以轻松地从此SQS中读取所有消息并将其重新发送到SNS。而Kinesis仅提供7天的保留期。

总之,SNS+SQS更容易且提供了大多数功能。在我看来,除非有非常强的理由选择Kinesis,否则应该选择SNS+SQS。


3
注意:您可以让Kinesis保留数据长达7天。 - Didier A.
38
最近,AWS宣布推出SQS FIFO([http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html]),可以确保消息按时间顺序提供服务。 - VijeshJain
10
非常微小的评论-在“SNS将消息拆分到多个SQS中”中,可能不会使用“split”这个词,因为它并不是将消息拆成几部分,而是将其复制到多个目的地。 - Mobigital
5
由于每个分片/秒钟的读者数量限制,Kinesis不适用于扇出(发布-订阅)用例。虽然这与原始查询无关,但任何依赖于Kinesis扩展到n个读者的人都应考虑到这一事实。https://forums.aws.amazon.com/message.jspa?messageID=760351 - codeasone
5
Kinesis的订单保证是按照每个分片而不是每个流来计算的。一旦您拥有超过一个分片,整个流的顺序就无法得到保证。对于SQS队列,在吞吐量相对较低的情况下,它几乎是先进先出的。只有在吞吐量增加时,顺序才会被较少遵循。这是关于经典SQS队列,而不是FIFO队列。 - yoroto
显示剩余3条评论

68

这些技术的语义不同,因为它们被设计用于支持不同的场景:

  • SNS/SQS: 流中的项目没有相互关联
  • Kinesis: 流中的项目相互关联

让我们通过例子来了解它们的区别。

  1. 假设我们有一个订单流,对于每个订单,我们需要预留一些库存并安排送货。完成此操作后,我们可以安全地从流中删除该项,并开始处理下一个订单。在开始下一个订单之前,我们完全完成了先前的订单。
  2. 再次,我们有相同的订单流,但现在我们的目标是按目的地对订单进行分组。一旦我们有了,比如说,10个到同一地方的订单,我们就想要一起交付(交付优化)。现在情况不同了:当我们从流中获取新项目时,我们无法完成处理;相反,我们“等待”更多项目以满足我们的目标。此外,如果处理器崩溃,我们必须“恢复”状态(这样就不会丢失任何订单)。

一旦一个项目的处理无法与处理另一个项目分离,我们就必须具备Kinesis语义以安全地处理所有情况。


使用 SQS FIFO 队列,我们可以按照发送顺序对消息进行排序。这一点是否使得 SQS 与 Kinesis 在该方面类似呢? - Andy Dufresne
2
@AndyDufresne:这很好地涵盖了顺序重要的情况。在上述情况(1)中,您可能希望按顺序处理订单。因此,如果库存不足,则会拒绝或延迟后续订单。FIFO语义不能解决核心相关性(分组)问题。 - Konstantin Triger
非常好的答案,谢谢。我有一个关于“如果处理器进程崩溃,我们必须‘恢复’状态(以确保没有订单丢失)”的问题 - 难道这不也是通过SQS消息自动重新出现(如果它们没有被明确删除)来实现的吗? - undefined
@JurajMartinka:是的,这两种技术都支持其主要用例(单个或相关消息处理)的崩溃恢复。 - undefined

62

表面上它们有些相似,但你的使用情况将决定哪个工具更适合。依我看,如果你能够使用 SQS 完成想要的功能,那么就应该使用它,因为它更简单、更便宜。但是在 AWS 的常见问题解答中提供了更好的解释,其中给出了两种工具的适用场景示例,以帮助你做出决策:

常见问题解答


9
FYI http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-subscribe-queue-sns-topic.html。SQS FIFO 与 SNS 不兼容。 - Brent
3
@Brent 为了保持最新状态 - AWS已经在SNS中添加了对FIFO SQS的支持。 - Julian Camilleri

57

Kinesis支持多个消费者的功能,这意味着相同的数据记录可以在24小时内同时或不同时处理在不同的消费者中,类似的行为在SQS中可以通过写入多个队列并且消费者可以从多个队列读取来实现。但是,再次写入多个队列会在系统中添加子秒{几毫秒}延迟。

其次,Kinesis提供路由功能,使用分区键将数据记录有选择地路由到不同的分片中,可以由特定的EC2实例处理并启用微批量计算{计数和聚合}。

在任何AWS软件上工作都很容易,但是在SQS上最容易。对于Kinesis,需要提前分配足够数量的分片,动态增加分片数量以管理峰值负载并减少成本也是必需的。这在Kinesis中很痛苦,在SQS中不需要这样的东西。SQS是无限可扩展的。


13
关于你对 SQS 的解释。如果在它们之前添加 SNS,你可以通过一种简单的方式将相同的消息发送到多个 SQS。 - Roee Gavirel
8
应用程序(App)--> 社交网络主题(SNS Topic)--> SQS1、SQS2、SQS3等消息队列。 - kartik
4
是的,我指的就是这种方法。 - Roee Gavirel
@BarbarosAlp - 我只知道短信(移动文本消息)的限制,这不是本主题的讨论范围。这是官方文档:http://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_sns - Roee Gavirel
我发现在使用SNS和SQS时的问题是无法保证顺序。你只能使用标准SQS而不是FIFO。 - m0g
显示剩余3条评论

46

以下内容摘自AWS文档:

我们建议使用Amazon Kinesis Streams来处理以下具有类似要求的用例:

  • 将相关记录路由到同一记录处理器(例如流MapReduce)。例如,当所有给定键的记录都被路由到同一记录处理器时,计数和聚合更简单。

  • 记录排序。例如,您想要将日志数据从应用程序主机传输到处理/存档主机,同时保持日志语句的顺序。

  • 多个应用程序可以同时使用相同的流来消费数据。例如,您有一个更新实时仪表板的应用程序和一个将数据归档到Amazon Redshift的应用程序。您希望两个应用程序都可以同时且独立地从同一流中消费数据。

  • 数小时后按相同的顺序消费记录的能力。例如,您有一个计费应用程序和一个运行落后于计费应用程序几个小时的审计应用程序。因为Amazon Kinesis Streams可以存储数据长达7天,所以您可以将审核应用程序追赶计费应用程序最多7天。

我们建议使用Amazon SQS来处理以下具有类似要求的用例:

  • 消息语义(例如消息级确认/失败)和可见性超时。例如,您有一个工作项队列,并希望单独跟踪每个项目的成功完成。Amazon SQS会跟踪确认/失败,因此应用程序无需维护持久化检查点/光标。Amazon SQS将删除已确认的消息,并在配置的可见性超时后重新传递失败的消息。

  • 单个消息延迟。例如,您有一个作业队列,并需要对单个作业进行延迟计划。使用Amazon SQS,您可以为单个消息配置最长15分钟的延迟。

  • 动态增加读取时的并发/吞吐量。例如,您有一个工作队列,并希望添加更多的读取器,直到积压的工作被清除。使用Amazon Kinesis Streams,您可以扩展到足够数量的分片(但请注意,您需要提前分配足够的分片)。

  • 利用Amazon SQS透明扩展的能力。例如,您可以缓冲请求,而负载因偶尔的负载高峰或业务的自然增长而发生变化。由于每个缓冲请求可以独立处理,因此Amazon SQS可以透明地扩展以处理负载,而无需您提供任何预配指令。


  • 这个回答简洁地回答了问题。 - Govind Rai

    41

    对我来说,最大的优势是 Kinesis 是可重放队列而 SQS 不是。因此,您可以在 Kinesis 上拥有相同消息的多个消费者(或不同时段的同一消费者),而对于 SQS,则一旦确认了消息,它就会从队列中消失。因此,SQS 对于工作队列来说更好。


    你是如何确认消息的?你是否指的是删除? - NeverEndingQueue
    是的,基本上就是这样。您可以说您已经完成了此消息。 - Matthew Curry
    1
    您设置了SQS监听器的删除策略,这并不正确,因此当读取消息时无法删除该消息。 - farhad
    3
    也许这是新的事情,@farhad,我回答了这个问题已经7年了。如果有这样的删除策略,听者会再次收到相同的信息吗?还是允许你跳过信息?不管怎样,尽管可以滥用SQS进行其他事情,但通常实践中它仍然更像作业队列。 - Matthew Curry

    19

    另外,Kinesis可以触发Lambda,而SQS则不行。因此,使用SQS时,你要么必须提供一个EC2实例来处理SQS消息(并处理它失败的情况),要么必须有一个定时Lambda(无法扩展或缩小 - 每分钟只有一个)。

    编辑:这个答案已经不正确了。自2018年6月起,SQS可以直接触发Lambda。

    https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html


    1
    -1 不同意。虽然Kinesis可以触发Lambda,但与定时的SQS Lambda相比并没有任何优势。后者将无缝扩展(即如果需要的时间超过一分钟,则会启动第二个Lambda)。计算时间的价格也没有明显的差异。如果需要超过5个并发Lambda,只需添加多个触发器,每个触发器相隔几秒钟(使用cron)。这不是使用Kinesis而不是SNS / SQS的理由。 - Steven de Salas
    5
    我不确定我是否同意这种不同意的态度;] - 您可以安排每分钟一个lambda,这将限制您批处理到达该间隔的消息。 Kinesis允许您立即读取消息。或者是我误解了什么? - Moszi
    当需要调用拉取Lambda针对SQS时,几个CloudWatch触发器和数百个之间存在巨大差异。 - Coding Pig
    14
    Lambda现在支持将SQS作为触发器! - sixty4bit

    19

    计费模型不同,因此根据您的使用情况,其中一个可能更加便宜。 在最简单的情况下(不包括 SNS):

    • SQS 按每条消息收费(每 64 KB 计为一个请求)。
    • Kinesis 每小时按每个 shard 收费(每个 shard 可处理最多 1000 条消息或 1 MB/秒数据),并且还要按您放入的数据量收费(每 25 KB)。

    根据当前价格,不考虑免费套餐,如果您以最大消息大小每天发送 1 GB 的消息,则 Kinesis 的成本将比 SQS 高得多(Kinesis 为 $10.82/月,而 SQS 为 $0.20/月)。 但是,如果您每天发送 1 TB,则 Kinesis 稍微便宜一些($158/月 vs. $201/月 的 SQS)。

    详情:SQS 每百万次请求收取 $0.40(每个 64 KB),因此每 GB 为 $0.00655。每天 1 GB,这仅需不到 $0.20/月;每天 1 TB,总共需花费略高于 $201/月。

    Kinesis 每百万次请求收取 $0.014(每个 25 KB),因此每 GB 为 $0.00059。每天 1 GB,这少于 $0.02/月;每天 1 TB,则大约为 $18/月。但是,Kinesis 还会按 $0.015/shard-hour 收费。您每秒至少需要 1 个 shard 来处理 1 MB 的数据。每天 1 GB,1 个 shard 完全足够,因此这将增加每天 $0.36 的费用,总成本为 $10.82/月。每天 1 TB,您至少需要 13 个 shards,这又增加了每天 $4.68 的费用,总共需花费 $158/月。


    我不完全明白指数级增长的大小在这里为什么很重要。你能深入挖掘一下吗?听起来你有一些见解,我也想了解一下。编辑实际上,看着Euguene Feingold的答案,似乎有一个相当坚实的争论(?)。 - Thomas
    抱歉,我的计算有些错误(现在已经修正了,希望没问题了)。 - John Velonis
    没错,但如果您的平均SQS消息大小很小,比如1kb或更小呢? - mcmillab
    1
    @mcmillab SQS无论您的消息是1 KB还是64 KB,都会收取相同的费用--请参阅Amazon的SQS定价页面。因此,如果您的消息只有1 KB,则如果您发送相同总数据量,SQS将比我上面给出的数字多花费64倍的费用。但是,单个请求最多可以包含10条消息,因此,如果您能够将消息批处理在一起,它可能只会增加6倍的费用(取决于批次有多满)。 - John Velonis
    1
    @JohnVelonis 上述有关SQS定价的计算缺少一个关键要素。需要特别注意如何收费SQS请求。1个请求=1个API操作。为了处理单个“消息”,至少需要执行3个API操作:1个发送+1个读取+1个删除。其他SQS功能,如更改可见性,将产生更多的API操作。这种意外的乘数非常恶劣,通常导致SQS在大数据集(例如每月处理1亿条消息)方面比Kinesis Streams贵2-10倍。 - Vlad Poskatcheev

    12

    Kinesis解决了流式数据的typical map-reduce情景中地图部分问题。而SQS并没有保证这一点。如果您有需要根据键聚合的流式数据,Kinesis会确保该键的所有数据都进入特定的shard,并且可以在单个主机上消耗该shard,相比之下使用SQS更容易进行键聚合。


    10

    Kinesis使用案例

    • 日志和事件数据收集
    • 实时分析
    • 移动数据捕获
    • “物联网”数据供应

    SQS使用案例

    • 应用程序集成
    • 解耦微服务
    • 将任务分配给多个工作节点
    • 将用户请求与后台密集工作解耦
    • 批处理消息以供未来处理

    4
    Kinesis可以做你提到的SQS所有的事情吗? - CodesInTheDark
    说到这个,SNS不能做Kinesis建议的所有事情吗?我感觉这并没有回答“为什么”的问题。 - Casey
    1
    SQS(可选与SNS结合,用于扇出)用于松耦合的微服务;而Kinesis数据流用于高吞吐量的流摄取,并将流以低延迟高吞吐量交付给消费者: -SQS FIFO每秒只能摄取“仅”300个事务(SQS FIFO高吞吐量为3000 TX/s);而Kinesis(也是FIFO)每个分片可以吸收1000个TX/s,您可以创建多个分片! -SQS不提供有关其传递延迟(记录摄取和可读时间之间的时间)的指标,而对于Kinesis平均值为200毫秒。 - galeop

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接