1

Вот ситуация у меня есть модель, какКак обновить данные об объекте Google App Engine ОПРС, так что он отлично работает для нескольких записи одновременно

class Content(ndb.Model): 
    likeCount=ndb.IntegerProperty(default=0) 
    likeUser = ndb.KeyProperty(kind=User, repeated=True) 

Когда новый контент генерируют чем новый «Содержимое» объект создается как

content_obj_key = Content(parent=objContentData.key, #Where ContentData is  another ndb.Model subclass 
          likeUser=[], 
          likeCount=0 
          ).put() 

И когда любой пользователь, как же содержание, чем ниже функция вызывается

def modify_like(contentData_key, user_key): 
    like_obj = Content.query(parent=contetData_key).get() 
    if like_obj: 
     like_obj.likeUser.append(user_key) 
     like_obj.likeCount += 1 
     like_obj.put() 

Проблема:
Теперь проблема заключается в том, что при одновременном использовании более 4 пользователей, таких же, как этот объект, записывают неправильные данные.
Я имею в виду, скажем, userA, userB, userC и userD как эти данные одновременно, и в настоящее время только пользователю нравится тот же контент.
Итак, все новые четыре записи «likeCount» не 5, всегда меньше 5, а длина списка «likeUser» также меньше 5.

Итак, как я могу решить эту проблему? Так что всегда данные остаются согласованными.

+0

Если я удаляю «родительское» ограничение, в котором указано, что «всего 1 запись/сек», чем та же проблема. – AnkurJat

+1

читал о возможной согласованности. есть много других s.o. вопросы и статьи, касающиеся этого. –

+0

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

ответ

1

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

Если пользовательA и userB получают объект Content одновременно, оба имеют одинаковое значение счета (например, Count = 1). Затем оба прироста до значения 2 - когда оно должно быть в общей сложности 3.

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

NUM_SHARDS = 5 

class SimpleCounterShard(ndb.Model): 
    """Shards for the counter""" 
    count = ndb.IntegerProperty(default=0) 

def get_count(): 
    """Retrieve the value for a given sharded counter. 

    Returns: 
     Integer; the cumulative count of all sharded counters. 
    """ 
    total = 0 
    for counter in SimpleCounterShard.query(): 
     total += counter.count 
    return total 

@ndb.transactional 
def increment(): 
    """Increment the value for a given sharded counter.""" 
    shard_string_index = str(random.randint(0, NUM_SHARDS - 1)) 
    counter = SimpleCounterShard.get_by_id(shard_string_index) 
    if counter is None: 
     counter = SimpleCounterShard(id=shard_string_index) 
    counter.count += 1 
    counter.put() 

Более подробную информацию и примеры на прилавках Sharding можно найти по адресу: https://cloud.google.com/appengine/articles/sharding_counters

+0

Спасибо, Джефф за ваш ответ. Я попробую это, и вы скоро узнаете. – AnkurJat

0

Использование transactions:

@ndb.transactional(retries=10) 
def modify_like(contentData_key, user_key): 
    ... 

транзакция представляет собой операцию или набор операций, которые гарантированы , чтобы быть атомарным, что означает, что транзакции никогда не частично применяются . Используются либо все операции в транзакции, , либо ни одно из них не применяется. Транзакции имеют максимальную продолжительность 60 секунд с истечением 10 секунд бездействия через 30 секунд.

+0

Brent #transaction гарантированно для атомных, но что, если обе транзакции считывают одно и то же значение?В этом случае оба завершатся, но результат будет неправильным, поскольку Джефф и я проиллюстрируем примерами. – AnkurJat

+0

Поскольку набор операций в 'modify_like()' является гарантией быть атомарным, более поздний запрос будет терпеть неудачу и повторить попытку. Затем он получит обновленный объект 'like_obj'. –

 Смежные вопросы

  • Нет связанных вопросов^_^