2012-03-14 92 views
0

我有一個設計問題,我的應用程序有一個成長的流量,我有很多「交易衝突。重試...」。我不知道如何避免他們。避免數據存儲競爭

介紹: 這個應用程序中的每個演員都可以訪問另一個演員。

這是我的實際設計(它可以有錯誤,它只是一個例子)

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) 

如果有人有一個想法對我來說,讓這個模型更好。謝謝

+0

我假設你沒有實際使用硬編碼的key_name字符串,當你搜索你的ActorVisits和Vist?這意味着你總是隻修改一個ActorVisits對象。 – dragonx 2012-03-14 14:13:33

+0

@dragonx:是的,這只是我寫得很快的一個例子。 – sahid 2012-03-14 14:17:43

回答

2

通過將訪問移出Actor的EntityGroup,使訪問最終保持一致。如果每次訪問都是根實體,則不會遇到任何寫入速率問題,您可以輕鬆查詢它們。

如果您不想創建大量訪問實體,但只需更新一個訪問實體,則可以通過將訪問實體與演員和訪問者區分開來,確定訪問確定性的關鍵。

所以演員有123標識, 位訪客(其他演員)有888標識,

你讓類型訪問的關鍵,用 「123_888」(無父),你把ID()的使用此密鑰訪問並更新時間,並覆蓋以前的訪問。你也可以在鍵上做一個get(),並且它會非常一致(如果你保持一個計數說)。

然後,您可以使用最終一致的查詢來構建ActorVisits。

+0

請注意,根實體也可能存在爭用問題 – systempuntoout 2012-05-27 19:47:15