什么是 AWS Kinesis 中的分区键?

What is partition key in AWS Kinesis all about?

我在读 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 在这里的真正含义是什么?它在后台做什么?我读了它 documentation 但不明白它的意思。

分区键仅在流中有多个分片时才重要(但它们始终是必需的)。 Kinesis 计算分区键的 MD5 哈希值来决定将记录存储在哪个分片上(如果您描述流,您将看到哈希范围作为分片描述的一部分)。

为什么这很重要?

每个分片只能接受 1,000 条记录 and/or 每秒 1 MB(请参阅 PutRecord 文档)。如果您写入单个分片的速度快于此速率,您将获得 ProvisionedThroughputExceededException.

使用多个分片,您可以扩展此限制:4 个分片为您提供 4,000 条记录 and/or 每秒 4 MB。当然,也有注意事项。

最大的就是必须使用不同的分区键。如果您的所有记录都使用相同的分区键,那么您仍在写入单个分片,因为它们都将具有相同的哈希值。如何解决这个问题取决于您的应用程序:如果您从多个进程写入,那么使用进程 ID、服务器的 IP 地址或主机名可能就足够了。如果您从单个进程写入,那么您可以使用记录中的信息(例如,唯一记录 ID)或生成随机字符串。

第二个注意事项是分区键计入总写入大小,并存储在流中。因此,虽然您可以通过在记录中使用某些文本组件来获得良好的随机性,但您会浪费 space。另一方面,如果您有一些随机文本组件,您可以从中计算您自己的哈希值,然后将其字符串化为分区键。

最后,如果您正在使用 PutRecords(如果您正在写入大量数据,则应该这样做),请求中的个别记录可能会被拒绝,而其他记录会被接受。发生这种情况是因为这些记录进入了一个已经达到其写入限制的分片,并且您必须 re-send 它们(在延迟之后)。


另一个答案指出记录在分区内是有序的,并声称这是分区键的真正原因。但是,此顺序反映了 Kinesis 接受 记录的顺序,这不一定是客户端想要的顺序。

  • 如果客户端是 single-threaded 并使用 PutRecord API,那么是的,客户端和分区之间的顺序应该一致。
  • 如果客户端是multi-threaded,那么所有标准分布式系统的混乱原因(内部线程调度、网络路由、服务调度)都可能导致顺序不一致。
  • 如果客户端使用 PutRecords API,批次中的单个记录可能会被拒绝,并且必须重新发送。该文档非常清楚,此 API 调用不会保留顺序。在 high-volume 环境中,这是您将使用的 API。

除了写入时顺序不一致之外,重新分片操作还可能导致读取时出现不一致。您必须遵循从 parent 到 child(ren) 的链条,认识到可能有更多或更少的 children,并且分割可能不均匀。天真的“每个分片一个线程”的方法(例如 Lambda 使用的方法)是行不通的。

所以,底线是:是的,分片提供排序。但是,依赖该顺序可能会在您的应用程序中引入 hard-to-diagnose 错误。

在大多数情况下,这无关紧要。但是,如果您需要保证顺序(例如处理事务日志时),那么您 必须 在写入记录时将自己的顺序信息添加到记录中,并确保记录在读取时正确排序.

接受的答案解释了什么是分区键以及它们在 Kinesis 中的用途(决定将数据发送到哪个分片)。不幸的是,它并没有解释为什么首先需要分区键。

理论上 AWS 可以为每条记录创建一个随机分区键,这将导致近乎完美的传播。

使用分区的真正原因是 "ordering/streaming"。 Kinesis 维护每个分片的顺序(序列号)。

换句话说,通过将 X 和之后的 Y 流式传输到分片 Z,可以保证 X 将在 Y 之前从流中拉出(当从所有分片拉取记录时)。 另一方面,通过将 X 流式传输到分片 Z1,然后将 Y 流式传输到分片 Z2,无法保证顺序(从所有分片中提取记录时)。 Y肯定先于X拉。

分片 "streaming" 功能在很多情况下都很有用。

(例如,视频服务使用用户名和电影名称作为分区键将电影流式传输给用户)。

(例如处理常见事件流,并应用聚合)。

在不需要排序(流式传输)或分组(例如聚合)的情况下,生成随机分区键就足够了。