글 작성자: Key Ryung

개요

이번 포스팅에서는 재고 관리 Integrity 문제 1편의 마지막에 '왜 Database Lock이 Distributed-Lock보다 TPS 성능이 좋겠나왔는가?'를 다뤄보려고 합니다. 

 

주의🚫 : 해당 테스트에서 Distributed-Lock이 DB Lock보다 성능이 안 좋게 나왔지만 Database Lock은 항상 Distributed-Lock보다 좋다라는 관점은 적절하지 않습니다.

 

Distributed-Lock은 왜 사용할까?

처음 예상하기로는 In-memory DB를 통해서 Lock을 수행하므로 막연히 더 빠르겠지(?)라는 생각을 갖고 있었습니다. 더불어 분산 락으로 인해 Database에서 해당 Row에 대한 Update 동작을 경합할 Transaction의 수가 적어지니 Database에서도 Lock에 대한 WAIT가 짧아지므로 전체적인 요청-응답 사이클이 빨라질 것이라 예상했습니다. 하지만 이 모든 가정들이 저만의 상상이었다는 것을 모니터링 결과를 통해 알게 되었습니다.

 

Distributed-Lock은 분산 환경에서 Lock을 제공하여 동기화된 처리를 제공할 목적이라는 것이 핵심입니다.

Distributed-Lock 동작 Diagram

무엇이 다시 병목 지점을 만들어냈을까?

위의 Diagram에서 Thread가 어디서 Blocking 될지 예상해보면 두 곳이 보입니다. 분산 락이 수행되는 부분과 DB에서 재고를 차감하기 위해 락이 수행되는 부분입니다. 분산 락을 통해서 재고 데이터 검증하는 트랜잭션이 하나만 유지되어 무결성을 지킬 수 있었지만 다시 DB를 통해서 Lock이 수행되므로 DB Lock이 해제된 후 분산락도 해제되는 구조입니다.

 

Database Node Monitoring / 위 - DB Lock, 아래 - Distributed-Lock

데이터베이스 노드 모니터링 결과를 보면 차이가 없는 것을 확인할 수 있습니다. 따라서 분산락을 사용해도 DB의 Busy IO Wait가 비슷한 비율로 수행됩니다. 그렇다면 다시 원래 질문으로 돌아가기 위한 Pinpoint 지표를 살펴보겠습니다.

 

Pinpoint Inspector / 위 - DB Lock, 아래 - Distributed Lock

Response Time은 Distributed Lock이 짧고 특히 Total Thread와 Tomcat의 Connection과 관련된(Socket 동작) Direct Buffer Count의 경우 Distributed Lock을 사용하는 곳에서 더 적은 것을 확인할 수 있었습니다.

 

* Thread Dump를 확인했었으면 더 정확한 판단이 가능했을 텐데 이 부분은 확인하지 못했습니다.

 

하나의 Application 기준으로 DB Lock은 Thread가 280개 정도 사용되고 분산 락은 130개 정도 사용됩니다. Direct Buffer Count를 맺어진 Connection의 개수와 비슷하다고 가정한다면 DB Lock은 200개로 Tomcat의 Max Thread 기본 세팅과 같고 이에 반해 Distributed Lock은 75개 정도로 측정됩니다. 이와 비슷한 비율을 TPS 비교표에서 확인할 수 있습니다.

 

  Distributed-Lock Database Lock
TPS 158 411.8

 

이런 현상은 Distributed-Lock의 동작과 관련 있다고 판단했습니다. 분산 락은 분산 환경에서 동기화된 처리를 위해 사용됩니다. Scale-Out을 사용하면서 Resource들이 수평적으로 확장되어 성능이 올라갔지만 분산 락을 사용함으로써 결국 한 순간에 처리될 수 있는 요청을 하나밖에 없으므로 이에 따라 하나의 요청이 처리되는 시간 자체(Response Time)는 향상되지만 전체적으로 처리되는 양은 줄어듭니다. 

 

재고 데이터 무결성 검증

Database Lock과 분산 락 모두 재고 데이터에 대한 무결성을 검증했습니다. Redis와 통신하는 부분은 로그인 한 유저만 구매할 수 있도록 처리했기 때문에 로그인 정보를 가지고 오는 부분에서 Counting 되었습니다.

구매 주문만 Filtering한 Pinpoint Bird View - DB Lock

Pinpoint에서 확인한 결과 구매 요청은 80,518이라고 모니터링되었지만 실제로 생성된 주문 건수는 80,521개로 확인되었고 한 번의 구매 시 10개씩 구매하여 99,194,790개의 재고가 정확히 남는 것을 확인할 수 있었습니다.

 

Next Level

Database Lock을 통해 Write-Skew를 막아 데이터의 무결성을 보장할 수 있었지만 목표한 TPS에는 한참 미치지 못합니다. 처음 프로젝트 기획 시 적어도 500명의 유저들이 동시에 구매하는 상황까지 예상을 했기 때문에 성능을 더 높일 필요성이 있습니다.

 

고민을 위한 여지

  • 왜 분산 락을 적용했을 때 Connection의 수가 줄었을까? 재확인 필요

 

해당 프로젝트는 네이버 클라우드를 활용하여 진행했습니다.