// Links to the libraries needed

제가 현재 진행 중인 프로젝트는 SNS 기능이 있고 해당 게시물에는 조회 수와 좋아요 기능이 있습니다.

여기서 조회 수는 데이터의 신뢰성이 그렇게 중요하지 않다고 생각이 들지만 좋아요 수는 사용자 경험에 영향을 미칠 수도 있다는 생각이 들어 동시성 문제를 해결하며 성능을 최대한 보장해주려 합니다.

여기서 바로 생각이 드는 것은 낙관적 락, 비관적 락, 레디스가 생각이 나는데 제가 예상하기로 낙관적 락 < 비관적 락 < 레디스 순으로 성능이 좋을 것 같지만 성능을 직접 확인해보는 것이 좋을 것 같아 확인해보려 합니다.

Jmeter로 성능 테스트를 진행할 예정입니다.

Redis 고려 이유

Redis는 고려한 이유는 다음과 같습니다.

1. In-Memory DB이다.

Redis는 In-Memory DB이기 때문에 IO 작업이 훨씬 빠를 것이라 생각했습니다.

2. Redis 6.0부터는 Network IO가 추가되었다.

Redis 6.0에서는 IO만 담당하는 Thread가 3개 추가되었기 때문에 성능이 훨씬 빠를 것이라 생각했습니다.

3. Single Thread이다.

Redis는 Single Thread이고 수를 증가시키는 것은 원자적 연산으로 들어가기 때문에 데이터 신뢰성 보장을 해줄 것이라 생각했습니다.

그렇다면 이제 성능을 테스트해보겠습니다.

테스트 환경

우선 테스트 환경은 다음과 같습니다.

  • 낙관적 락과 비관적 락을 테스트해볼 게시물

image

  • 레디스를 테스트 해볼 환경

image

  • HTTP Request image

500명의 사용자가 1초에 1개씩 요청을 보내고 100번 반복합니다. 총 50000번의 요청이 서버에 보내집니다.

Same user on each iteration을 통해 각 사용자의 쿠키나 세션 등이 동일한 상태를 유지한 채로 반복 실행합니다.

테스트

우선 저는 총 실행 시간, 초당 Throughput, TPS 그래프를 중점적으로 볼 계획입니다.

테스트는 Optimistic Lock -> Pessimistic Lock -> Redis 순서로 할 예정입니다.

Optimistic Lock

  • Database

image

50000개 중 8595개만 정확히 들어간 것을 확인할 수 있습니다.

낙관적 락에서 소요 시간을 고려하여 100번 이상 반복되는 테스트는 나가게 했기 때문에 데이터가 많이 튕겨 나간 것을 확인할 수 있습니다.

  • Summary Report

image

테스트에 총 1분 13초가 소요되었습니다. 단순히 생각해도 오래 걸린 것을 알 수 있습니다.

Error는 82.81%가 나왔고 초당 Throughput은 678.5가 나온 것을 확인할 수 있습니다.

역시 데이터의 신뢰성을 보장할 수 없다는 것을 확인할 수 있었습니다.

  • TPS Graph

image

HTTP Request 요청의 성공과 실패가 불안정한 것을 볼 수 있습니다.

성공 요청은 그나마 일정한데 실패 요청이 불안정하게 많아졌다가 적어지는 모습을 반복하고 있습니다.

Pessimistic Lock

  • Database

image

50000개 모두 정확히 들어간 것을 확인할 수 있습니다.

비관적 락은 순차적으로 모든 데이터가 충돌을 일으키지 않기 때문에 데이터의 신뢰성이 보장되는 것을 확인할 수 있습니다.

  • Summary Report

image

테스트에 총 31초가 소요되었습니다. 낙관적 락보다 2배 정도 빠른 것을 확인할 수 있습니다.

낙관적 락보다는 충돌이 많이 예상될 때 사용하는 방법이기 때문에 테스트 환경과 같이 충돌이 많이 발생하는 환경에서 더 효율적인 모습을 보여주는 것 같습니다.

Error는 0%가 나왔고 초당 Throughput은 1582.6가 나온 것을 확인할 수 있습니다.

데이터의 신뢰성을 보장하고 성능적인 우수함도 가져가고 있습니다.

  • TPS Graph

image

HTTP Request 요청의 성공이 일정하게 유지되는 것을 확인할 수 있습니다.

확실히 낙관적 락보다 충돌이 많은 상황에서 안정적인 것을 확인할 수 있습니다.

요청이 1000 ~ 1900 사이로 폭이 조금 크지만 그래도 성공이 일정한 그래프를 그리며 유지되고 있습니다.

Redis

Single Thread에 In-Memory DB인 Redis를 사용하여 테스트해보겠습니다.

  • Database

image

50000개 모두 정확히 들어간 것을 확인할 수 있습니다.

Redis 또한 Single Thread로 순차적으로 모든 데이터가 충돌을 일으키지 않기 때문에 데이터의 신뢰성이 보장되는 것을 확인할 수 있습니다.

  • Summary Report

image

테스트에 총 14초가 소요되었습니다. 비관적 락보다 2배 정도 빠른 것을 확인할 수 있습니다.

Redi는 Single Thread지만 In-Memory DB로 데이터베이스 통신 비용이 적게 들고 Redis 6부터는 네트워크 IO를 위한 Thread 3개가 생겼기 때문에 더 성능이 우월한 거 같습니다.

Error는 0%가 나왔고 초당 Throughput은 3417.2가 나온 것을 확인할 수 있습니다.

데이터의 신뢰성을 보장하고 성능적인 우수함도 가져가고 있습니다.

  • TPS Graph

image

HTTP Request 요청의 성공이 일정하게 유지되는 것을 확인할 수 있습니다.

요청을 첫 부분과 끝 부분을 빼고 보면 3200~3900까지 폭이 크지 않고 일정하게 유지되는 것을 확인할 수 있습니다.

비관적락은 1000~1900으로 작동했던 것을 보면 비율적으로 훨씬 안정적이라고 생각해볼 수 있습니다.

정리

처음에 예상했던 대로 낙관적 락 < 비관적 락 < 레디스 순으로 성능이 좋은 것을 확인했습니다.

낙관적 락에서 레디스를 사용할 때는 성능이 80.82% 개선되었고

비관적 락에서 레디스를 사용할 때는 성능이 54.84% 개선되었습니다.

image

물론 Redis는 In-Memory DB라 포스트에 대한 좋아요 데이터를 영구적으로 계속 사용할 수는 없을 것 같아 아키텍쳐에 대한 고민은 더 가져봐야할 것 같습니다.


© 2024. All rights reserved.

김민제의 블로그