동시성 이슈 해결하기(낙관적락 적용)

kimseungki·2023년 4월 5일
1
post-thumbnail

계기

IT-Hermes 프로젝트 진행 과정에서, 게시글을 클릭할 경우, IP를 확인하여 방문한 이력이 없을 경우
조회수를 카운팅하는 API가 있습니다. 하지만, 방문 이력이 없는 2개의 PC에서 동시에 접속을 할 경우
+2가 아닌 +1로 카운팅이 되는 이슈가 있었습니다.

구조

아래의 그림은 여러 API를 실행하는 트래픽이 있는 상태에서 발생하는 상황입니다.

문제상황

그림에서 본것과 같이 2가지의 문제가 있습니다. 문제는 다음과 같습니다.

조회 수 카운팅 시, 데이터 정합성 문제 발생

조회수를 가져온 테이블을 Youtube라고 가정하고, 트랜잭션 A와 B가 데이터가 테이블 Youtube에 접근한다고 가정할 때, 1,2번 실행 상황에서 Youtube 테이블은 A와 B 트랜잭션 모두에게 동일한 데이터를 줄 수 밖에 없게 됩니다. 그러면 A와 B는 모두 조회수에 +1을 하더라도, 조회수는 +2로 증가하는 것이 아닌 +1로 증가하게 됩니다.

IP주소 등록 문제

가장 치명적인 이유입니다. A와 B 트랜잭션이 실행되는 상황에서 조회수가 +2가 아닌 +1이 되었음에도 IP주소는 A,B 모두 조회수를 처리한거로 등록이 된 것은 조회수 카운팅이 적용이 안된 IP주소는 다시 들어가도 카운팅이 되지 않는 이슈가 발생함은 물론, 개발자의 예상과 다른 데이터(IP주소)가 쌓이게 되는 사이드이펙트를 발생시킵니다.

동시성 이슈를 해결하기 위한 방법

가장 쉽게 생각할 수 있는 것은 DBMS 격리수준을 높이는 (Serializable) 것이지만, 이는 조회수 뿐만 아닌 다른 API에서 동시에 DB에 접근할 때 처리속도를 너무 느리게 만들기 때문에, 이 하나의 조회수 API의 이슈를 개선하기 위해 적용시키는 것은 Trade-Off가 너무 크다고 판단했습니다.
그래서 DBMS를 직접 건드리지 않고, 애플리캐이션에서 처리할 수 있는 방법을 확인했는데, JPA에서 제공하는 낙관적락, 비관적락을 확인했고, 처음엔 비관적락을 적용하여 처리하는 것에 대해서도 고민했지만, 조회수 API의 경우 이벤트와 같은 API도 아니라서, 많은 동시성 이슈가 발생하지 않을뿐더러, 마찬가지로 다른 API를 수행하는 여러 트랜잭션들에서 하나의 트랜잭션이 끝날 때까지 대기해야 되는 이슈가 있어, 이는 서비스를 운영하는 과정에서 처리속도에 영향을 크게 미칠거라 판단했습니다.
따라서 애플리캐이션에서 처리해서 상대적으로 DBMS에 직접 격리수준을 수정하는거보다는, 무겁지않고 충돌이 자주 발생을 하지 않는 상황에서 낙관적락을 적용시키는게 적합하다 판단했습니다.

낙관적 락을 통해 해결할 수 있는 것

조회수를 카운팅 할 때, 여러 트러블 슈팅 중 IP주소 등록 문제를 해결할 수 있다는 장점이 있습니다.
이유는 다음과 같습니다.

해당 부분의 경우 낙관적 락을 적용한 후, 동시성 이슈를 처리한 로직입니다.
기존의 경우 조회수가 +1만 카운팅이 되었음에도 IP주소가 2개가 등록되는 반면, 낙관적락을 적용한 이후
트랜잭션의 버전 정보가 다를경우 롤백처리가 되기 때문에, 해결할 수 있습니다.

낙관적락 적용

프로젝트에 낙관적락이 필요하다 느낀 테이블은 2개였습니다.
해당 부분에 JPA에서 제공하는 버전 어노테이션을 적용시켜 낙관적락을 적용시켰습니다.


해당 데이터와 같이 낙관적락이 잘 적용이 되었음을 확인할 수 있습니다.

낙관적락에서 고려해야 될 점

낙관적락은 동시성 이슈가 발생할 때, 결국 롤백을 시킨다는 점에서, 동시성 이슈가 자주 발생하는 경우 롤백을 위한 실행시간이 많이 나서 오히려 문제가 발생하게 됩니다. 지금과 같은 경우, 동시성으로 인한 이슈가 많이 발생할 가능성이 낮아서, 처리속도에 큰 영향을 미치지는 않았지만, 동시성 이슈가 많이 발생할 경우 비관적락을 적용시키는게 오히려 더 빠를수도 있습니다.
또한 중요한 데이터는 아니라서 낙관적락을 적용시키긴 했지만, 1번에서 발생하는 이슈 역시 결국 완벽하게 해결을 할 수가 없다는 단점이 존재합니다.
만약 결제나 아니면, 예약시스템에서 이러한 비슷한 트러블 슈팅이 발생하게 된다면, 비관적락을 적용을 하는거도 좋을거라 생각이 듭니다.

profile
seung 기술블로그

0개의 댓글