多个服务器检查并写入数据库中的标志
我的环境有 4 台服务器和 2 台 Oracle 数据库服务器,它们之间有流,用于即时 2 路复制。
我有一个 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();
}
这适用于只有一台服务器的环境,但不适用于我的场景。
如果我在同步块中的两个不同服务器上有一个线程,并且它们都在检查作业没有运行之后,那么它们都会尝试设置标志。因此,我内置了应急措施,以便能够捕获唯一的键约束(每个作业都有一个 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 的交易吗?或者你能建议别的吗?
谢谢。
I have an environment with 4 servers and 2 oracle database servers which have streams between them for instant 2 way replication.
I have a servlet (I cannot control which of the 4 servers it goes to) which checks if a job is running and if not it starts the job in a thread. Only one of these jobs should be running at any time. I am placing a flag on the database to indicate that the job is running (as there are 4 servers I cannot just hold the flag in memory).
In a synchronized block I do a check to see if the job is running and if its not I set a flag. After this I start the job
synchronized (this)
{
if (statusDao.isJobRunning())
{
throw new JobRunningException("Job is already running");
}
//set flag to indicate that job is running
statusDao.setJobRunningFlag();
}
This works for an environment where there is only one server, but not in my scenario.
If I have a thread on 2 different servers in the synchronized block and they are both after checking that the job isn't running then they will both try to set the flag. So I have built in contingency to be able to catch a unique key constraint (each job has an id, which is the primary key in the database. I have this value hard coded to 1 so that only one entry can be in database). I am using 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.");
}
So again, this function correctly but I can imagine there is a better way to do this. Can you please suggest another approach? It seems to me that I need something which will lock the database (while I check if flag is running and then set flag running). Remember, there are 2 databases, so I don't know if having the lock on just one will work. Should I be looking at Spring's tranactions? Or can you suggest something else?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论