У нас возникла тупиковая ситуация, которая возникла из-за большой нагрузки на микросервис (например, A), вызвавшей несколько запросов от разных клиентских служб (B, C). Таким образом, эти вызовы из B и C приходят для одного и того же clientId (ключа) и обслуживаются разными экземплярами A, и они пытаются обновить одни и те же данные clientId в базе данных в одно и то же время, вызывая ошибку ниже.
CannotAcquireLockException is thrown,
(SQL Error: 60, SQLState: 61000..
ORA-00060: deadlock detected while waiting for resource
Мы решили реализовать разбиение на уровне балансировщика нагрузки (haproxy), которое будет гарантировать, что один и тот же экземпляр A всегда будет обслуживать запросы от B и C для определенного ключа c (clientId), поэтому у нас нет нескольких экземпляров обработка запроса на тот же ключ (clientId).
Теперь мы входим в режим всего в одном jvm, так как мы убедились, что запросы от B и C для определенного c clientId всегда приходят к одному и тому же экземпляру A.
При этом все еще возможно, что запросы от служб B и C приходят для одного и того же clientId с разницей во времени наносекунд. Любые несколько потоков будут снова пытаться обновить одни и те же данные clientId в базе данных одновременно, снова вызывая ту же ошибку.
Чтобы улучшить это, мы ищем возможные решения, и одним из решений является ReentrantReadWriteLock, который должен позаботиться об этом на основе по понятиям.
Мы используем данные весны jpa и выполняем сохранение, которое выглядит как
clientJpaRepository.save(ClientObject);
Теперь можно использовать что-то вроде ниже.
public void save(Client clientObject) {
String clientId = clientObject.getClientId();
try {
boolean isLockAcquired = writeLock.tryLock(100, TimeUnit.MILLISECONDS);
if (isLockAcquired) {
clientJpaRepository.save(clientObject);
}
} catch (InterruptedException e) {
log.error("exception occured trying to acquire lock for clientId={}", clientId);
} finally {
writeLock.unlock();
}
}
Я не очень уверен, как это будет иметь дело с ключами. Как и в я не хочу, чтобы какие-либо потоки блокировать, если они хотят обновить для другого ключа (clientId 2). Кроме того, еще одна вещь, на которую следует обратить внимание, - это может быть чтение, как часть других вызовов API для этих данных из базы данных. Надеюсь, они не будут ждать слишком долго, и я надеюсь, что мне не нужно вносить какие-либо изменения для чтения. Извините за длинный вопрос, надеюсь, я скоро услышу от кого-то. Благодаря.