[英]Java Google Appengine sharded counters without transactions
我正在使用Java中的分片計數器示例: http : //code.google.com/appengine/articles/sharding_counters.html
我對遞增方法的實現有疑問。 在python中,它顯式包裝get()和增量在事務中。 在Java示例中,它只是檢索並設置它。 我不確定我是否完全了解數據存儲區和事務,但關鍵更新部分似乎應該包裝在數據存儲區事務中。 我想念什么嗎?
原始代碼:
public void increment() {
PersistenceManager pm = PMF.get().getPersistenceManager();
Random generator = new Random();
int shardNum = generator.nextInt(NUM_SHARDS);
try {
Query shardQuery = pm.newQuery(SimpleCounterShard.class);
shardQuery.setFilter("shardNumber == numParam");
shardQuery.declareParameters("int numParam");
List<SimpleCounterShard> shards =
(List<SimpleCounterShard>) shardQuery.execute(shardNum);
SimpleCounterShard shard;
// If the shard with the passed shard number exists, increment its count
// by 1. Otherwise, create a new shard object, set its count to 1, and
// persist it.
if (shards != null && !shards.isEmpty()) {
shard = shards.get(0);
shard.setCount(shard.getCount() + 1);
} else {
shard = new SimpleCounterShard();
shard.setShardNumber(shardNum);
shard.setCount(1);
}
pm.makePersistent(shard);
} finally {
pm.close();
}
}
}
事務代碼(我相信您需要在事務中運行此代碼以確保並發事務下的正確性嗎?):
public void increment() {
PersistenceManager pm = PMF.get().getPersistenceManager();
Random generator = new Random();
int shardNum = generator.nextInt(NUM_SHARDS);
try {
Query shardQuery = pm.newQuery(SimpleCounterShard.class);
shardQuery.setFilter("shardNumber == numParam");
shardQuery.declareParameters("int numParam");
List<SimpleCounterShard> shards =
(List<SimpleCounterShard>) shardQuery.execute(shardNum);
SimpleCounterShard shard;
// If the shard with the passed shard number exists, increment its count
// by 1. Otherwise, create a new shard object, set its count to 1, and
// persist it.
if (shards != null && !shards.isEmpty()) {
Transaction tx = pm.currentTransaction();
try {
tx.begin();
//I believe in a transaction objects need to be loaded by ID (can't use the outside queried entity)
Key shardKey = KeyFactory.Builder(SimpleCounterShard.class.getSimpleName(), shards.get(0).getID())
shard = pm.getObjectById(SimpleCounterShard.class, shardKey);
shard.setCount(shard.getCount() + 1);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
} else {
shard = new SimpleCounterShard();
shard.setShardNumber(shardNum);
shard.setCount(1);
}
pm.makePersistent(shard);
} finally {
pm.close();
}
}
文檔的這一部分直接表明您完全需要進行交易:
http://code.google.com/appengine/docs/java/datastore/transactions.html#Uses_For_Transactions
本示例演示了事務的一種用法:使用相對於其當前值的新屬性值更新實體。
Key k = KeyFactory.createKey("Employee", "k12345");
Employee e = pm.getObjectById(Employee.class, k);
e.counter += 1;
pm.makePersistent(e);
這需要進行事務處理,因為在此代碼獲取對象之后但在保存修改后的對象之前,其他用戶可能會更新該值。 如果沒有事務,則用戶的請求將在其他用戶更新之前使用counter的值,並且保存將覆蓋新值。 通過事務,該應用程序將被告知其他用戶的更新。 如果在事務期間更新實體,則事務將失敗,並發生異常。 應用程序可以重復交易以使用新數據。
它與分片示例的操作非常接近,並且像您一樣,我無法找到分片計數器不同的任何原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.