如何在AWS Kinesis中使用ExplicitHashKey进行轮询流分配

7

我正在尝试通过Amazon Kinesis传输大量数据(每秒约10,000个点)。

为了最大化每秒钟通过我的分片的记录数,我想要在分片上轮询我的请求(我的应用程序逻辑不关心单个消息进入哪个分片)。

看起来我可以在发送到PutRecords端点的列表中的消息的ExplicitHashKey参数中完成此操作 - 但是Amazon文档实际上没有描述如何使用ExplicitHashKey,除了先知般的声明:

http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html

Records数组中的每个记录都可以包括一个可选参数ExplicitHashKey,该参数覆盖分区键到分片映射。此参数允许数据生产者明确确定记录存储的分片。有关详细信息,请参见Amazon Kinesis Streams开发人员指南中的使用PutRecords添加多个记录。

(上述文档中的语句链接到另一节文档,该文档根本不讨论ExplicitHashKeys)。

是否有一种方法可以使用ExplicitHashKey在分片之间轮询数据?

参数的有效值是什么?


“ExplicitHashKey”如何减少分区数量?您不想为Kinesis生成MD5并决定其所属分区的好“partitionKey”吗?假设您有2个分区,并选择了一个好的“partitionKey”,那么Kinesis分区器将根据128位值将该记录发送到其中一个分区。 - prayagupa
1
@prayagupd - 假设您想每秒驱动9,900个数据点。由于Kinesis支持每个分片每秒1,000个点,因此您应该能够使用10个分片完成。但是,如果您的数据分布在分片之间不够均匀,迟早会有一个分片每秒获得超过1,000个点。作为一个实际的例子,我有一个系统,我通过它每秒传输13,000个点,并使用随机数作为我的分区键,即使使用23个分片,我仍然偶尔会看到速率限制异常。如果我有完美的轮询分配,我可以使用13个分片完成。 - deadcode
明白了。但你是怎么考虑轮询的呢?我想到可以使用一些顺序数字作为“partitionKey”,以便它均匀地进入“sequentialPartitionKey / np”。为简单起见,假设一个分区最多可以写入10个事件/1000ms。对于130个事件/1000ms的速率,假设序列号从1到130,那么恰好有10个事件1、14、27、40、53、66、79、92、105、118进入分区1,无论以何种顺序处理,其他分区也是如此。你似乎在正确的轨道上,设置自己的分区键而不是MD5哈希。 - prayagupa
2
现在我更好地理解了事情,对于我的特定情况,我可以通过将每个第N条记录发送到str(int(((N%NUM_SHARDS)+0.5)*(2 ** 128 / NUM_SHARDS))))来轮询。这是因为我的碎片都恰好具有相同大小的哈希键范围。您也可以描述流,动态计算哈希键范围,并选择每个范围内的数字,然后在这些数字上进行轮询。 - deadcode
虽然我不理解 str( int( (( N%NUM_SHARDS )+0.5) * ( 2**128 / NUM_SHARDS ) ) ),但它看起来很有趣。 - prayagupa
1个回答

12

每个分片从 0 到 2^128 - 1 分配了一系列连续的 128 位整数。

您可以通过 AWS CLI 在流中找到分配给给定分片的整数范围:

aws kinesis describe-stream --stream-name 您的流名称

输出将如下所示:

{
    "StreamDescription": {
        "RetentionPeriodHours": 24, 
        "StreamStatus": "ACTIVE", 
        "StreamName": "name-of-your-stream", 
        "StreamARN": "arn:aws:kinesis:us-west-2:your-stream-info", 
        "Shards": [
           {
                "ShardId": "shardId-000000000113", 
                "HashKeyRange": {
                    "EndingHashKey": "14794885518301672324494548149207313541", 
                    "StartingHashKey": "0"
                }, 
                "ParentShardId": "shardId-000000000061", 
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49574208032121771421311268772132530603758174814974510866"
                }
            }, 
           { ... more shards ... }
       ...
您可以将记录的ExplicitHashKey设置为哈希键范围内任何一个整数值的字符串十进制表示形式,以便将其强制发送到特定的分片。请注意,由于之前对分片进行了合并和拆分操作,因此可能存在许多具有重叠HashKeyRanges的分片。当前打开的分片是没有SequenceNumberRange.EndingSequenceNumber元素的分片。
您可以通过识别感兴趣的每个分片范围内的128位整数,并将该数字的字符串表示形式轮流分配给每个记录的ExplicitHashKey,以在一组分片之间进行轮询请求。
另外,您还可以通过以下方式计算给定PartitionKey的哈希值:
  1. 计算分区键的MD5总和。
  2. 将MD5总和解释为十六进制数字并将其转换为十进制。这将是该分区键的哈希键。然后,您可以查找该哈希键所属的分片。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接