【发布时间】:2015-02-13 14:47:43
【问题描述】:
我们的应用突然获得了大量流量,并且系统存在一些设计缺陷(或者更确切地说,我们从未想过它会获得如此多的流量,所以我们只是选择跳过它)。
正如主题所述,我正在寻找一种防止错误的方法:org.datanucleus.exceptions.NucleusDataStoreException: Concurrent Modification
目前我有一个名为 Group 的实体,看起来像这样:
@PersistenceCapable
public class Group extends PersistableString {
private static final long serialVersionUID = 6215353466976945628L;
@Persistent
private int yesCount;
@Persistent
private int noCount;
public void increaseYesCount()
{
yesCount++;
}
public void increaseNoCount()
{
noCount++;
}
}
以下代码是实体的更新是如何完成的:
int answer = Integer.parseInt(req.getParameter("answer"))
try {
PersistenceManager pm = PMF.getPersistenceManager();
for(String groupId : allGroupsToBeUpdated)
{
Group group = pm.getObjectById(Group.class, groupId);
if(answer == 0)
group.increaseNoCount();
else
group.increaseYesCount();
}
pm.close();
} catch (Exception e) {
e.printStackTrace();
}
allGroupsToBeUpdated 是一个包含大约 30 个字符串 ID 的列表。有什么方法可以避免Concurrent Modification-error 吗?我可以检查我检索的实体是否正在更新,然后丢弃(/忽略)更新?写入实际上是否成功并不重要,我只是想确保我没有收到错误(或者它一直试图成功写入),因为它导致请求需要 10-30 秒。
我是否应该在每次更新之间打开(获取新的PM-instance)并关闭连接(pm.close()),而不是等待所有 30 次更新完成?
我知道分片计数器并且应该(显然)使用它们,但现在我正在寻找解决这个问题的“快速解决方案”。
编辑: 我正在使用:
App Engine SDK 1.8.9
JDO 3.0
可以在以下位置找到 Stacktrace: http://pastebin.com/TWnmkpPU
【问题讨论】:
-
由于你不发布堆栈跟踪,软件版本,它不可能说什么。
-
抱歉,我认为这无关紧要。问题是(至少我认为是)这个请求在多个服务器实例和想要更新的同一个组上运行,从而导致错误。我将使用 App 引擎版本和可能的堆栈跟踪更新帖子。
-
因此并发修改异常是由 Google 的数据库和/或处理代码引发的(即与 JDO 本身无关)。也许升级正在使用的库版本(例如,JDO v2 是古老的),也许在你的代码中使用事务
-
对不起,我的错!我正在使用 JDO v3。 “通过选择Datanucleus JDO/JPA v2切换到JDO 3.0”,这是我看到和写的数字,但实际上是JDO 3.0。是的,也许升级 App Engine SDK 会有所作为,但我怀疑这就是问题所在。当服务器上传时,我认为它在幕后使用了最新的“引擎”。
标签: java google-app-engine jdo