2010-09-23 27 views
10

Tôi đang đi qua Sharded Quầy dụ trong Java: http://code.google.com/appengine/articles/sharding_counters.htmlJava Google AppEngine quầy sharded mà không giao dịch

Tôi có một câu hỏi về việc thực hiện các phương pháp thặng dư. Trong python nó kết thúc một cách rõ ràng get() và tăng trong một giao dịch. Trong ví dụ Java nó chỉ lấy nó và thiết lập nó. Tôi không chắc tôi hoàn toàn hiểu được Datastore và các giao dịch nhưng có vẻ như phần cập nhật quan trọng cần được gói trong một giao dịch kho dữ liệu. Tui bỏ lỡ điều gì vậy?

đang Original:

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(); 
    } 
    } 
} 

đang giao dịch (Tôi tin rằng bạn cần phải chạy này trong một giao dịch để bảo lãnh đúng đắn dưới giao dịch đồng thời?):

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(); 
    } 
    } 

Trả lời

6

Phần này thẳng ra khỏi các tài liệu cho thấy rằng bạn hoàn toàn chính xác về việc cần một giao dịch:

http://code.google.com/appengine/docs/java/datastore/transactions.html#Uses_For_Transactions

Ví dụ này minh họa một lần sử dụng giao dịch: cập nhật thực thể có giá trị thuộc tính mới tương ứng với giá trị hiện tại của nó.

Key k = KeyFactory.createKey("Employee", "k12345"); 
    Employee e = pm.getObjectById(Employee.class, k); 
    e.counter += 1; 
    pm.makePersistent(e); 

Điều này đòi hỏi một giao dịch vì giá trị có thể được cập nhật bởi một người dùng khác sau khi mã này lấy về đối tượng, nhưng trước khi nó tiết kiệm đối tượng điều chỉnh. Không có giao dịch, yêu cầu của người dùng sẽ sử dụng giá trị bộ đếm trước bản cập nhật của người dùng khác và lưu sẽ ghi đè giá trị mới. Với một giao dịch, ứng dụng được thông báo về bản cập nhật của người dùng khác. Nếu thực thể được cập nhật trong giao dịch thì giao dịch sẽ không thành công với ngoại lệ. Ứng dụng có thể lặp lại giao dịch để sử dụng dữ liệu mới.

Rất gần với ví dụ mà bạn đã làm và, như bạn, tôi không thể tìm thấy bất kỳ lý do nào khiến các quầy phân phát khác nhau.

+1

Tôi đã tạo sự cố mở trên trình theo dõi vấn đề Appengine: http://code.google.com/p/googleappengine/issues/detail?id=3778 – Dougnukem

+0

@Dougnukem - tuyệt vời. Tôi sẽ upvote câu hỏi của bạn một lần nữa, nếu tôi có thể, để làm cho các nỗ lực để đóng góp thông tin phản hồi trở lại dự án để cải thiện nó. Tôi upvoted một trong những câu hỏi khác của bạn để thay thế :-) –

Các vấn đề liên quan