Подтвердить что ты не робот

Почему Google TrueTime API трудно дублировать?

Я не уверен, почему в прессе вообще говорится, что Google TrueTime API трудно реплицировать (Wired, Slashdot и т.д.).

Я могу понять, как было бы трудно получить низкие интервалы ошибок, которые Google достигнет, но я не вижу, как сам API будет очень сложным.

Например, я взломал взломанную вместе версию. Здесь интервал.

    typedef struct TT_interval {
            struct timeval earliest;
            struct timeval latest;
    } TT_interval;

Здесь функция now.

    int TT_now(TT_interval* interval)
    {
        struct ntptimeval tv;
        struct timeval delta;

        struct timeval* earliest_p = &(interval->earliest);
        struct timeval* latest_p = &(interval->latest);
        struct timeval* now_p = &(tv.time);
        struct timeval* delta_p = δ

        timerclear(&delta);
        timerclear(&interval->earliest);
        timerclear(&interval->latest);

        if(ntp_gettime(&tv) == 0) {
            tv.maxerror = tv.maxerror > 0 ? tv.maxerror : -(tv.maxerror);

            delta.tv_sec = delta.tv_sec + (tv.maxerror / 1000);
            delta.tv_usec = delta.tv_usec + ((tv.maxerror % 1000) * 1000);

            if(delta.tv_usec > 1000000) {
                delta.tv_usec -= 1000000;
                delta.tv_sec++;
            }

            timeradd(now_p, delta_p, latest_p);
            timersub(now_p, delta_p, earliest_p);
        } else {
            printf("error on ntp_gettime. %s\n", strerror(errno));
            return ERROR;
        }

        return SUCCESS;
    }

Наконец, здесь функции before и after (которые являются оболочками вокруг функции now и могут использовать немного СУХОГО рефакторинга).

    int TT_before(TT_interval* interval, bool* success)
    {
        struct timeval* latest_p;
        struct timeval* earliest_p;
        TT_interval now;

        if(TT_now(&now) != SUCCESS) {
            return ERROR;
        }

        latest_p = &(interval->latest);
        earliest_p = &(now.earliest);

        if(timercmp(latest_p, earliest_p, <) != 0) {
            *success = true;
            return SUCCESS;
        } else {
            *success = false;
            return SUCCESS;
        }

        return ERROR;
    }

   int TT_after(TT_interval* interval, bool* success)
    {
        struct timeval* latest_p;
        struct timeval* earliest_p;
        TT_interval now;

        if(TT_now(&now) != SUCCESS) {
            return ERROR;
        }

        earliest_p = &(interval->latest);
        latest_p = &(now.earliest);

        if(timercmp(latest_p, earliest_p, <) != 0) {
            *success = true;
            return SUCCESS;
        } else {
            *success = false;
            return SUCCESS;
        }

        return ERROR;
    }

Кажется, что я получаю интервальные ошибки в пределах от 5000 до 350 000 (используя публичный NTPd). Это далеко от цифр Google, но вам нужно где-то начать.

Помимо тусклой производительности, есть ли главный недостаток в этом дизайне, который предотвратил бы создание чего-то вроде Spanner сверху?

4b9b3361

Ответ 1

Задача по внедрению API TrueTime заключается в гарантиях, которые вы должны предоставить. А именно, абсолютное время должно никогда находиться вне интервала TrueTime на любом сервере в системе. Если это может произойти, то теряется абсолютное упорядочение событий, как и большинство гарантий "Гаечного ключа".

Бумага для гаечных ключей достигает этого с помощью комбинации средств (раздел 3):

  • Несколько серверов времени с разрозненными источниками (GPS, атомные часы), включая серверы времени из других датацентров.
  • Алгоритм Marzullos для обнаружения лжецов и мультиплексирования различных источников надежного времени в обновление локальных машинных часов.
  • Предполагаемый дрейф часов 200us/s в spanservers, применяемый между синхронизацией часов.
  • Выкалывание машин из системы, которые показывают измеренный локальный сдвиг часов > порог (порог < 200us/s по необходимости).

Теперь вы можете добиться этого с помощью более простых средств - NTP и предполагаемый интервал ошибок в 10 минут тривиально. Но, как отмечалось в этом вопросе, это связано с результатами. Операции чтения и записи (4.2.1) должны ждать при фиксации с ожидаемым временем ожидания 2 * errorAverage - 20 минут в этом примере. Точно так же транзакции только для чтения (4.2.2) в момент "сейчас" - а не время в прошлом - должны ждать, пока безопасное время продвинется достаточно далеко; не менее 10 минут в этом примере. Таким образом, чтобы иметь высокопроизводительную систему, вам нужно максимально минимизировать интервалы ошибок, не теряя при этом своих гарантий, в которых возникает сложность.

Я не уверен, как в вашей системе вызывается ntp_adjtime - возможно, он уже настроен с использованием нескольких ненадежных и некоррелированных источников времени, и в этом случае вы больше всего там. Если вы также можете гарантировать, что значение maxerror гарантированно будет продвигаться быстрее, чем возможный дрейф часов вашей системы, вам должно быть хорошо идти. Большая часть производительности Spanner, без ваших личных атомных часов:).