【问题标题】:Kinesis partition key falls always in the same shardKinesis 分区键始终位于同一个分片中
【发布时间】:2015-11-10 15:24:30
【问题描述】:

我有一个带有 2 个分片的运动流,如下所示:

{
    "StreamDescription": {
        "StreamStatus": "ACTIVE",
        "StreamName": "my-stream",
        "Shards": [
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "17014118346046923173168730371587",
                    "StartingHashKey": "0"
                },
            {
                "ShardId": "shardId-000000000002",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "17014118346046923173168730371588"
                },
        ]
    }
}

发送方设置一个通常是 UUID 的分区。它总是落在 shard-002 以上,这使得系统没有负载平衡,因此无法扩展。

作为旁注,kinesis 使用 md5sum 分配记录,然后将其发送到包含其范围内结果哈希的分片。事实上,当我在我使用的 UUId 上对其进行测试时,它们确实总是落在同一个分片中。

echo -n 80f6302fca1e48e590b09af84f3150d3 | md5sum
4527063413b015ade5c01d88595eec11  

17014118346046923173168730371588 < 4527063413b015ade5c01d88595eec11 < 340282366920938463463374607431768211455

你知道如何解决这个问题吗?

【问题讨论】:

    标签: amazon-kinesis


    【解决方案1】:

    首先看这个问答:How to decide total number of partition keys in AWS kinesis stream?

    关于你的情况;您有 2 个分片,但它们的哈希键范围不相等。

    分片 1 包含的分区键数:

    17014118346046923173168730371587 - 0 = 17014118346046923173168730371587

    分片 2 包含的分区键数:

    340282366920938463463374607431768211455 - 17014118346046923173168730371587 = 340282349906820117416451434263037839868

    这两者有很大的不同;

    17014118346046923173168730371587:17 x 10^30

    340282349906820117416451434263037839868:34 x 10^37

    如果shard 1是碎片1是在“0 - 17014118346047303715884604720371588460472093715884604690371588460374607454/2114607455703440938845578211445598093074559809388455782114455”和碎片2之间。

    您可能使用过台式机或其他精度较低的计算器。试试更好的计算器。请参阅下面的示例;

    package com.cagricelebi.kinesis.core.utils;
    
    import java.math.BigInteger;
    
    public class MyCalc {
    
        public static void main(String[] args) {
            try {
    
                String num1 = "340282366920938463463374607431768211455";
                String num2 = "-17014118346046923173168730371587";
    
                String diff = bigCalc(num1, num2, "1", "1");
                System.out.println("result1 : " + diff); // 340282349906820117416451434263037839868
    
                String optimumHalf = bigCalc(num1, "0", "1", "2");
                System.out.println("result2 : " + optimumHalf); // 170141183460469231731687303715884105727
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Basic calculator.
         * First adds up first two elements, than multiplies the summation.
         * The result is the division of the multilication to divisor.
         *
         * @param bigInt A
         * @param bigInt2 B
         * @param multiplicator C
         * @param divisor D
         * @return ((A+B)*C)/D
         */
        private static String bigCalc(String bigInt, String bigInt2, String multiplicator, String divisor) {
            BigInteger summation = new BigInteger(bigInt).add(new BigInteger(bigInt2));
            BigInteger multiplication = summation.multiply(new BigInteger(multiplicator));
            BigInteger division = multiplication.divide(new BigInteger(divisor));
            return division.toString();
        }
    
    }
    

    【讨论】:

    • 对,这正是发生的问题,如上所述。好像你在我的回复上传之前回答了这个问题。很好,你找到了,点赞!!!
    【解决方案2】:

    经过几个小时的调查,我找到了根本原因,再次是人为错误。在这里分享解决方案,即使这样可以节省其他人花在上面的时间。

    问题是由于原始流的拆分方式造成的。当您使用一个分片拆分流时,您必须计算新子分片的起始哈希键。这个新的散列键通常在父分片散列键范围的中间。

    新创建的分片(父)将具有以下范围:

    0 - 340282366920938463463374607431768211455
    

    所以你天真地去你的Windows计算器并复制粘贴这个“340282366920938463463374607431768211455”然后除以2。

    我错过并且很容易错过的问题是 Windows 计算器实际上会在不让您知道的情况下截断数字。上面粘贴在计算器中的数字现在将是 "34028236692093846346337460743176" 。一旦你将它除以 2,你实际上会得到一个与父分片的范围相比非常小的数字,然后你的记录将不会被分发,它们将转到获得范围较大部分的分片。

    一旦您将上面的数字用于适合大数字的计算器,您就会得到该范围的中间值。 我用它来计算范围:https://defuse.ca/big-number-calculator.htm

    进行此更改后,记录完美分布,系统可很好地扩展。

    【讨论】:

    • md5 散列与分区范围相比如何?假设我有 paritionKey="1",其中 md5 哈希为c4ca4238a0b923820dcc509a6f75849b。是去分区 1 还是分区 2?
    • 似乎 partitionKey 1 进入 shard1 (261578874264819908609102035485573088411 -&gt; shardId-000000000001) 而 PatitionKey 96 进入 shard0 (51037628727478963551185524537127703940 -&gt; shardId-000000000000)
    猜你喜欢
    • 1970-01-01
    • 2019-06-20
    • 2021-01-03
    • 2019-06-24
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多