Frage

ein GAE (Python) App Betrachten Sie die auf Songs Benutzer Kommentar lässt. Die erwartete Anzahl der Benutzer ist 1.000.000+. Die erwartete Anzahl von Songs ist 5000.

Die App muss in der Lage sein:

  • Geben Sie die Anzahl der Songs ein Benutzer kommentiert
  • Geben Sie die Anzahl der Benutzer, die auf einen Song kommentiert haben

Counter-Management muss Transaktions so sein, dass sie immer die zugrunde liegenden Daten widerspiegeln.

Es scheint, GAE-Anwendungen müssen diese Arten von Zählungen zu jeder Zeit berechnet halten, da zum Zeitpunkt der Anforderung für sie die Abfrage wäre ineffizient.

Meine Daten Modell

class Song(BaseModel):
    name = db.StringProperty()
    # Number of users commenting on the song
    user_count = db.IntegerProperty('user count', default=0, required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

class User(BaseModel):
    email = db.StringProperty()
    # Number of songs commented on by the user
    song_count = db.IntegerProperty('song count', default=0, required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

class SongUser(BaseModel):
    # Will be child of User
    song = db.ReferenceProperty(Song, required=True, collection_name='songs')
    comment = db.StringProperty('comment', required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

Code
Diese Griffe des transaktions Song Zählung des Benutzers, aber nicht die Benutzeranzahl des Songs.

s = Song(name='Hey Jude')
s.put()

u = User(email='me@example.com')
u.put()

def add_mapping(song_key, song_comment, user_key):
    u = User.get(user_key)

    su = SongUser(parent=u, song=song_key, song_comment=song_comment, user=u);
    u.song_count += 1

    u.put()
    su.put()

# Transactionally add mapping and increase user's song count
db.run_in_transaction(add_mapping, s.key(), 'Awesome', u.key())

# Increase song's user count (non-transactional)
s.user_count += 1
s.put()

Die Frage ist:? Wie kann ich beiden Zähler transaktions verwalten

Auf der Grundlage meiner dieses Verständnis wäre unmöglich, da Benutzer, Song, und SongUser würde ein Teil des gleichen Entitätsgruppe . Sie können nicht in einer Einheit Gruppe sein, weil dann alle meine Daten in einer Gruppe sein würde und es könnte nicht durch den Benutzer verteilt werden.

War es hilfreich?

Lösung

Sie sollen sich wirklich keine Sorgen machen müssen über die Benutzeranzahl von Songs Handhabung, auf das sie in einer Transaktion geäußert haben, weil es unwahrscheinlich scheint, dass ein Nutzer auf Kommentar zu einem Zeitpunkt auf mehr als einen Song der Lage sein würde, nicht wahr?

Nun, es ist definitiv der Fall, dass viele Nutzer auf dem gleichen Lied auf einmal kommentieren werden könnte, so dass ist, wo Sie Sorge haben sicher zu machen, dass die Daten nicht durch eine Race-Bedingung ungültig gemacht wird.

Wenn Sie jedoch die Zählung der Anzahl der Nutzer zu halten, die auf einem Song in der Song-Einheit kommentiert haben, und sperren Sie die Einheit mit einer Transaktion, Sie gehen für diese Entität sehr hohe Konkurrenz bekommen und Datenspeicher-Timeouts machen Sie Anwendung haben viele Probleme.

Diese Antwort für dieses Problem ist sharded Zähler .

Um sicher zu stellen, dass Sie eine neue SongUser Entität erstellen und aktualisieren Sie die sharded Zählers bezogen Song, sollten Sie die SongUser Entität, die haben als Eltern die zugehörige Lied. Das wird sie in der gleichen Einheit Gruppe setzen und Sie können sowohl die SongUser erstellen und den sharded Zähler in der gleichen Transaktion aktualisiert. Die SongUser Beziehung zu dem Benutzer, der sie erstellt wurden, können in einem Reference gehalten werden.

In Bezug auf Ihre Besorgnis über die zwei Aktualisierungen (die Transaktions ein und das Update Benutzer) nicht beide Erfolg, die immer eine Möglichkeit ist, aber wenn man bedenkt, dass entweder Update fehlschlagen können, müssen Sie, dass sowohl die richtige Ausnahmebehandlung zu gewährleisten, haben gelingen. Das ist ein wichtiger Punkt: die in transaktions Updates wird nicht garantiert zum Erfolg. Sie können eine TransactionfailedError Ausnahme, wenn die Transaktion nicht abgeschlossen werden kann aus irgendeinem Grunde erhalten.

Also, wenn Sie Ihre Transaktion abgeschlossen wird, ohne eine Ausnahme zu erhöhen, führen Sie das Update auf Benutzer in einer Transaktion. Das wird Ihnen automatische Wiederholungen des Updates auf Benutzer erhalten, sollte ein Fehler auftreten. Es sei denn, etwas über eine mögliche Konkurrenz auf der User-Einheit gibt es, dass ich nicht verstehe, dass die possiblity wird es nicht gelingen, schließlich ist surpassingly klein . Wenn das ein inakzeptables Risiko ist, dann glaube ich nicht, dass die App Engine eine perfekte Lösung für dieses Problem für Sie hat.

Zuerst fragen Sie sich: ist es wirklich so schlimm, wenn die Anzahl der Songs, dass jemand auf von einem ausgeschaltet hat kommentiert? Ist das so kritisch wie ein Bankkonto Gleichgewicht zu aktualisieren oder einen Aktienverkauf abgeschlossen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top