Как избежать разногласий в хранилище данных - PullRequest
0 голосов
/ 14 марта 2012

У меня проблема с дизайном, у моего приложения растет трафик, и у меня часто возникает «Коллизия транзакций. Повторная попытка ...». Я не знаю, как их избежать.

Введение: Каждый актер в этом приложении может посетить другого актера.

Это мой фактический дизайн (могут быть ошибки, это просто пример) :

class Actor(object):
  name = db.StringProperty()

class ActorVisits(object):
  """Store a list of all actors has visited the parent of this kind

  Note: Has an ancestor an Actor
  """
  visits = db.ListProperty(db.Key)

class Visit(object):
  """A new visit by actor on the parent of this kind.
  Each time a same actor visits the parent of this kind, this kind is updated
  with the new datetime for the visit.

  Note: Has an ancestor an Actor
  """
  actor = db.ReferenceProperty(collection_name=Actor)
  visited_at = db.datetimeProperty()

Это пример использования:

foo = Actor(name="foo")  
bar = Actor(name="bar")

db.put([foo, bar])

def trx():
  """Store a new visite from 'bar' to 'foo' """

  av = ActorVisits.get_bey_keys_name(key_name="v/foo", parent=foo)
  if av is None:
    av = ActorVisits(key_name="v/foo", parent=foo)

  v = Visit.get_bey_keys_name(key_name="v/foo/bar", parent=foo, actor=bar)
  if v is None:
    v = Visit(key_name="v/foo/bar", parent=foo, actor=bar)
  v.visited_at = datetime.datetime.utcnow()
  async = db.put_async(v)

  if not v.key() in av.visits:
    av.visits.append(v.key())
    av.put()

  async.get_result()

db.run_in_transaction(trx, bar, foo)

Если у кого-нибудь есть идея сделать эту модель лучше. Спасибо

1 Ответ

2 голосов
/ 14 марта 2012

Сделайте Посещения в конечном итоге непротиворечивыми, удалив их из EntityGroup Актера. Если каждое посещение является корневым объектом, вы не столкнетесь с какими-либо проблемами, связанными со скоростью записи, и сможете легко их запросить.

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

Итак, у актера Id 123, Vistor (другой актер) имеет идентификатор 888,

Вы создаете ключ типа «Визит» с идентификатором «123_888» (без родительского элемента), Вы ставите () «Посещение» с этим ключом и обновленным временем, и оно перезаписывает предыдущее посещение. Вы также можете выполнить get () для ключа, и он будет строго согласован (если вы ведете счет).

Затем вы можете создавать ActorVisits с в конечном итоге согласованным запросом.

...