분산락 적용하기 (실전)

유수민·5일 전
1
post-thumbnail

이전까지는 왜 분산락을 적용했고, 해당 코드가 어떤지에 대해서 이야기해보았다.
이번에는 적용한 코드가 우리가 원하는 동시성에 대한 대책이 제대로 되었는지에 대한 이야기를 해볼것이다.

📌 조건은?

우선, 난 Jmeter를 활용해서 하나의 락을 거는 @DistributedLock과 여러 락을 동시에 거는@MultiDistributedLock에 대한 동시성 테스트를 진행했다.
조건은 둘다 똑같이 설정했다.

조건을 해석해보자면,

  • 50개의 스레드 (동시 사용자 50명)
  • Ramp-up 시간 50초 (1초마다 1개의 스레드가 추가됨)
  • Loop Count: 10 (각 스레드가 10번 반복 요청)

→ 즉, 최대 500개의 요청이 순차적으로 발생

추가적으로 설명하자면,
Ramp-up Period는 모든 스레드(사용자)를 얼마나 걸쳐서 실행할지를 결정하는 값이다.
즉, JMeter는 총 N개의 스레드를 Ramp-up Period 동안 균등하게 분배하여 시작한다.

이걸 공식으로 정리하자면,
🔹 스레드 시작 간격 (초) = Ramp-up Period / 총 스레드 개수

내가 설정한 조건에 의하면, Ramp-up Period를 50초, 스레드 개수를 50으로 설정하게 되고
50초/50쓰레드 가 되니 1초마다 1개의 스레드가 추가되는 구조가 된다.

정리하자면, 50초 동안 50개의 스레드가 점진적으로 늘어나며, 매 초마다 1개의 스레드가 실행된다. 50초가 지나면 모든 스레드가 동시에 실행된 상태에서 반복(Loop Count: 10번)하면서 요청을 보내게 되는 조건이다.

📌 테스트 해볼까?

이제 본격적으로 테스트를 해보자.

@DistributedLock 테스트

{
  "id": "row:2"
}

하나의 키를 동시에 여러번 테스트하는 것인데 한 키만을 걸었기 때문일까


모든 요청이 동시에 보냈음에도 불구하고 성공률이 100%였다 ㅋㅋㅋ

하나하나 뜯어보자면,

  • Samples: 500 → 총 500개의 요청이 전송됨
  • Average: 5006 ms → 모든 요청의 평균 응답 시간이 5006ms (5.006초)
  • Median: 5006 ms → 응답 시간을 작은 순서대로 정렬했을 때 중간 값이 5006ms
  • 90% Line: 5010 ms → 응답 시간이 5010ms 이하인 요청이 전체의 90%
  • 95% Line: 5012 ms → 응답 시간이 5012ms 이하인 요청이 전체의 95%
  • 99% Line: 5015 ms → 응답 시간이 5015ms 이하인 요청이 전체의 99%
  • Min: 5001 ms → 가장 빠른 응답 시간이 5001ms
  • Max: 5028 ms → 가장 느린 응답 시간이 5028ms
  • Error %: 0.0% → 오류 없이 100% 성공
  • Throughput: 5.0/sec → 초당 평균 5개의 요청을 처리
  • Received KB/sec: 0.86 KB/s → 서버에서 초당 0.86KB 데이터를 받아옴
  • Sent KB/sec: 1.03 KB/s → 서버로 초당 1.03KB 데이터를 보냄

평균 응답시간 (Throughput)이 5초인게 아마 코드 상 Thread.sleep(5000) 영향인 듯 싶다.
사실 어떻게 100% 성공일 수 있지? 설마 락이 안걸리나 싶어서

log를 걸어서 봤는데 락이 잘 걸려있는 것을 확인할 수 있었다.
그렇다면 멀티로 락을 걸었을때는 어떨까?

@MultiDistributedLock 테스트

@DistributedLock과 같은 조건으로 진행하였다.
사실 처음에 테스트 할때는 이것도 성공률이 100%일줄 알았다.

뭐야? 이건 왜 간간히 성공해?? 왜 실패한건 500에러야?

에러 메세지를 확인해보니, 락 거는데 에러가 뜬거였다.

Single 락과 Multi 락 왜 같은 조건인데 결과가 다를까??

✔️ @DistributedLock (Single)

  • 요청마다 하나의 키(row:2 같은 단일 값)만 사용
  • waitTime = 15이므로 락을 못 잡으면 최대 15초까지 대기 + 쓰레드 sleep 5초
  • 하나의 키만 처리하므로 충돌 가능성이 낮음
  • 결과적으로 스레드 간 충돌 없이 요청이 순차적으로 처리됨 → 실패율 낮음

✔️ @MultiDistributedLock (Multi)

  • 여러 개의 키(["row:2","row:1","row:3"])를 락으로 사용
  • 만약 다른 스레드가 row:1을 선점했다면, row:2와 row:3이 잠겨 있어도 락을 얻지 못함
  • 락을 얻지 못하면 실패 (대기 시간이 지나도 모든 키를 얻지 못하면 실패)
  • 일부 키만 사용 가능해도 전체가 실패하는 구조 → 충돌 가능성이 급증

따라서 싱글락과 달리 멀티락에서 에러가 뜨는 것은 동시성 테스트에서 잘 방어를 하고 있다는 뜻이었다.

참고) 나의 github 코드 : https://github.com/sue4869/lockPractice

profile
배우는 것이 즐겁다!

0개의 댓글

관련 채용 정보