Ключ раздела Kinesis всегда находится в одном сегменте

У меня есть поток кинезиса с двумя осколками, который выглядит так:

{
    "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

Есть идеи, как это решить?


person isaac.hazan    schedule 10.11.2015    source источник


Ответы (2)


Прежде всего, просмотрите эти вопросы и ответы: Как определить общее количество ключей разделов в AWS kinesis stream?

О вашей ситуации; у вас есть 2 шарда, но их диапазон хеш-ключей не равен.

Количество ключей разделов, которые шард 1 содержит:

17014118346046923173168730371587 - 0 = 17014118346046923173168730371587

Количество ключей разделов, которые шард 2 содержит:

340282366920938463463374607431768211455 - 17014118346046923173168730371587 = 340282349906820117416451434263037839868

Между этими двумя есть большая разница;

17014118346046923173168730371587 : 17 x 10^30

340282349906820117416451434263037839868 : 34 x 10^37

Было бы замечательно, если бы сегмент 1 находился в диапазоне «0–170141183460469231731687303715884105727», а сегмент 2 - в диапазоне «170141183460469231731687303715884105728 - 340282366920938463463374607431768211455».

Вы, вероятно, использовали настольный компьютер или другой калькулятор с более низкой точностью. Попробуйте калькулятор получше. См. Пример ниже;

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();
    }

}
person az3    schedule 11.11.2015
comment
Правильно, это как раз та проблема, которая возникла, как я описал выше. Похоже, вы ответили на вопрос до того, как был загружен мой ответ. Хорошо, что вы его нашли, проголосовали за !!! - person isaac.hazan; 11.11.2015

После нескольких часов расследования я обнаружил основную причину - опять же человеческий фактор. Поделитесь решением здесь, даже если это просто сэкономить время, которое кто-то может потратить на него.

Проблема возникла из-за способа разделения исходного потока. Когда вы разделяете поток с одним осколком, вам нужно вычислить начальный хеш-ключ нового дочернего осколка. Этот новый хэш-ключ обычно находится в середине диапазона хэш-ключей родительского сегмента.

Вновь созданный осколок (родительский) будет иметь следующий диапазон:

0 - 340282366920938463463374607431768211455

Так что наивно вы идете к своему калькулятору Windows и копируете, вставляете это "340282366920938463463374607431768211455", а затем делите его на 2.

Проблема, которую я пропустил и которую легко упустить, заключается в том, что калькулятор Windows фактически обрезает число, не сообщая вам об этом. Приведенное выше число, вставленное в калькулятор, теперь будет «34028236692093846346337460743176». Как только вы разделите его на 2, вы фактически получите число, которое очень мало по сравнению с диапазоном родительского осколка, и тогда ваши записи не будут распространяться, они перейдут к осколку, который получил большую часть диапазона.

Как только вы возьмете указанное выше число в калькулятор, адаптированный для больших чисел, вы попадете прямо в середину диапазона. Я использовал это для вычисления диапазона: https://defuse.ca/big-number-calculator.htm.

После этого изменения записи отлично распределяются, и система хорошо масштабируется.

person isaac.hazan    schedule 11.11.2015
comment
Как хеш md5 по сравнению с диапазоном разделов, который указан в числах? Скажем, у меня есть paritionKey = 1, для которого хеш md5 равен c4ca4238a0b923820dcc509a6f75849b. Это относится к Части 1 или 2? - person prayagupd; 26.05.2017
comment
Кажется, что partitionKey 1 переходит в shard1 (261578874264819908609102035485573088411 -> shardId-000000000001), а PatitionKey 96 идет в shard0 (51037628727478963551185524537127703940 -> shardId-000000000000) - person prayagupd; 26.05.2017