我有一个包含4个服务器和2个oracle数据库服务器的环境,它们之间有流,用于即时双向复制。
我有一个servlet(我无法控制它进入的4个服务器中的哪个),它检查作业是否正在运行,如果没有,它会在一个线程中启动作业。这些工作中只有一个应该随时运行。我在数据库上放置一个标志,表明作业正在运行(因为有4个服务器,我不能只在内存中保存标志)。
在同步块中,我检查作业是否正在运行,如果不是我设置了标志。在此之后我开始工作
synchronized (this)
{
if (statusDao.isJobRunning())
{
throw new JobRunningException("Job is already running");
}
//set flag to indicate that job is running
statusDao.setJobRunningFlag();
}
这适用于只有一台服务器的环境,但不适用于我的场景。
如果我在synchronized块中的2个不同服务器上有一个线程,并且他们都在检查作业没有运行之后,那么他们都会尝试设置标志。所以我已经构建了偶然性来捕获一个唯一的键约束(每个作业都有一个id,这是数据库中的主键。我将此值硬编码为1,这样只有一个条目可以在数据库中)。我正在使用Springs JdbcTemplate
try {
this.jobJdbcTemplate.update(insert into JOB (JOB_ID, RUNNING) values ('1','Y'));
}catch (DataAccessException dae){
if (StringUtils.contains(dae.getMessage(), "ORA-00001"))
{
throw new JobRunningException("Job is already running");
}
throw new JobException("Error setting Job Flag.");
}
再次,这个功能正确,但我可以想象有更好的方法来做到这一点。你能建议另一种方法吗?在我看来,我需要一些将锁定数据库的东西(当我检查标志是否正在运行然后设置标志运行)。请记住,有2个数据库,所以我不知道只有一个锁可以工作。我应该看看Spring的派系吗?或者你可以推荐别的东西吗?
感谢。