-
싱글턴 문제점과 해결책개발/java 2024. 9. 2. 11:55
자바의 경우 싱글턴 패턴으로 이루어져 있다
예를 들어 동일 서비스를 10번 호출을 하게 되면 10번을 새로운 서비스로 인지해서 비효율적이니 1번의 호출만 새로운 서비스로 인식하고 나머지 9번을 1번을 호출된 서비스를 받아 처리하는 구조이다.
이 경우 상태를 체크하는 부분에서 문제가 발생할 수 있다.
예를 들어 멀티스레드로 구성된 경우 주문을 접수를 하는 고객이 여러번 주문생성이 가능한 구조라면 여러가지 상태 체크를 무시하는 경우가 발생할 수 있다.
이를 방지하는 경우는 여러가지가 있으나 그중 DB를 통해 resource lock을 걸어 제어하는 방법이 있다.
방식
1. 서비스 시작 시 특정 키를 통해 db를 insert 한다
2.서비스 수행 도중 해당 키를 통해 유입된 경우 유입을 대기 한다
3.서비스가 종료 되면 특징 키로 유입된 db를 컬럼을 delete한다
4.대기 된 서비스의 경우 재 수행을 진행한다.
고객이 주문 후 상품을 다른 상품으로 변경하려고 할때 판매자는 이미 배송을 완료 하려고 한다고 가정을 해보자
이 경우 둘의 시점으로 인해 배송이 완료가 됐지만 상품이 데이터 상 변경이 될 수 있다.
해당 둘의 시점을 일치 시키기 위해 데이터에 락을 걸어 둘의 유입의 우선순위를 정해야한다.
고객이 먼저 변경을 하려고 하면 배송 완료를 안되게 하거나 배송완료가 되면 고객이 변경이 안되게 하게 해야하는 것이다.
키를 주문번호로 둔다고 해보자
아래와 같이 changeOption을 수행할때 createKey 생성 , standByKey를 통해 작업 수행 여부 확인 , deleteLockKey를 통해 작업완료 이후 key 삭제를 하게 되면 작업은 하나의 key로 묶이게 되며 이를 통해 싱글턴 문제를 해소할 수 있다.
public void ChangeOption(String odNo){ //옵션 변경 시 ResourceLock을 execute() 수행에 옵션 변경을 넘기는 방식이다 return ResourceLock.on(odNo, 0L).execute(() -> { return orderInfo.changeOption(odNo); }); } public <T> T execute(final Supplier<T> supplier) { try { //odNoㄹ createKey(odNo); standByKey(odNo); return supplier.get(); } finally { deleteLockKey(this); } } } public void createKey(String odNo){ if(resourceLock.readKey() == null){ resourceLock.insertKey(); } } public void standByKey(String odNo){ if(resourceLock.readKey() != null){ while(waitingTime<=0){ } if(waitingTime <=0){ throw Exception("재시도 대기 시간이 지났지만 다른곳에서 아직 작업 중임") } } } public void deleteLockKey(String key){ //해당 key를 delete 함 resourceLock.delete(key) }
'개발 > java' 카테고리의 다른 글
java stream Util 만들기 (2) 2024.09.04 mybatis로 jpa 흉내내기 (3) 2024.09.03 api retry하기 (0) 2024.08.28 Exception 분리 (0) 2024.08.19 RESTAPI 이력감지 (0) 2024.08.19