caffeine-library / Domain-Driven-Design

🌱 에릭 에반스의 '도메인 주도 설계'를 읽는 스터디
4 stars 0 forks source link

[question] 동시성 이슈를 어떤 식으로 관리하고 있나요? #21

Closed wooyounggggg closed 1 year ago

wooyounggggg commented 1 year ago

질문

p.73의 시퀀스 다이어그램을 보면서, 동시성 관리 키워드가 떠올랐는데요. 여러분의 팀이나 개인 프로젝트에서 동시성 이슈를 해결했던 방식이 있으면 같이 공유해보면 좋을 것 같습니다.

연관 챕터

없음

kth990303 commented 1 year ago

경험이 비교적 적지만 경험해봤던 방식을 적어볼게요

  1. 낙관적 락을 이용한 동시성 이슈 해결 (https://kth990303.tistory.com/390) 1-1. 단, 낙관적 락을 사용했을 때 데드락이 발생할 경우 비관적 락 고려 (성능 저하 감수)

  2. redis 분산락 이용 (spin lock은 지양) 2-1. mysql 분산락을 이용하는 방법도 있는 듯한데, 해본 적은 없습니다...(https://techblog.woowahan.com/2631)

  3. ThreadLocal 변수 사용 -> 이건 아직 저는 경험이 없긴 합니다. 스프링 빈으로 관리하고 있는 service나 controller에 상태변수를 넣는 것을 최대한 지양하고 있어요.

leejaeseung commented 1 year ago

DB 의 락 관련한 동시성 처리는 아니지만, 동시 및 분산 처리를 Akka 로 구현하고 있어 공유드립니다. Akka 와 actor 모델에 대한 글이 많기도 하고 막상 저도 Akka 관련 코드는 눈으로 보기만 할 뿐 건들인 적은 없어서(너무 잘 짜여져 있어서 수정할 일이 없는..).. 저희 팀에서 어떻게 활용되고 있는지 정도만 공유드릴 수 있을 것 같습니다.

저희 팀은 akka 패턴 중에 scatter-gather 패턴을 사용하고 있습니다. image 위 그림처럼 액터를 Scatter, Subtask, Gather 로 나누는 패턴입니다. Scatter : 요청받은 작업(MainTask)을 동시 처리 가능한 여러 SubTask 로 뿌려줍니다. SubTask : Scatter 가 분담해준 task 를 수행하고, 결과를 Gather 로 전송합니다. Gather : 각 SubTask 로부터 전달받은 결과를 합쳐서 처리합니다.

Akka 는 각 MainTask 마다 Scatter, SubTask, Gather 의 그룹을 매번 생성하고 관리합니다. 그룹 안에서 메시지를 전달하면 그룹 내부에서만 메시지를 주고 받겠죠. 다른 MainTask 와 겹칠 가능성을 고려하지 않아도 됩니다. 실제로 저희 코드에서도 TaskUnitGather 클래스가 var receivedCount 라는 전역 변수를 가지고 있습니다. TaskUnitGather 각각은 receivedCountSubTask 의 응답 갯수를 관리할 수 있습니다.

저희 팀에서 사용 중인 Akka 동시 처리의 사용 예를 말씀드리면 저희 팀은 여러 개의 조건(true/false)을 묶은 HQL 이라는 자체 쿼리를 관리합니다. 각 조건들은 AND 들만으로 혹은 OR 들만으로 묶일 수 있습니다. (AND, OR 혼용 불가) 각 조건은 다른 서비스의 API 를 호출해야 하기 때문에 지연이 발생합니다. 만약 동시 처리를 하지 않는다면 모든 조건을 순차적으로 판단하고, 모두 판단이 끝나야 전체 HQL 에 대한 판단이 가능하겠죠.

Scatter 로 각 조건을 각각의 SubTask 로 쪼개고, SubTask 는 동시 처리되어 Gather 로 조건 판단 결과를 전송합니다. 여기서 첫 번째로 각 API 호출이 동시 처리되어 성능 이점을 얻을 수 있습니다. 또, 모든 조건은 모두가 AND 혹은 OR 로만 묶여있기 때문에, 다른 조건을 skip 할 수 있습니다. 만약 모든 조건이 AND 로 묶여있는데 가장 먼저 온 결과가 false 라면 다른 조건을 기다리지 않고 최종 결과를 false 로 반환할 수 있겠죠.

이번 기회에 Akka 코드를 자세히 훑어보게 되었는데, 확실히 각 actor 의 메시지를 따라가면서 전체 구조를 파악하기 쉽다는 느낌을 받았습니다. 여러 동시성 이슈를 Akka 가 차단하고 각각 독립적인 actor 의 로직만 살피면 되니 상당히 직관적으로 보여지더라구요.

사실 Akka 관련 자료를 보는게 더 도움이 되실꺼라 생각하지만.. Akka 의 활용 예시를 공유해보는 것도 좋을 것 같아 짧게나마 정리해 보았습니다..ㅎㅎ