2016-08-25 2 views
0

Я пытаюсь добиться сильной консистенции. Назовём моя модель PVPPlayer:AppEngine достижение сильной консистенции

class PVPPlayer(ndb.Model): 
    points = ndb.IntegerProperty() 

Каждый ключ для модели создается следующим образом:

pvp_player = PVPPlayer(key=ndb.Key(Profile, "test_id", PVPPlayer, "test_id")) 

где Profile является родительская модель:

class Profile(ndb.Model): 
    def build_key(cls, some_id): 
     return ndb.Key(cls, some_id) 

У меня есть 2 REST API URL:

1) update_points 
2) get_points 

В 1) я:

# I use transaction because I have to update all the models in single batch 
@ndb.transactional(xg=True, retries=3) 
def some_func(points): 
    pvp_player = ndb.Key(Profile, "test_id", PVPPlayer, "test_id").get() 
    pvp_player.points += points 
    pvp_player.put() 
    # update other models here` 

В 2) я:

pvp_player = ndb.Key(Profile, "test_id", PVPPlayer, "test_id").get() 
return pvp_player.points` 

Мой поток выглядит следующим образом:

1) update_points() 
2) get_points() 
3) update_points() 
4) get_points()` 
... 

Проблема:

Использование get() гарантирует высокую согласованность o что я не понимаю, почему иногда в результате get_points() я получаю устаревшие данные, такие как точки не обновлялись вообще.

Пример:

POST get_points -> 0 
POST sleep 1-3 sec 
POST update_points -> 15 
POST sleep 1-3 sec 
POST get_points -> 15 
POST sleep 1-3 sec 
POST update_points -> 20 
POST sleep 1-3 sec 
POST get_points -> 15 !!!` 
+0

Ваша функция # 2 также украшены '@ndb .transactional'? Кроме того, я предполагаю, что имя функции «update_points» в # 1 действительно «update_points», правильно? –

+0

> Является ли ваша # 2 функция также украшенной @ ndb.transactional? Я попытался добавить @ ndb.transactional для # 2, но это не имеет значения - оно по-прежнему дает мне устаревшие данные время от времени > имя функции update_points в # 1 действительно update_points, не так ли? Абсолютно –

+0

Извините, я имел в виду 'some_func'' 'update_points'? :) –

ответ

1

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

+0

Физический игрок является единственным, кто обновляет модель PVPPlayer.Ситуация, когда кто-то делает 2 запроса update_points() одновременно для одной и той же модели, вообще не может произойти в соответствии с логикой игры –

+0

На самом деле еще страннее то, что иногда между 15-секундным интервалом обновления (15) все еще устаревший, поэтому он ведет себя точно так же, как и конечная согласованность, но я не могу понять, почему –

2

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

Также проверьте все ваши обновления, завернутые в транзакции, чтобы избежать гонок. Cloud Datastore: ways to avoid race conditions


Этот случай, скорее всего, не о проблемах согласованности, но топать обновления, проверка этой ссылки на некоторые интересные случаи:

http://engineering.khanacademy.org/posts/transaction-safety.htm http://engineering.khanacademy.org/posts/user-write-lock.htm

+0

Я просто понял, что один из моих запросов обновляет мою родительскую модель (например, Профиль) одновременно с update_points(). Это похоже на проблему –

+0

Должен ли я назначать другой родительский ключ, чтобы избежать этой проблемы? –

+0

Все, что разделяет родительский ключ, включая родительский, находится в одной группе сущностей. –

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