NodeJS AWS Kinesis中的分区密钥是什么?

siv3szwd  于 2023-01-08  发布在  Node.js
关注(0)|答案(3)|浏览(150)

我阅读了关于AWS Kinesis的文章,在下面的程序中,我将数据写入名为TestStream的流中,我将这段代码运行了10次,向流中插入了10条记录。

var params = {
    Data: 'More Sample data into the test stream ...',
    PartitionKey: 'TestKey_1',
    StreamName: 'TestStream'
};

kinesis.putRecord(params, function(err, data) {
   if (err) console.log(err, err.stack); // an error occurred
   else     console.log(data);           // successful response
});

所有记录都成功插入。partition key在这里到底是什么意思?它在后台做什么?我读了它的文档,但不明白它的意思。

euoag5mw

euoag5mw1#

只有当流中有多个分片时,分区键才起作用(但它们始终是必需的)。Kinesis计算分区键的MD5散列,以决定在哪个分片上存储记录(如果描述流,您将看到散列范围作为分片描述的一部分)。
这有什么关系呢?
每个shard只能接受1,000条记录和/或每秒1 MB(请参阅PutRecord文档)。如果您写入单个shard的速度超过此速度,您将获得ProvisionedThroughputExceededException
对于多个碎片,可以扩展此限制:4个碎片给你4,000条记录和/或每秒4 MB,当然也有一些注意事项。
最大的问题是你必须使用不同的分区键。如果你所有的记录都使用相同的分区键,那么你仍然是在写一个分片,因为它们都有相同的哈希值。如何解决这个问题取决于你的应用程序:如果您从多个进程写入,则使用进程ID、服务器的IP地址或主机名可能就足够了。如果您从单个进程写入,则可以使用记录中的信息(例如,唯一的记录ID)或生成随机字符串。
第二个注意事项是分区键是根据总写入大小计算的,并且存储在流中。因此,虽然您可以通过在记录中使用一些文本组件来获得良好的随机性,但您将浪费空间。另一方面,如果您有一些随机文本组件,您可以从中计算自己的哈希,然后将其字符串化为分区键。
最后,如果使用PutRecords(如果要写入大量数据,应该使用PutRecords),请求中的个别记录可能会被拒绝,而其他记录则会被接受,这是因为这些记录进入了一个已经达到写入限制的shard,您必须重新发送它们(在延迟之后)。
另一种回答指出记录在分区中是有序的,并声称这是分区键的真正原因,但是,这种排序反映了Kinesis * 接受 * 记录的顺序,而这不一定是客户机想要的顺序。

  • 如果客户机是单线程的并且使用PutRecord API,那么是的,客户机和分区之间的顺序应该一致。
  • 如果客户端是多线程的,那么所有的标准分布式系统的无序原因(内部线程调度、网络路由、服务调度)都可能导致排序不一致。
  • 如果客户端使用PutRecords API,则批处理中的单个记录可能会被拒绝,并且必须重新发送。文档非常清楚地表明,此API调用不会保留顺序。在高容量环境中,您将使用此API。

除了写入时的顺序不一致外,rehard操作还可能在读取时引入不一致。您必须遵循从父到子(ren)的链,认识到可能有更多或更少的子,并且拆分可能不均匀。天真的"每个碎片一个线程"方法(如Lambda所使用的)不会起作用。
所以,底线是:是的,分片提供了排序。2然而,依赖于这种排序可能会在应用程序中引入难以诊断的bug。
在大多数情况下,这并不重要,但是如果您需要保证顺序(比如在处理事务日志时),那么您 * 必须 * 在写入记录时将自己的排序信息添加到记录中,并确保记录在读取时正确排序。

50pmv0ei

50pmv0ei2#

公认的答案解释了什么是分区密钥以及它们在Kinesis中的用途(决定将数据发送到哪个shard),但不幸的是,它没有解释为什么首先需要分区密钥。
从理论上讲,AWS可以为每个记录创建一个随机分区密钥,这将导致近乎完美的传播。
使用分区的真实的原因是为了“排序/流”。Kinesis维护每个碎片的排序(序列号)。
换句话说,通过将X流传输到碎片Z,然后将Y流传输到碎片Z,可以保证X在Y之前从流中被拉取(当从所有碎片拉取记录时)。另一方面,通过将X流传输到碎片Z1,然后将Y流传输到碎片Z2,则无法保证排序(当从所有碎片拉取记录时)。Y肯定会在X之前被拉取。
碎片的“流”功能在很多情况下都很有用。
(E.g.使用用户名和电影名称作为分区密钥向用户流式传输电影的视频服务)。
(E.g.处理公共事件流并应用聚集)。
在不需要排序(流)或分组(例如聚合)的情况下,生成随机分区密钥就足够了。

fykwrbwg

fykwrbwg3#

如果你难以理解碎片,那么可以把它们看作是由你创建的一个单独的kinesis资源处理的不同队列。你可以使用多个队列,因为一个队列只能处理1 MB/秒的数据。2所以使用多个队列来处理更多的吞吐量。3大多数情况下你将使用AWS lambda来处理队列。拥有多个队列也可以得到多个lambda,这意味着现在你可以处理更多的数据,但这与你的问题分区键是什么意思无关。
如果你不定义你自己的分区键,那么你的数据将随机进入任何队列/碎片,你的lambda总是只处理相同类型的数据,这样你的数据的顺序将不会得到维护,因为如果lambda拒绝了一批记录,kinesis将在推送下一批之前再次释放同一批数据。
但是如果你使用了适当的分区键,比方说customerID或movieID,你显然希望购买事件或电影内容以相同的顺序出现。并且如果你使用了使用唯一customerID/movieID的相同队列/碎片,你将最终使所有数据顺序地进入最终由lambda检索的相同队列/碎片,并且如果lambda拒绝了一批,kinesis将确保除非成功处理该批数据,否则不会获得下一批数据。
这,我的朋友就是你问题的答案。希望能有所帮助。

相关问题