1

this artice採取分片計數器,下面的函數演示了在遞增之前如何選擇一個隨機分片。這發生在一個事務中。事務中的分片計數器

def increment(): 
    """Increment the value for a given sharded counter.""" 
    def txn(): 
     index = random.randint(0, NUM_SHARDS - 1) 
     shard_name = "shard" + str(index) 
     counter = SimpleCounterShard.get_by_key_name(shard_name) 
     if counter is None: 
      counter = SimpleCounterShard(key_name=shard_name) 
     counter.count += 1 
     counter.put() 
    db.run_in_transaction(txn) 

只有一個事務可以發生在一個時間是不是會阻止不同的(隨機)分片將同時更新計數器? 如果是這樣,什麼是分片計數器的目的,如果只有一個分片計數器可以在同一時間進行更新?

謝謝!

回答

5

交易鎖定所有參與交易的實體。只要不觸及相同的實體,您就可以進行多項交易。

每個碎片是一個獨立的實體。這使您可以同時更新各種分片。

如果事務正好嘗試擊中已經在事務中的碎片(由於隨機數發生器),則事務將失敗。

+0

當事務失敗時,它會在失敗前嘗試重試幾次(我認爲是5),在這種情況下,最終會成功挑選未鎖定的碎片。 –

+0

錯誤:在GAE上的交易不做鎖定:他們用樂觀併發控制,這意味着當事務被提交它檢查內部版本字段,如果沒有改變(=在同一時間別人改變的值),它拋出一個異常:HTTPS:/ /developers.google.com/appengine/docs/java/datastore/transactions#What_Can_Be_Done_In_a_Transaction –

+0

Python API中,通過db.run_in_transaction,將嘗試3次。 – Greg

3

不,這是單獨的交易,不會彼此阻塞,寫入限制也僅適用於每個實體。

理由:在你的情況下SimpleCounterShard實體沒有父節點,這意味着每個實體都是它自己的實體組的根節點。事務的範圍是實體組,同時寫入限制也適用於實體組。

+0

問題:使用分片計數(哈希值)並將其用作GAE實體的唯一字符串密鑰是否可行?是否它(給定類型的生成計數)在某個點不會相互衝突?\ – xybrek

+0

@xybrek不確定我理解這一點,但是:當然它會碰撞 - 相同的計數值將創建相同的散列值,從而相同的密鑰。因此具有相同計數值的不同計數器將創建相同的密鑰並相互覆蓋。而且,即使沒有碰撞,這應該如何工作?每次計數器值發生變化時,您都會創建一個新的實體? –

+0

不會爲每個計數器更改創建新實體,而是使用計數器值作爲實體的ID,因爲我需要實體ID將以1開頭(或者至少有一個非常小的長值),等等。 GAE會生成相當長的Long值,這會破壞我的應用程序的目的 – xybrek