为啥我应该使用 Amazon Kinesis 而不是 SNS-SQS?
Posted
技术标签:
【中文标题】为啥我应该使用 Amazon Kinesis 而不是 SNS-SQS?【英文标题】:Why should I use Amazon Kinesis and not SNS-SQS?为什么我应该使用 Amazon Kinesis 而不是 SNS-SQS? 【发布时间】:2014-12-24 18:19:00 【问题描述】:我有一个用例,其中会有数据流进来,我不能以相同的速度使用它并且需要一个缓冲区。这可以使用 SNS-SQS 队列来解决。我知道 Kinesis 解决了相同的目的,那么有什么区别?为什么我应该更喜欢(或不应该更喜欢)Kinesis?
【问题讨论】:
【参考方案1】:请记住,这个答案在 2015 年 6 月是正确的
在研究了这个问题一段时间后,心里有同样的问题,我发现大多数用例都首选 SQS(带 SNS),除非消息的顺序对您很重要(SQS 不保证 FIFO消息)。
Kinesis 有 2 个主要优势:
-
您可以从多个应用程序中读取相同的消息
您可以在需要时重新阅读邮件。
使用 SNS 作为 SQS 的扇出可以实现这两个优势。这意味着消息的生产者只向 SNS 发送一条消息,然后 SNS 将消息扇出到多个 SQS,每个消费者应用程序一个。通过这种方式,您可以拥有任意数量的消费者,而无需考虑分片容量。
此外,我们还添加了一个订阅 SNS 的 SQS,该 SNS 将保存消息 14 天。在正常情况下,没有人从这个 SQS 中读取,但如果出现让我们想要回退数据的错误,我们可以轻松地从这个 SQS 读取所有消息并将它们重新发送到 SNS。而 Kinesis 仅提供 7 天的保留期。
总之,SNS+SQSs 更容易并且提供了大多数功能。 IMO,您需要一个非常强大的案例来选择 Kinesis。
【讨论】:
仅供参考:您可以让 Kinesis 保留长达 7 天。 最近,AWS 发布了 SQS FIFO [docs.aws.amazon.com/AWSSimpleQueueService/latest/…,可以服务于消息的时间排序。 超级次要评论 - 可能不会在SNS split the message to multiple SQSs
中使用 split
这个词,因为它不会将消息分解成碎片,而是将其复制到多个目的地。
Kinesis 不适合扇出 (pub-sub) 用例,因为每分片/秒的读者数量受到限制。虽然与原始查询无关,但任何依赖 Kinesis 扩展到 n 阅读器的人都应该考虑到这一事实。 forums.aws.amazon.com/message.jspa?messageID=760351
Kinesis 的订单保证是每个分片,而不是每个流。一旦你有多个分片,整个流将无法保证顺序。对于一个 SQS 队列,当吞吐量比较低时,几乎是 FIFO。只有当您的吞吐量更高时,订单才会更少遵循。这是关于经典的 SQS 队列,而不是 FIFO 队列。【参考方案2】:
从表面上看,它们有点相似,但您的用例将决定哪种工具是合适的。 IMO,如果您可以使用 SQS,那么您应该 - 如果它可以满足您的需求,它将更简单、更便宜,但这里有一个来自 AWS 常见问题的更好解释,它提供了两种工具的适当用例示例帮助您做出决定:
FAQ's
【讨论】:
仅供参考 docs.aws.amazon.com/AWSSimpleQueueService/latest/… SQS FIFO 不适用于 SNS @Brent 只是为了保持最新 - AWS 在 SNS 中增加了对 FIFO SQS 的支持【参考方案3】:Kinesis 支持多个消费者功能,这意味着相同的数据记录可以在同一时间或 24 小时内的不同时间在不同的消费者处处理,SQS 中的类似行为可以通过写入多个队列来实现,消费者可以从多个队列中读取。然而,再次写入多个队列会在系统中增加亚秒 几毫秒 的延迟。
其次,Kinesis 提供路由功能,可以使用分区键选择性地将数据记录路由到不同的分片,该分区键可以由特定的 EC2 实例处理,并且可以启用微批量计算计数和聚合。
使用任何 AWS 软件都很容易,但使用 SQS 是最简单的。使用 Kinesis,需要提前配置足够的分片,动态增加分片数量以管理峰值负载并减少分片以节省管理成本。 Kinesis 很痛苦,SQS 不需要这样的事情。 SQS 可无限扩展。
【讨论】:
关于您对 SQS 的解释。您可以通过在多个 SQS 之前添加一个 SNS 来实现将相同消息发送到多个 SQS 的简单方法。 app --> sns 主题 ---> sqs1, sqs2, sqs3... ? 是的,我指的正是这种方法。 @RoeeGavirel sns api 的请求/秒限制怎么样? @BarbarosAlp - 我只知道 SMS(移动短信)的限制,这不是这里的主题。这是官方文档:docs.aws.amazon.com/general/latest/gr/…【参考方案4】:这些技术的语义不同,因为它们旨在支持不同的场景:
SNS/SQS:流中的项目不相互关联 Kinesis:流中的项目彼此相关让我们通过示例来了解差异。
-
假设我们有一个订单流,我们需要为每个订单预留一些库存并安排交货时间。完成后,我们可以安全地从流中删除该项目并开始处理下一个订单。在开始下一个订单之前,我们已完全完成上一个订单。
同样,我们有相同的订单流,但现在我们的目标是按目的地对订单进行分组。一旦我们有 10 个订单到同一个地方,我们希望将它们一起交付(交付优化)。现在情况不同了:当我们从流中获得一个新项目时,我们无法完成对它的处理;相反,我们“等待”更多的项目来实现我们的目标。此外,如果处理器进程崩溃,我们必须“恢复”状态(因此不会丢失任何顺序)。
一旦一个项目的处理不能与另一个项目的处理分开,我们必须有 Kinesis 语义才能安全地处理所有情况。
【讨论】:
使用 SQS FIFO 队列,我们将在发送消息时对其进行排序。这是否使 SQS 在这方面类似于 Kinesis? @AndyDufresne:这很好地涵盖了顺序很重要的场景。在上述情况 (1) 中,您可能希望“按顺序”处理订单。因此,如果您缺货,以后的订单将被拒绝或延迟。 FIFO 语义并不能解决核心相对性(分组)问题。【参考方案5】:对我来说最大的优势是 Kinesis 是一个可重放队列,而 SQS 不是。因此,您可以拥有 Kinesis 的相同消息的多个消费者(或不同时间的同一消费者),其中使用 SQS,一旦消息被确认,它就会从该队列中消失。 因此,SQS 更适合工作队列。
【讨论】:
你如何确认消息?你的意思是删除吗? 是的,基本上。表示您已完成此消息 不正确,你在你的sqsListener上设置了删除策略,所以你可以说阅读时永远不要删除它 也许这是一个新事物@farhad,我在 7 年前回答了这个问题。有了这样的删除策略的监听器会再次抓取相同的消息,还是允许您跳过消息?无论如何,SQS 的通常做法仍然更多是工作队列,尽管可以将其滥用于其他事情【参考方案6】:摘自AWS Documentation:
我们建议将 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 可以透明地扩展以处理负载,而无需您提供任何预置指令。
【讨论】:
这简洁地回答了这个问题【参考方案7】:另一件事:Kinesis 可以触发 Lambda,而 SQS 不能。因此,对于 SQS,您要么必须提供一个 EC2 实例来处理 SQS 消息(并在它失败时处理它),要么您必须有一个计划的 Lambda(它不会扩大或缩小 - 每分钟只有一个) .
编辑:这个答案不再正确。自 2018 年 6 月起,SQS 可以直接触发 Lambda
https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html
【讨论】:
-1 不同意。虽然 Kinesis 可以触发 lambda,但与已调度的 SQS lambda 相比,这并没有优势。后者将无缝扩展(即,如果花费超过一分钟,第二个 lambda 将启动)。价格是按计算时间计算的,因此也没有明显的差异。如果您需要超过 5 个并发 lambda,那么只需添加多个间隔几秒钟安排的触发器(使用 cron)。这不是在 SNS/SQS 上使用 Kinesis 的理由。 我不确定我是否同意这种分歧;] - 您可以安排一个 lambda / 分钟,这将限制您批量处理到达该时间间隔的消息。 Kinesis 将允许您立即阅读消息。还是我误解了什么? 当需要针对 SQS 调用 pull lambda 时,几个 cloudwatch 触发器和数百个触发器之间存在巨大差异。 Lambda 现在支持 SQS 作为触发器!【参考方案8】:定价模型不同,因此根据您的用例,其中一种可能更便宜。使用最简单的情况(不包括 SNS):
SQS 对每条消息收费(每 64 KB 计为一个请求)。 Kinesis 每小时按分片收费(1 个分片最多可处理 1000 条消息或 1 MB/秒)以及您输入的数据量(每 25 KB)。插入当前价格且不考虑免费层级,如果您以最大消息大小每天发送 1 GB 消息,Kinesis 的成本将远高于 SQS(Kinesis 每月 10.82 美元,而每月 0.20 美元对于 SQS)。但是,如果您每天发送 1 TB,Kinesis 会便宜一些(每月 158 美元,而 SQS 每月 201 美元)。
详细信息:SQS 每百万个请求(每个 64 KB)收费 0.40 美元,因此每 GB 0.00655 美元。按每天 1 GB 计算,每月只需不到 0.20 美元;按每天 1 TB 计算,每月只需 201 美元多一点。
Kinesis 每百万个请求(每个 25 KB)收费 0.014 美元,因此每 GB 0.00059 美元。每天 1 GB,每月不到 0.02 美元;每天 1 TB,每月大约 18 美元。然而,Kinesis 也收取每分片小时 0.015 美元的费用。每秒每 1 MB 至少需要 1 个分片。在每天 1 GB 的情况下,1 个分片就足够了,因此每天将再增加 0.36 美元,每月的总成本为 10.82 美元。如果每天 1 TB,您将需要至少 13 个分片,这样每天又增加了 4.68 美元,总成本为每月 158 美元。
【讨论】:
我不完全理解为什么这里的大小呈指数增长很重要。你能再挖一点吗?听起来你有一些我想要的洞察力。 编辑实际上,看看 Euguene Feingold 的回答,似乎对此(?)进行了相当扎实的辩论。 抱歉,我的计算出了一些错误(希望现在已修复)。 对,但是如果您的平均 SQS 消息大小很小,比如 1kb 或更小,该怎么办? @mcmillab SQS 将收取相同的费用,无论您的消息是 1 KB 还是 64 KB - 请参阅 Amazon's SQS pricing page。因此,如果您的消息只有 1 KB,如果您发送相同的总数据量,SQS 的成本将是我上面给出的数字的 64 倍。但是,一个请求最多可以包含 10 条消息,因此如果您能够将消息批处理在一起,它可能只有 6 倍(取决于您的批处理的完整程度)。 @JohnVelonis 以上 SQS 定价计算缺少关键部分。需要特别注意了解 SQS 请求的收费方式。 1 个请求 = 1 个 API 操作。为了处理单个“消息”,至少需要执行 3 个 API 操作:1 个发送 + 1 个读取 + 1 个删除。其他 SQS 功能(例如更改可见性)将引发更多 API 操作。这种意想不到的乘数非常糟糕,通常会导致 SQS 对于大型数据集(例如每月处理 1 亿条消息)的成本比 Kinesis Streams 高 2-10 倍。【参考方案9】:Kinesis 解决了流数据的典型 map-reduce 场景中的 map 部分问题。虽然 SQS 不能确定这一点。如果您有需要在密钥上聚合的流数据,kinesis 会确保该密钥的所有数据都进入特定的分片,并且该分片可以在单个主机上使用,与 SQS 相比,密钥上的聚合更容易
【讨论】:
【参考方案10】:我还要补充一件其他人没有提到的东西——SQS 的成本要高几个数量级。
【讨论】:
你确定吗?根据我的计算,Kinesis 要贵得多,但我从来没有使用过亚马逊简单价格计算器。 查看当前在 aws 上的定价示例:具有 2.67 亿条消息的 Kinesis 大约为 60 美元,而通过 SQS 发送该数量的消息将导致 107 美元。显然,我只是做了一个非常快速的比较,这与不同的用例有很大的不同,但这个答案绝对值得称赞。 假设你正在做一个扇出,说每天有 2 个消费者和 1 亿条消息。 SNS 费用为 50 美元/天。 SQS 成本为 40 美元/天/消费者或总计 80 美元/天。 Kinesis PUT 每天 1.4 美元,分片 0.36 美元。即使有 100 个分片(100 MB/s 输入,200 MB/s 输出),也只需 3.60 美元/天 + 1.40 美元/天。所以 Kinesis 每天 4 美元,而 SNS/SQS 每天 130 美元。 我很想知道为什么这个线程中的成本差异如此之大。 SQS 定价的一个问题是,每 100 万个请求的规定成本率并不是实际消息。它是 API 操作,其中 1 个请求 = 1 个 API 操作。为了处理单个“消息”,至少需要执行 3 个 API 操作:1 个发送 + 1 个接收 + 1 个删除。其他 SQS 功能(例如更改可见性)将引发更多 API 操作。这种意想不到的乘数非常糟糕,通常会导致 SQS 对于大型数据集(例如每月处理 1 亿条消息)的成本比 Kinesis Streams 高 2-10 倍。【参考方案11】:Kinesis 用例
日志和事件数据收集 实时分析 移动数据采集 “物联网”数据馈送SQS 用例
应用集成 解耦微服务 将任务分配给多个工作节点 将实时用户请求与密集的后台工作分离 批处理消息以供将来处理【讨论】:
Kinesis 不能做您提到的 SQS 可以做的所有事情吗?以上是关于为啥我应该使用 Amazon Kinesis 而不是 SNS-SQS?的主要内容,如果未能解决你的问题,请参考以下文章
Amazon Kinesis:在同步 Kinesis 分片和租约时捕获异常
使用 Amazon Kinesis Data Firehose ElasticSearch Selivery 时是不是可以设置文档 ID