どのようにカウントの両側多対多の関係にGoogle App Engine
-
20-09-2019 - |
質問
考えGAE(python)アプリはユーザにコメントを行います。想されるユーザ数は1,000,000+.想される楽曲数は5,000.
このアプリができること:
- の楽曲数、ユーザーにと
- のユーザー数人が歌
カウンター管理における取引そのものの背景にあるデータです。
そうでGAEのアプリを続けなければこれらの種類の数の計算時以降の照会に対して要求する効率が悪い。
私のデータモデル
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)
コード
このユーザーの曲をカウントtransactionallyなのユーザー数です。
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()
ここでの問いは どのようになったという経験を通じて両方のカウンター transactionally?
に基づきこれらを理解することでユーザー、歌、SongUserいるのと同じ エンティティグループ.することができませんティグループがその全てのデータが一つのグループで配布されます。
解決
あなたは本当に正しい、ユーザーが一度に複数の曲にコメントすることができるだろうとは考えにくいので、彼らはトランザクション内でコメントしている上の曲の利用者の数を扱う心配する必要はありません。<? / P> あなたは、データが競合状態によって無効にされていないことを確認することを心配する必要が場所なので、
さて、それは、間違いなく多くのユーザーが同時に同じ曲にコメントすることができた場合です。
ソングエンティティ内の曲にコメントしているユーザー数のカウントを保持し、トランザクションを持つエンティティをロックする場合は、しかし、あなたはそのエンティティとデータストアのタイムアウトのための非常に高い競合が行います得ようとしていますあなたのアプリケーションは、多くの問題を持っています。
この問題のために、この答えはシャードカウンターをされます。
あなたは新しいSongUserエンティティを作成し、関連する曲のシャードカウンタを更新できることを確認するためには、SongUserエンティティが親として、関連の歌を持って検討する必要があります。これは、同じエンティティグループに入れますと、あなたは両方SongUserを作成することができますし、同じトランザクション内のシャードのカウンタを更新しました。それを作成したユーザーにSongUserの関係はReferencePropertyで開催することができます。
2回の更新(トランザクション1とユーザー更新)両方ではなく、後続についてのあなたの懸念については、それは常に可能性があるが、どちらかのアップデートが失敗する可能性があることを考えると、あなたは、両方のことを確実にするために、適切な例外処理が必要になります成功します。これは重要なポイントです:イン・トランザクション更新は成功することは保証されません。トランザクションが何らかの理由で完了できない場合は、TransactionfailedError例外を得ることができます。
あなたのトランザクションは、例外を発生させずに完了した場合、だから、トランザクションでユーザーに更新を実行します。それはあなたのユーザーへのアップデートの自動再試行は、何らかのエラーが発生しなければならないでしょう。私は理解していないユーザー・エンティティの可能性の競合についての何かがありますない限り、それは最終的には成功しないだろうというpossiblityはののsurpassingly小さいです。それは容認できないリスクがある場合、私はAppEngineのは、あなたのために、この問題への完璧なソリューションを持っていることはないと思う。
まず自問してください:誰かがコメントした曲のカウントが1でオフになっている場合は、のは、それは本当に悪いのですか?銀行口座の残高を更新するか、株式売却を完了したとして、このように重要なのですか?の