1

Взято из this artice на шариковых счетчиках, следующая функция демонстрирует, как случайный осколок выбран до его приращения. Это происходит в транзакции.Оверенные счетчики в пределах транзакции

def increment(): 
    """Increment the value for a given sharded counter.""" 
    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) 

Может только одна сделка состоится в то время, и было бы, что не мешает различных (случайных) sharded счетчики обновляться одновременно? Если да, то какова цель подсчетных счетчиков, если только один подсвеченный счетчик может обновляться за раз?

Спасибо!

ответ

5

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

Каждый осколок представляет собой отдельный объект. Это позволяет одновременно обновлять различные осколки.

Если транзакция происходит, чтобы попытаться ударить осколок (из-за генератора случайных чисел), который уже находится в транзакции, транзакция завершится с ошибкой.

+0

Когда транзакция завершается с ошибкой, она пытается повторить попытку несколько раз (я думаю, 5), прежде чем провалиться навсегда, что в этом случае в конечном итоге удастся получить неблокированный осколок. –

+0

Неправильно: транзакции на GAE не блокируют: они используют оптимистичный контроль параллелизма, а это означает, что при совершении транзакции он проверяет внутреннее поле для проверки версий, а если изменено (= кто-то другой изменил значения в одно и то же время), он выдает исключение: https://developers.google.com/appengine/docs/java/datastore/transactions#What_Can_Be_Done_In_a_Transaction –

+0

Питон api через db.run_in_transaction попробует 3 раза. – Greg

3

Нет, это отдельные транзакции, которые не блокируют друг друга, а также ограничение записи применяется только к каждому объекту отдельно.

Обоснование: в вашем случае объекты SimpleCounterShard не имеют родителя, что означает, что каждая сущность является корнем собственной группы сущностей. Область транзакций - это группа сущностей, а также ограничение на одновременную запись применяется к группе сущностей.

+0

Вопрос: Можно ли использовать подсчётный счет (hash it) и использовать его как уникальный String-ключ для объекта GAE, не будет ли он (сгенерированный счетчик для данного типа) в какой-то момент? \ – xybrek

+0

@xybrek Не уверен Я это понимаю, но: конечно, это столкнулось бы - такое же значение счета создало бы одно и то же значение хэша и, таким образом, тот же самый ключ. Таким образом, разные счетчики с одинаковым значением счета будут создавать один и тот же ключ и перезаписывать друг друга. Кроме того, даже без столкновения, как это должно работать? Каждый раз, когда изменяется значение счетчика, вы создадите новый объект? –

+0

не создавать новое сущность для каждого изменения счетчика, но использовать значение счетчика как идентификатор для объекта, так как мне нужно, чтобы идентификаторы объектов начинались с 1 (или, по крайней мере, очень маленького длинного значения) и т. Д. GAE генерирует довольно длинные длинные значения, которые могут привести к поражению цели моего приложения. – xybrek