분산락을 적용한 뒤 부하 테스트를 진행하는 과정에서 5XX 응답이 과도하게 발생하는 현상을 확인했습니다. 이번 작업의 목적은 동일한 결제 성공 콜백이 동시에 들어오는 상황에서 분산락이 의도한 대로 동작하는지 검증하고, 그 결과를 해석 가능하게 만드는 것이었습니다. 문제는 5XX가 발생했을 때 그것이 분산락 경합에 의한 결과인지, 아니면 락 외부의 예외인지 구분하기 어려웠다는 점이었습니다. 따라서 이번 작업에서는 결제 기능 전체의 안정성 개선보다, 분산락 동작을 방해하는 노이즈를 줄이고, 락 경쟁 결과를 명확히 관측할 수 있도록 만드는 것에 초점을 맞췄습니다.먼저 200UV를 기준으로 잡고 k6를 돌려보겠습니다.30분간 200UV를 돌린결과 5XX에러가 19950번이 발생이 되었다는 것을 알 수 있습니다...
Stateless하게 개발한다는 것은 무엇을 의미할까? HTTP는 무상태(stateless)라고 하고, 아키텍처에서도 stateless라는 말이 자주 등장한다. 처음에는 이 개념이 잘 이해되지 않았다. 왜냐하면 상태를 가진다는 것은 결국 어딘가에 데이터가 저장된다는 의미이기 때문이다. 그렇다면 DB나 Redis 같은 저장소를 사용하는 순간 stateless하지 않은 것이 아닌가라는 생각이 들었다. 하지만 이는 잘못된 이해였다. Stateless의 기준은 인프라 전체가 아니라 서버이다. DB나 Redis를 사용하는 것은 상태를 없애는 것이 아니라, 서버 외부로 분리하는 것이다. 즉, stateless하게 개발한다는 것은 서버가 데이터를 전혀 저장하지 않는다는 의미가 아니라, 서버가 이전 요청의 상태를 기억..
스프링 이벤트스프링 이벤트(Spring Events)는 애플리케이션 내에서 컴포넌트 간의 느슨한 결합(loose coupling)을 유지하면서 비동기적 또는 동기적으로 메시지를 전달하는 메커니즘입니다.스프링의 Observer 패턴 기b-programmer.tistory.com이전에 스프링 이벤트를 학습한 적이 있습니다. 당시에는 이벤트가 어떻게 전달되고 실행되는지, 즉 내부 동작 방식에 집중해서 이해하려고 했습니다. 이번에는 조금 다른 관점에서 스프링 이벤트를 다시 바라보려고 합니다. 스프링 이벤트는 이벤트를 발행하는 퍼블리셔와 이를 처리하는 리스너로 구성되어 있으며, 이러한 구조는 메시지를 주고받는 MQ와 유사한 형태를 가지고 있습니다. 다만 스프링 이벤트는 Kafka나 RabbitMQ와 같은 외부 메..
이전에 데드락 관련 질문을 한적이 있었습니다. 그 당시 락을 학습을 했었을 때였던걸로 기억합니다. 아무튼 어떤 질문을 했었는데 그거는 데드락이 아니고 라이브락이라는 답변을 받은 적이 있습니다. 지금 이것들이 무엇인지 어떤건지 답변하기 어려워 이번 챕터를 준비를 하였습니다. 라이브락과 데드락의 차이는 무엇일까요? 데드락 (Deadlock)Deadlock은 두 단어로 이루어져 있습니다.Dead : 죽은, 멈춘Lock : 잠금, 자물쇠이를 직역하면 "죽은 잠금", 혹은 "완전히 막혀버린 상태"라는 의미가 됩니다.여기서 중요한 것은 Dead입니다. 단순히 잠겨 있는 상태가 아니라 더 이상 아무것도 진행되지 않는 상태를 의미합니다.가장 유명한 예시가 식사하는 철학자 문제입니다. 여러 명의 철학자가 원형 테이블에 ..
read-only일때 replica 사용하게 하기master-slave 구조 이해하기DB에서 master-slave 형태로 변경하다는 뜻은 읽기 전용과 쓰기 전용을 분리한다는 의미입니다.최근에는 master-slave라는 용어보다는 primary-replica라는 용어로 더 많이 사용이b-programmer.tistory.comMaster-Slave 환경을 구성하던 중 이상한 현상을 발견했습니다. 정상적인 구조라면 @Transactional(readOnly = true) 상황에서는Primary가 아니라 Replica로 라우팅되어야 합니다. 하지만 테스트를 진행해보니 예상과 다르게 ReadOnly 트랜잭션에서도 Primary가 사용되는 상황이 발생했습니다. 코드를 잘못 작성한 것일까 여러 부분을 확인해보았..
Actuatork6를 통해 부하 테스트와 API 테스트를 진행하면서 한 가지 한계를 느꼈습니다.요청을 보내고 결과를 확인하는 것은 가능했지만, 실제로 부하가 걸리는 동안 애플리케이션 내부에서 어떤 변화가b-programmer.tistory.com이전 장에서 Actuator에 대해 학습해봤습니다. Actuator는 Spring Boot 애플리케이션의 상태 정보를 확인할 수 있도록 제공되는 기능이라는 것을 알 수 있었습니다. Actuator를 통해 애플리케이션의 상태뿐만 아니라 메트릭 정보도 확인할 수 있으며, Prometheus와 같은 모니터링 시스템과 연동할 수 있는 endpoint도 제공됩니다. 또한 기본적으로 제공되는 다양한 메트릭 정보를 확인할 수 있다는 점도 알 수 있었습니다.그렇다면 기본적으로 ..
k6를 통해 부하 테스트와 API 테스트를 진행하면서 한 가지 한계를 느꼈습니다.요청을 보내고 결과를 확인하는 것은 가능했지만, 실제로 부하가 걸리는 동안 애플리케이션 내부에서 어떤 변화가 일어나는지 화면으로 확인하기는 어렵다는 점입니다. 그래서 자연스럽게 이런 생각이 들었습니다. 부하가 걸리는 상황을 시각적으로 모니터링할 수 있다면 더 좋지 않을까? 이럴 때 떠올릴 수 있는 대표적인 도구가 바로 Grafana입니다. Grafana는 메트릭 데이터를 시각화하여 시스템 상태를 한눈에 확인할 수 있게 도와줍니다. 그런데 Grafana가 사용하려면 먼저 애플리케이션이 자신의 상태 정보를 외부로 제공할 수 있어야 합니다. Spring Boot에서는 이를 위해 Actuator를 사용할 수 있습니다. Actuato..
국내에서는 많은 기업들이 MySQL을 사용하는 경우가 많습니다. 그래서 다른 회사들이 어떤 데이터베이스를 사용하는지에 대해서는 크게 의식하지 않았습니다. 그러다가 우연히 OpenAI가 수억 명의 사용자 규모까지 서비스를 확장한 과정을 설명한 글을 읽게 되었습니다.(https://blog.bytebytego.com/p/how-openai-scaled-to-800-million) 글을 읽다 보니 OpenAI가 PostgreSQL을 사용하고 있다는 점이 눈에 들어왔습니다. 다양한 데이터베이스가 존재하는데 왜 PostgreSQL을 선택했는지 궁금해졌습니다. 물론 이 글에서 PostgreSQL을 선택한 명확한 이유가 직접적으로 설명되지는 않습니다. 다만 일반적으로 PostgreSQL은 안정성과 성숙한 생태계를 갖..
프록시 JDBC(1)이전에 저는 파일을 통해 slow쿼리를 계산을 진행하였습니다. 하지만 그러다 보니 실시간으로 메시지를 보여주지 못하였습니다. 처음 의도가 네트워크 상황이라던지 여러 요인들이 존재하기 때b-programmer.tistory.com분량과 시간 문제로 다음 편에 작성하게 되었습니다.이전 장에서는 DelegatingDataSource와 Wrapper를 사용해야 하는 이유를 살펴보았습니다. 우리가 최종적으로 관찰하고 싶은 지점은 execute() 메서드입니다. 이 메서드는 실제로 SQL을 실행하는 역할을 합니다. 하지만 SQL은 execute() 시점에 갑자기 만들어지는 것이 아닙니다. SQL을 실행하려면 그보다 앞서 SQL을 준비하는 과정이 필요합니다. 그리고 그 역할을 담당하는 객체가 바로..
이전에 저는 파일을 통해 slow쿼리를 계산을 진행하였습니다. 하지만 그러다 보니 실시간으로 메시지를 보여주지 못하였습니다. 처음 의도가 네트워크 상황이라던지 여러 요인들이 존재하기 때문에 파일을 읽는 것을 선택하였지만, 곰곰히 생각해보니 그것을 어플리케이션 쪽에서 파일을 읽을 필요는 없었습니다. 어플리케이션에서 slow쿼리를 확인할때 그것이 네트워크 이슈나 다른 이슈들이 섞여있지 않다는 것을 확인할 필요가 없었습니다. 만약, db쪽에 slow쿼리 이슈라면 파일만 만들어두고 확인하는 방법을 선택하면 되었기 때문입니다. 그래서 slow쿼리를 파일로 읽는 방식이 아닌 datasource를 이용해서 어플리케이션에서 읽는 방법을 선택하였습니다. 중요한 사실은 datasorce에서시간 측정하는 것은 불가능합니다...
return wrapPreparedStatement(preparedStatement, sql); 슬로쿼리 모니터링 인터페이스 제작슬로 쿼리를 모니터링 인터페이스를 만들기위해 어떤 작업을 해야 할까요? slow 쿼리는 어떻게 탐지할 수 있을까?Slow Query는 단순히 실행 시간이 길었던 쿼리를 의미하는 것이 아니라, 데이터베이b-programmer.tistory.com모니터링 서비스를 만들면서, DB가 슬로우 쿼리로 판단한 요청을 로그나 알람 형태로 수집하고 보여주는 기능을 구현하고자 했습니다. 초기에는 long_query_time 값을 의도적으로 매우 낮게 설정한 뒤 테스트를 진행했고, 이때는 스케줄링 방식으로 실행했을 때도 비교적 정상적으로 슬로우 로그가 기록되는 것을 확인할 수 있었습니다. 하지..
데이터베이스는 데이터를 저장하고 관리하기 위한 인프라입니다. 일반적으로 데이터베이스라고 하면 가장 먼저 관계형 데이터베이스(RDB)를 떠올리는 경우가 많습니다. 하지만 최근에는 관계형 데이터베이스뿐만 아니라 NoSQL 데이터베이스도 함께 사용하는 경우가 많아졌습니다. 특히 애플리케이션의 요구사항에 따라 서로 다른 데이터베이스를 조합하여 사용하는 사례도 점점 늘어나고 있습니다. 또한 데이터베이스의 종류는 RDB와 NoSQL만 존재하는 것이 아닙니다. 각각의 목적과 특성에 따라 다양한 데이터베이스 유형이 존재합니다.이번 글에서는 이러한 다양한 데이터베이스 유형에 대해 함께 알아보겠습니다. RDB vs Nosql크게 DB에는 2가지 종류가 존재합니다. SQL을 사용하는 RDB와 SQL도 사용하는 NoSql(N..