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