私は、4 台のサーバーと 2 台の Oracle データベース サーバーを備えた環境を持っており、それらの間にストリームがあり、双方向のインスタント レプリケーションが可能です。
ジョブが実行されているかどうかをチェックし、そうでない場合はスレッドでジョブを開始するサーブレットがあります (4 つのサーバーのどれに行くかを制御できません)。これらのジョブのうち、一度に実行できるのは 1 つのみです。ジョブが実行中であることを示すフラグをデータベースに設定しています (サーバーが 4 つあるため、フラグをメモリに保持することはできません)。
同期ブロックでは、ジョブが実行されているかどうかを確認し、実行されていない場合はフラグを設定します。この後、私は仕事を始めます
synchronized (this)
{
if (statusDao.isJobRunning())
{
throw new JobRunningException("Job is already running");
}
//set flag to indicate that job is running
statusDao.setJobRunningFlag();
}
これは、サーバーが 1 つしかない環境では機能しますが、私のシナリオでは機能しません。
同期ブロック内の 2 つの異なるサーバーにスレッドがあり、両方ともジョブが実行されていないことを確認した後である場合、両方ともフラグを設定しようとします。そのため、一意のキー制約をキャッチできるように不測の事態を組み込みました (各ジョブには、データベースの主キーである ID があります。この値を 1 にハードコードして、データベースに 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 つのデータベースがあることを思い出してください。1 つだけをロックしても機能するかどうかはわかりません。Spring のトランザクションを確認する必要がありますか? それとも何か他のことを提案できますか?
ありがとう。