多个服务器检查并写入数据库中的标志

发布于 2024-08-21 07:11:59 字数 1186 浏览 6 评论 0原文

我的环境有 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文