Hello

SpringBoot-ShedLock DuplicateKeyException이슈?? 본문

spring

SpringBoot-ShedLock DuplicateKeyException이슈??

nari0_0 2023. 9. 14. 16:29
728x90

예전에 다중 서버 환경 스케쥴 처리 시 spring schedule를 사용해 중복실행되지 않도록 처리했습니다.

오늘 schedule에서 SQLException이 발생해 확인 요청을 받아 서버에 파일로그를 확인했는데 에러가 없어

try{}catch()문으로 포장해 에러를 남기도록 했는데도 따로 에러 로그는 확인되지 않았습니다.

 

Azure Insight 에서 확인된 에러라 Insight를 보니 아래 이미지 정보를 제공했습니다.

1 ) 아래 이미지에서 응답을 보면 200으로 호출이 성공한 것을 알 수 있습니다.

2 ) 실행 요청 내에서 일어나는 db 호출에 대한 로깅을 다 남겨주는 것을 알 수 있습니다.

3 ) 첫번째 db 호출이 EXCEPTION이 빨간색으로 표시되어 이슈가 있음을 알 수 있습니다.

 -- 오른쪽에 Exception을 보면 Duplicate entry 'shedlock_key_name' ~~ 내용이 작성된것을 보아 키 중복 에러임을 알 수 있습니다.

4 ) 아래 나머지 db 호출은 문제없이 처리 된 것을 확인 할 수 있습니다.

 

정리하면, 서버 최초 실행 시 shedlock이 키 관리 테이블에 해당 키가 있는지 seledt after insert or update를 처리하는것이 아닌, insert 실행 후 exception으로 key 유무를 판단하고 있기 때문에 발생한 이슈입니다.

shedlock 호출 살펴보기

StorageBasedLockProvider.doLock

StorageBasedLockProvider.doLock

1) lock key 생성되어있는지 확인

 - LockRecordRegistry에서 lock key 관리한다.

 - 어플리케이션 실행 시에는 빈 set이다.

2) 키를 찾을 수 없다면, 조건에 만족하여 if 절 내부의 코드들이 실행이 됩니다.

3) 키가 없기 때문에 insertRecord를 호출해 db에 등록하려고한다.

3-1)  sql 쿼리를 실행한다.

3-2) 성공적으로 insert 되면 true를 Exception이 발생한다면 false를 리턴한다.

JdbcTemplateStorageAccessor.insertRecord

4) LockRecordRegistry에 key를 추가한다.

5) key update 한다.

 

JdbcTemplateStorageAccessor.insertRecord 메소드를 보면 DuplicateKeyException 발생 시 false를 리턴합니다.
Azure Insight가 친절하게 쿼리당 로깅을 하고있어 이슈가 발생한 것 처럼 보여 확인 요청이 온 것 같습니다.
추가로 key update하는 메소드를 확인해보니, sql 쿼리 실행 후 성공하면 true를 업데이트 충돌로 트랜잭션을 완료하지 못한 경우 false를 리턴합니다.

shedlock git에 "한 노드에서 하나의 작업이 이미 실행 중인 경우 다른 노드에서의 실행은 기다리지 않고 단순히 건너뛴다" 라고 설명이 적혀있는데 오늘 디버깅하며 알게 되었 키를 선점해서 동작을 제어하는 것을 확실히 알게되었다. (처음 shedlock를 시스템에 도입할 때는 알고있었을 것이다....)

 

처음 공유된 에러는 어플리케이션 실행 시 무조건 발생하는 문제인데 조회 후 inser or update 하도록 처리되도록 변경하지 않는 이유를 알아봐야 겟당.

select 하지 않는 이유 : https://github.com/lukas-krecan/ShedLock/issues/75

shedlock 개발자는 select 하는 것을 불필요하게 생각하는 것 같다. select -> insert or update 가 하고싶으면 알아서 상속해서 사용하길 권장한다.

 

참고 : https://github.com/lukas-krecan/ShedLock

728x90