【问题标题】:How to ensure consistency with concurrent requests on Appengine entities with objectify?如何使用 objectify 确保与 Appengine 实体上的并发请求的一致性?
【发布时间】:2014-09-23 04:56:40
【问题描述】:

在我的应用程序中,并发写入发生在单个实体上,我注意到当超过 3 次/秒的写入发生时,并非所有请求都被持久化。 我正在从事务内部发出请求,但我也没有看到并发修改异常,我正在使用 Objectify,因此未抛出的异常可能是一个对象化的事情。 我知道对于并发写入,我需要实现分片计数器,但即使在那里,我也想绝对确定如果写入被删除,我会被告知。 在 objectify 中是否有 @version 的等价物,或者有没有办法在我的 objectify 实现中使用 JPA/JDO 中的 @version 机制? 继承我的实体的代码:

            while (true) {

                try {
                    ofy().transact(new VoidWork() {
                        public void vrun() {
                            Venue_Model tnxVenue = ofy().load()
                                    .type(Venue_Model.class).id(tnxVenueID)
                                    .now();
                            tnxVenue.doStuff();

                            ofy().save().entities(tnxVenue).now();
                        }
                    });
                    //There are cases where this part of the code is reached but updates to the entity are not reflected in the data store viewer.
                    break;
                } catch (ConcurrentModificationException e) {
                    // TODO Auto-generated catch block
                    if (retries == 0) {
                        e.printStackTrace();

                                + person_ref.getKey() + e.toString());
                        break;
                    }
                    retries--;


                } catch (Exception e) {

                }
            }
        }

要检查实体是否已持久化,我只需查看 appengine 仪表板上的数据存储查看器即可。

对于持久存在场所的每个请求,我还尝试检索 n 检查实体是否已持久存在,并且奇怪的是,在代码运行期间它会正确返回 - 数据存储查看器却讲述了不同的故事:/ 检查数据是否正确持久化的代码。

               venue = ofy().load().type(Venue_Model.class).id(venue_id).now(); // search if person has checked in
                if (!venue.allCheckins.contains(person_ref)) {
                    log.warning("attempt " + i + " for"
                            + person_ref.getKey());   // Never entered :/
                    venue.doStuff(person_ref, subVenueName);
                    ofy().save().entities(venue).now();
                } 

【问题讨论】:

  • 你能分享你当前的代码,包括你测试请求被持久化的方式吗?

标签: java google-app-engine concurrency objectify


【解决方案1】:

您的代码实际上并未在事务中执行任何数据存储操作。阅读有关交易的 Objectify 文档:

https://code.google.com/p/objectify-appengine/wiki/Transactions

【讨论】:

  • 是的...注意到几个小时前将原生 appengine 交易与交易的对象化实现混淆(上面更新了代码)--- 但是问题仍然存在。
  • 更新了代码以将“读取”放入事务中-不再看到无法解释的不一致-我的逻辑错误:/。然而,我现在使用上面的代码看到“IllegalArgumentException:对太多实体组进行操作”,即使我只是在事务中修改单个实体——“Venue_MOdel”是一个 java 类,并且 objectify 可能将它存储为幕后的多个实体? ...如果我找不到解决方案,我会为此打开一个单独的线程。
  • Objectify 不会对幕后的实体做任何复杂的事情。如果你得到了太多的实体,也许你正在使用 @Load Refs 拉入其他实体?
  • 此外,除非您指定重试限制,否则 Objectify.transact() 不会抛出 ConcurrentModificationException。默认情况下,transact() 会重试直到请求过期。
  • 是的,我正在使用 @Load 加载,这导致所有异常都被抛出。谢谢你:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 2015-06-20
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多