Счетчик шардов в Google App Engine не работает, получаются двойные числа - PullRequest
1 голос
/ 04 сентября 2011

Я пишу базу данных ошибок с помощью Google App Engine, и у меня возникают проблемы с получением уникальных номеров ошибок. Каждому жучку нужен уникальный номер, чтобы пользователи могли легко ссылаться на него, а числа должны быть простыми и как можно меньше. «Эй, я исправил ошибку 27» или «Я снова открыл ошибку 1867». Номера ошибок также должны увеличиваться, чтобы пользователи имели четкое представление о том, какие ошибки возникли после какой ошибки.

В App Engine нет настоящих счетчиков, таких как SQL, поэтому я реализовал следующую функцию, которая в основном представляет собой код, который рекомендует Google, но не работает постоянно.

Я иногда вижу повторяющиеся номера ошибок. В настоящее время я единственный человек, использующий базу данных ошибок (что значимо, эта ошибка находится в моей базе данных ошибок), и я не буду вводить ошибки быстрее, чем один раз в 5 или 10 секунд (если я печатаю быстро). Несмотря на то, что со временем появятся несколько пользователей, которые могут одновременно вводить ошибки.

class SimpleCounterShard(db.Model):
    count = db.IntegerProperty(required=True, default=0)

def getNewID():
    def txn():
        index = random.randint(0, NUM_SHARDS - 1)
        shard_name = "shard" + str(index)
        counter = SimpleCounterShard.get_by_key_name(shard_name)
        if counter is None:
            counter = SimpleCounterShard(key_name=shard_name)
        counter.count += 1
        counter.put()
    db.run_in_transaction(txn)

    total = 0
    for counter in SimpleCounterShard.all():
        total += counter.count

    return total

Что я делаю не так (или не понимаю)? Или лучше, если в некоторых случаях на производственных серверах появляются уникальные номера, которые не являются случайными, как, например, ключи или идентификаторы.

Ответы [ 2 ]

1 голос
/ 05 сентября 2011

У заштрихованных счетчиков будет точно такая же проблема - если вы можете так ее назвать - что есть у встроенных автоматически сгенерированных идентификаторов: они не гарантируют монотонность. Заштрихованные счетчики предназначены для подсчета вещей, а не для присвоения номеров вещам; в результате вы не можете получить сумму всех шардов в транзакции, и ваш результат неверен.

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

Если вам абсолютно необходимо иметь последовательные числа, вы можете использовать один счетчик и допускать максимальную скорость вставки 1-10 в секунду, или вы можете запустить «встречный» бэкэнд, который распределяет идентификаторы в пакетах из хранилища данных и раздает их в ответ на запросы RPC от вашего интерфейса. Если последнее звучит знакомо, это потому, что это то, что делают автоматически сгенерированные идентификаторы, только на нескольких машинах.

0 голосов
/ 05 сентября 2011

Ваш код не является потокобезопасным.Да, вы используете транзакцию для увеличения счетчика, но вы не используете его для чтения счетчика.Есть также другие шарды, которые вы не блокируете в этой транзакции (потому что они находятся в другой группе сущностей).Вы можете представить, что два запроса увеличивают счетчик, а затем оба читают значение после транзакции (получая одинаковые значения).Вам в основном нужно делать все в транзакции и иметь только один осколок.Это означает блокировку нескольких вызовов для нового идентификатора (их сериализация).Я бы предложил использовать разные счетчики для каждого проекта / тега / контекста / чего угодно, чтобы лучше масштабировать записи.

Подробнее о транзакциях здесь .

Честно говоряпросто бы использовал автоматически сгенерированные идентификаторы моделей на вашем месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...