仅当流中有多个分片时分区键才重要(但始终需要它们)。 Kinesis 计算分区键的 MD5 哈希来决定在哪个分片上存储记录(如果您描述流,您将看到哈希范围作为分片描述的一部分)。
那么为什么这很重要呢?
每个分片每秒只能接受 1,000 条记录和/或 1 MB(请参阅放置记录 https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html文档)。如果您写入单个分片的速度快于此速率,您将得到ProvisionedThroughputExceededException
.
通过多个分片,您可以扩展此限制:4 个分片可为您提供 4,000 条记录和/或每秒 4 MB。当然,也有一些警告。
最大的问题是您必须使用不同的分区键。如果所有记录都使用相同的分区键,那么您仍然写入单个分片,因为它们都具有相同的哈希值。如何解决这个问题取决于您的应用程序:如果您从多个进程进行写入,那么使用进程 ID、服务器的 IP 地址或主机名可能就足够了。如果您从单个进程写入,则可以使用记录中的信息(例如,唯一的记录 ID)或生成随机字符串。
第二个需要注意的是,分区键会根据总写入大小进行计数,并存储在流中。因此,虽然您可以通过在记录中使用某些文本组件来获得良好的随机性,但您会浪费空间。另一方面,如果您有一些随机文本组件,您可以从中计算自己的哈希值,然后将其字符串化为分区键。
最后,如果您使用放置记录 https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html(如果您要写入大量数据,则应该这样做),请求中的个别记录可能会被拒绝,而其他记录可能会被接受。发生这种情况是因为这些记录发送到的分片已经达到其写入限制,并且您必须重新发送它们(在延迟后)。
另一个答案指出记录在分区内是排序的,并声称这是分区键的真正原因。但是,此顺序反映了 Kinesis 的顺序accepted记录,这不一定是客户想要的顺序。
- 如果客户端是单线程并使用放置记录 https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.htmlAPI,那么是的,客户端和分区之间的排序应该一致。
- 如果客户端是多线程的,那么所有标准分布式系统的无序原因(内部线程调度、网络路由、服务调度)都可能导致顺序不一致。
- 如果客户端使用放置记录 https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.htmlAPI,批次中的单个记录可能会被拒绝,并且必须重新发送。该文档非常清楚地表明此 API 调用不保留顺序。在大容量环境中,这就是您将使用的 API。
除了写入时顺序不一致之外,重新分片操作还可能导致读取时出现不一致。您必须遵循从父母到孩子的链条,认识到可能有更多或更少的孩子,并且分割可能不均匀。简单的“每个分片一个线程”方法(例如 Lambda 使用的)是行不通的。
所以,底线是:是的,分片提供排序。但是,依赖该顺序可能会给您的应用程序带来难以诊断的错误。
在大多数情况下,这并不重要。但如果您需要保证顺序(例如在处理事务日志时),那么您must在写入记录时将您自己的排序信息添加到记录中,并确保在读取记录时正确排序。