티스토리 뷰

 서비스 오픈을 위해 개발에 힘쓰던 중 동시성 문제를 해결해야할 상황이 왔다.

 개발중인 서비스는 가계부인데, 거래가 입력되거나 수정되거나 삭제될 때마다 금액에 대한 업데이트를 정확하게 해줘야할 필요가 있었다. 그러나 고려해야 할 사항은 아래 두 가지가 있었다.

첫번째, 서버의 스케일 아웃을 고려해야 한다.
두번째, 서버 개발에는 최소의 비용이 들어야 한다.

 첫번째 사항인 서버의 스케일 아웃을 고려하면 당연히 소스코드 내에서 처리하는 것은 불가능했고, 비관적 락, 낙관적 락, Named Lock, 혹은 분산 시스템을 사용하여 락을 구현하는 방법 등 여러 가지 방법이 있었는데 내가 선택한 방법은 Named Lock이었다.


 비관적 락의 경우, 실제로 로우나 테이블 단위로 데이터에 락을 거는 방법인데, 충돌이 빈번하게 일어날 경우 낙관적 락보다 성능이 좋은 방법이다. 그렇지만 성능 감소가 있을 수 있다는 단점이 있다.

 낙관적 락의 경우, 실제로 락을 걸지 않지만 버전을 비교해서 맞으면 수행하고 안 맞으면 다시 데이터를 읽는다. 별도의 락을 잡지 않아 비관적 락에 비해 성능상 이점은 있지만 동작 실패시 재시도 로직을 개발자가 직접 작성해야 한다는 단점이 있다.

 네임드 락의 경우, 이름을 가진 메타데이터 락으로 트랜잭션 종료시 락이 자동으로 해제되지 않기 때문에 해제를 수행해주거나 선점시간이 끝나야 락이 해제된다.


 내가 현재 참여하고 있는 서비스는 한 계정으로 동시에 여러 기기에서 이용이 가능하다. 그렇기 때문에 여러 기기에서 같은 계정으로 같은 계정과목으로 거래를 동시에 발생시키면 동시성 문제가 발생한다.

 우선 이런 상황이 그렇게 자주 발생하지 않을 것이라고 생각했고, 발생하더라도 트랜잭션이 커밋될 때까지 락을 유지하기 때문에 자원 낭비가 발생할 수 있다고 생각해서 비관적 락은 제외했다.

 그 다음으로 낙관적 락을 고려해볼 수 있었는데, 우선 낙관적 락의 경우 동작 실패시 재시도 로직을 직접 작성해야 하는데 이 로직에 대한 부담이 있었다. 점점 재시도하는 케이스가 늘어날 수 있다는 딜레마에 빠졌던 것.

 네임드 락은 내가 원하는대로 락을 세분화하여 유연하게 관리할 수 있다는 장점이 있었다. 실제로 거래가 계층구조를 가지고 요청되는 경우가 있는데, 이럴 때는 각 거래가 동일한 계정과목을 가지고 있을 수도 있는데, 이럴 때 같은 계정과목이라면 굳이 락을 걸지 않아도 되는 상황이었는데 이럴 때 편리했다.

 마지막으로 Redis나 Zookeeper 등을 사용하여 분산 락을 잡는 방법도 있는데, 이 방법은 두번째 사항(서버 개발에는 최소의 비용이 들어야 한다)때문에 제외했다. Redis를 사용할 줄 모르는 것은 아니고, 동시성 문제를 Redis로 해결해본 경험도 있지만, 현재 프로젝트 규모를 생각했을 때 Redis를 붙이는 것이 오히려 더 큰 부담이 될 것 같았다. 그리고 Redis로 처리해놓는다 해도 인프라 구축 비용과 유지보수 비용을 고려하지 않을 수 없다.

 그래서 나는 Named Lock으로 문제를 해결했다. 실제 제이미터로 테스트를 했을 때 문제없이 계정과목의 금액이 잘 업데이트되는 것을 확인할 수 있었다.


 사실 서버를 개발하면서 늘 고려하고 어떻게 해결할지 고민했던 부분이라 미리 강의를 들었었다. (인프런의 재고시스템으로 알아보는 동시성 이슈 강의) 미리 공부를 해놓길 잘했다고 늘 생각한다.

재고시스템으로 알아보는 동시성이슈

300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함