2012-11-27 15 views
28

uygulama motorunda JDO 2.3 kullanıyorum yazmaz. Yerel test için Master/Slave veri deposunu kullanıyordum ve yakın zamanda yerel testler için HRD veri deposunu kullanmaya geçtim ve uygulamamın bazı bölümleri kırılıyor (bu da beklenen). Çarpışan uygulamanın bir kısmı, hızlıca çok sayıda yazının gönderildiği yerdir - bunun nedeni 1 saniyelik sınırlama nedeniyle, eşzamanlı bir değişiklik istisnasıyla başarısız oluyor.Gönderilen JDO, yerel GAE HRD veya muhtemelen yeniden kullanılan işlem

Tamam, bu da beklenen bir durumdur, dolayısıyla tarayıcı başarısız olduklarında daha sonra tekrar yazmayı tekrar deneyebilirim (belki de en iyi kesmek değil, sadece çabucak çalışıyorum).

Ama garip bir şey oluyor. Başarılı olması gereken bazı yazımlar (eşzamanlı modifikasyon istisnasını DON'NUYOR), taahhüt aşaması tamamlansa ve istek benim başarı kodumu döndürse de başarısız oluyor. Günlüğünden, yeniden denenen isteklerin düzgün çalıştığını görebiliyorum, ancak ilk denemede işlenmiş görünen diğer talepler, asla "uygulanmadı". Ama başvuru aşaması ile ilgili okuduklarımdan, aynı varlığa tekrar yazmak, başvuruyu zorlamalıdır ... ama değil.

Kod izler. Dikkat Edilmesi Gereken Noktalar:

  1. automatic JDO caching'u kullanmaya çalışıyorum. Bu yüzden JDO, kapakların altında memcache kullanıyor. Bu, aslında her şeyi bir işlemde sarmadan çalışmaz.
  2. Tüm istekleri yapmak, bir varlığın bir dizesini okumak, dizenin bir kısmını değiştirmek ve bu dizeyi varlığa geri kaydetmek. Bu istekler işlemlerde değilse, elbette "kirli okuma" problemine sahip olacaksınız. Ancak işlemlerde, izolasyonun "serileştirilebilir" seviyesinde olması gerekiyordu, bu yüzden burada neler olduğunu göremiyorum.

    PersistenceManager pm = PMF.getManager(); 
    Transaction tx = pm.currentTransaction(); 
    String responsetext = ""; 
    try { 
        tx.begin(); 
        // I have extra calls to "makePersistent" because I found that relying 
        // on pm.close didn't always write the objects to cache, maybe that 
        // was only a DataNucleus 1.x issue though 
        Key userkey = obtainUserKeyFromCookie(); 
        User u = pm.getObjectById(User.class, userkey); 
        pm.makePersistent(u); // to make sure it gets cached for next time 
        Key mapkey = obtainMapKeyFromQueryString(); 
        // this is NOT a java.util.Map, just FYI 
        Map currentmap = pm.getObjectById(Map.class, mapkey); 
        Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity 
        Text newMapData = parseModifyAndReturn(mapData); // transform the map 
        currentmap.setMapData(newMapData); // mutate the Map object 
        pm.makePersistent(currentmap); // make sure to persist so there is a cache hit 
        tx.commit(); 
        responsetext = "OK"; 
    } catch (JDOCanRetryException jdoe) { 
        // log jdoe 
        responsetext = "RETRY"; 
    } catch (Exception e) { 
        // log e 
        responsetext = "ERROR"; 
    } finally { 
        if (tx.isActive()) { 
         tx.rollback(); 
        } 
        pm.close(); 
    } 
    resp.getWriter().println(responsetext); 
    
    :
  3. varlık değiştirilen ben çapraz grup işlemleri

ilgili kod (bu basitleştirilmiş versiyonu olan) sağladı (bir grupta) bir kök varlık

  • olduğunu

    UPDATE: Bunun neden olduğunu bildiğime gayet eminim, ancak yine de bunu onaylayabilecek herkese ödül vereceğim.

    Temel olarak, sorunun, işlemlerin yerel veri tabanında gerçekte uygulanmadığı yönündedir. Kaynaklar:

    işlemler uygulanmadı Çünkü

    https://groups.google.com/forum/?fromgroups=#!topic/google-appengine-java/gVMS1dFSpcU https://groups.google.com/forum/?fromgroups=#!topic/google-appengine-java/deGasFdIO-M https://groups.google.com/forum/?hl=en&fromgroups=#!msg/google-appengine-java/4YuNb6TVD6I/gSttMmHYwo0J

    , geri alma esasen no-operasyon. Bu nedenle, iki işlem aynı anda kaydı değiştirmeye çalışırken kirli bir okuma alıyorum. Başka bir deyişle, A verileri okur ve B aynı zamanda verileri okur. Verileri değiştirmeye yönelik girişimler ve B, verilerin farklı bir bölümünü değiştirmeye çalışır. Bir detastore yazıyor, sonra B yazıyor, A'nın değişikliklerini yok ediyor. Ardından B, uygulama motoru tarafından "geri alınır", ancak geri bildirimler yerel veri deposunda çalışırken no-op olduğundan, B değişiklikleri değişmez ve A olmaz. Bu arada, B istisnayı attıran iş parçacığı olduğu için, istemci B'yi yeniden dener, ancak A'yı yeniden denemez (çünkü A, başarılı bir işlemdi).

  • +0

    Eğer datastore yeniden tasarlama düşündünüz mü yerli yolu öğrenmeye değer olduğunu ve çok kez saniyede birden aynı varlık grubuna devam eden önlemek için, nasıl kullanacağımız? Alternatif olarak, datastore için sıralanan görevlere devam etmeyi ve 1/s taraf grubunun yazma frekans sınırına uymaya yönelik düzenlemeleri yapmayı denediniz mi? –

    +0

    Bunu düşündüm. Ama bunu yapmadan önce, bu özel hatanın neden olduğunu anlamak isterim ... endişem, temel olarak İKG veya uygulama motoru/jdo işlemleri veya bir şey hakkında bir şey anlamadığım veya bir şeyi özlediğim dokümantasyon ve ben şimdiki eklenti kullanarak, – eeeeaaii

    +0

    FWIW (veri deposu erişimler bir işlemde değilse çalışmaz JDO önbelleğe) için işlemleri eklemem gerekiyor en az 25 diğer hizmetler var çünkü (daha sonra Gae beni ısıracak JDO v2.x), L2 önbelleğinin çalışması için bir işlemde bulunma gerekliliğini görmüyorum; eğer bir nesne okunduğunda L2 önbelleğe alınmışsa ve rapor edilmemişse (eski eklenti desteklenmiyorsa, o zaman sadece güncel bir durum söz konusuysa). – DataNucleus

    cevap

    1

    Belki sizin için kötü haber, JDO'yu bıraktım ve Objectify'ı kullanıyorum ve bazı yerlerde doğrudan datanucleus'u kullanıyorum.Bir performans ve tasarım daha iyi bir seçim olan (uzun vadede düşünürseniz) kalıcılığım üzerinde mükemmel bir kontrole sahibim. Eğer standart JPA ne de hatta somutlaştırabilir olmayan şeyler yapabilirsiniz yerli DataNucleus API kullanarak

    : db no-sql Çünkü

    , JPA, JDO ve standart varsayımlara karşı yapısal değişiklikler vardır örnek Ben işlem GAE bulunmaz dinamik

    sütunları yaratmaktı kullanılan, bazen bir işlem (varlık grupları) benzeyebilir şey var. Bu yüzden yerli API'yi kullanmanız, bu türden etkili bir jimnastik yapmamanızı engelleyecektir.

    işe yarayabilir bir joystick ile bir araba çalışılıyor, ancak öğrenmek için mutlaka yeni şeyler vardır. Bence o

    +1

    Zied haklı. Google'ın JPA ve JDO soyutlama katmanlarını sağladığı çok ilginç olsa da, kendileriyle çok iyi giden bir proje görmedim. Genelde insanların, veri deposunu bir RDBMS olarak düşünmeye devam etmelerinden dolayı, genellikle her türlü kötü hackle sonuçlanır. İnsanlara JPA veya JDO kitaplıklarını kullanmamalarını ve ham Google API'sini veya Objectify'ı kullanmasını şiddetle öneririm. –