반응형
약간 올드한 방식이지만 디비로 분산락을 구현한 사례가 있어서 정리한다.
락을 거는 테이블이 있어야 하고, 락을 거는 역할을 하는 서비스가 있어야 한다
public void runSynchronousTask(TaskKey taskKey, Runnable task) {
startSynchronousTask(taskKey); //디비에 키 저장
try {
task.run(); //비즈니스 로직 실행
} finally {
endSynchronousTask(taskKey); //디비에 키 삭제
}
}
private void startSynchronousTask(TaskKey taskKey) {
try {
insertTaskKey(taskKey);
} catch (Exception e) {
if (selectTaskKeyCount(taskKey) > ZERO) {
throw BadukTaskException.FAIL_START_SYNCHRONOUS_TASK;
}
if (updateTaskKey(taskKey) != SUCCESS) {
throw BadukTaskException.FAIL_START_SYNCHRONOUS_TASK;
}
}
}
private void endSynchronousTask(TaskKey taskKey) {
try {
deleteTaskKey(taskKey);
} catch (Exception e) {
deleteTaskKey(taskKey);
}
}
사용처에서 아래와 같이 사용하면 된다. (자바6기준..)
public ApiResponse giveEventMoney(final EventMoneyApiRequest eventMoneyApiRequest) {
runSynchronousTask(
generateLockKey(), // lock key
new Runnable() {
@Override
public void run() {
int resultCode = giveMoney();
if (resultCode != SUCCESS_CODE) {
throw new ApiException(ApiErrorCode.FAIL_MONEY_PAYMENT);
}
}
});
return ApiResponse.OK();
}
1. DB 자체 락 구현
DB를 사용해 특정 키를 기반으로 락을 관리하고 동시 실행을 방지하는 방식.
장점
- 데이터와 락 관리의 일원화:
- 락이 저장되는 위치와 애플리케이션 데이터가 동일한 데이터베이스에 존재하므로 별도의 외부 시스템 없이 처리 가능.
- DB 트랜잭션과 자연스럽게 통합되어 데이터 일관성을 유지하기 쉬움.
- 분산 환경 지원:
- 여러 인스턴스에서 동일한 DB를 바라보므로 클러스터 환경에서도 동기화를 보장.
- 의존성 최소화:
- 별도의 락 관리 시스템(Redis, ZooKeeper 등)을 도입할 필요 없이 DB만으로 해결 가능.
단점
- 성능/확장성 제한:
- 락 관리(INSERT/DELETE)를 위해 DB I/O가 발생하므로 빈번한 락 작업이 성능에 영향을 줄 수 있음.
- 대량 트래픽 시 DB 부하를 초래할 가능성.
- 잠금 해제 누락 위험:
- 애플리케이션 장애 또는 네트워크 문제로 인해 finally 블록이 실행되지 않으면 락이 DB에 남아 다른 프로세스가 진행되지 못할 수 있음.
- 락의 유효 시간 관리 필요:
- 만약 비즈니스 로직이 예상보다 오래 걸리거나 문제가 발생해 락이 해제되지 않으면, 추가적인 재처리 로직이 필요함.
2. 디비 네임드 락
장점
- 성능:
- 데이터베이스 내부에서 처리되므로 빠르고 효율적.
- 자동 해제:
- 세션 종료 시 락이 자동으로 해제되므로, 애플리케이션 장애로 락이 남아있는 문제를 방지.
- 간단한 사용:
- 복잡한 로직 없이 락 획득/해제를 호출만으로 구현 가능.
- 분산 환경 지원:
- 동일한 데이터베이스를 사용하는 여러 애플리케이션 인스턴스 간의 락 동기화 가능.
단점
- 트랜잭션 제약:
- 네임드 락은 일반적으로 트랜잭션 경계와는 독립적으로 동작하므로, 데이터와 락의 일관성을 따로 관리해야 함.
- 락 관리 제한:
- 락의 TTL이나 재시도 로직 등을 세밀하게 제어하기 어려움.
- 데드락 위험:
- 잘못된 사용으로 인해 데드락 발생 가능.
추가적인 내용 참고
728x90
반응형
'개발 > java' 카테고리의 다른 글
[병렬처리] Folkjoinpool & executorService (0) | 2024.11.26 |
---|---|
[동기화] 뮤텍스/세마포어 (0) | 2024.11.24 |
[test] org.mockito.exceptions.misusing.PotentialStubbingProblem (1) | 2024.11.15 |
자바와 스프링에서 thread pool (0) | 2024.11.11 |
[test] object mother (2) | 2024.09.26 |