我有一个MDB(消息驱动bean),它接收表示单词的字符串消息。我还有一个数据库中的表。MDB应该在表中存储单词和每个单词接收到的次数(计数器)。
问题是为了获得更好的性能,MDB启动了许多实例,当不同实例接收到相同的新单词时,它们都会创建具有计数器1的相同行。
为解决此问题,我应该使单词字段唯一,然后第二个实例将在提交时失败,重新传输消息,这将起作用,但可能会有问题。这是一个好的做法吗?
另一种解决方案是以后合并这些行并总结计数器。但如果另一个实例在更新中增加计数器怎么办?
如果两个实例尝试增加计数器怎么办? @Version足够了吗?
我不确定这里的正确解决方案是什么。您如何处理这样的情况?
此外,您能否建议一些关于并发实践的书籍(不涉及使用synchronized,因为我需要支持Java EE并可能运行应用程序服务器集群)?
更新:阅读更多关于EJB和JPA的资料后,我想要的是类似锁定实体的东西。例如,我可以创建一个只有id和key列以及以下数据的新表:
所以问题是这种方法可行吗?我能否在不维护带有锁定行的DB表的情况下做同样的事情?也许有一些Java EE容器锁定机制?
如果有帮助,我正在使用JBoss 4.2。
我有一个新的想法。我可以创建两个MDB:
第一个MDB允许多个实例,将处理所有消息,如果找不到单词,将发送单词给第二个MDB
第二个MDB只允许一个实例,将按顺序处理消息并允许创建新单词
最好的部分:没有整个表/方法/进程锁定,只有计数器更新时的行锁定
那太棒了!
谢谢。
问题是为了获得更好的性能,MDB启动了许多实例,当不同实例接收到相同的新单词时,它们都会创建具有计数器1的相同行。
为解决此问题,我应该使单词字段唯一,然后第二个实例将在提交时失败,重新传输消息,这将起作用,但可能会有问题。这是一个好的做法吗?
另一种解决方案是以后合并这些行并总结计数器。但如果另一个实例在更新中增加计数器怎么办?
如果两个实例尝试增加计数器怎么办? @Version足够了吗?
我不确定这里的正确解决方案是什么。您如何处理这样的情况?
此外,您能否建议一些关于并发实践的书籍(不涉及使用synchronized,因为我需要支持Java EE并可能运行应用程序服务器集群)?
更新:阅读更多关于EJB和JPA的资料后,我想要的是类似锁定实体的东西。例如,我可以创建一个只有id和key列以及以下数据的新表:
ID | KEY
1 | WORDS_CREATE_LOCK
这样当我需要处理一个新单词时,我会做类似于这样的事情(不是准确的代码,不确定它是否能编译):
// MAIN FUNCTION
public void handleWord(String wordStr) {
Word w = getWord(wordStr);
if (w == null)
w = getNewOrSychronizedWord(wordStr);
em.lock(w);
w.setCounter(w.getCounter() + 1);
em.unlock(w);
}
// Returns Word instance or null if not found
private Word getWord(String wordStr) {
Word w = null;
Query query = em.createQuery("select w from words as w where w.string = :wordStr order by w.id asc");
query.setParameter("wordStr", wordStr);
List<Word> words = query.getResultList();
if (words.getSize() > 0)
w = words.get(0);
return w;
}
// Handles locking to prevent duplicate word creation
private Word getNewOrSynchronizedWord(String wordStr) {
Word w = null;
Locks l = em.find(WORDS_CREATE_LOCK_ID, Locks.class);
em.lock(l);
Word w = getWord(wordStr);
if (w == null) {
w = new Word(wordStr);
em.persist(w);
}
em.unlock(l);
return w;
}
所以问题是这种方法可行吗?我能否在不维护带有锁定行的DB表的情况下做同样的事情?也许有一些Java EE容器锁定机制?
如果有帮助,我正在使用JBoss 4.2。
我有一个新的想法。我可以创建两个MDB:
第一个MDB允许多个实例,将处理所有消息,如果找不到单词,将发送单词给第二个MDB
第二个MDB只允许一个实例,将按顺序处理消息并允许创建新单词
最好的部分:没有整个表/方法/进程锁定,只有计数器更新时的行锁定
那太棒了!
谢谢。