스케줄러와 상태 관리를 통한 분할 트랜잭션과 복구 로직 설계
·
프로젝트/트러블 슈팅
단일 트랜잭션으로 인한 문제https://tojaman.tistory.com/188 현재 트랜잭션 범위는 결제 정보 검증 및 스케줄 점유 → 결제 API 호출 → 결제/매칭 완료 처리 순으로 되어 있다.위 작업들을 하나의 트랜잭션으로 묶게 되면 외부 API 요청 대기로 인해 트랜잭션의 시간이 매우 길어질 수 있고, 이로 인해 다음 문제가 발생할 수 있다.커넥션 풀 부족트랜잭션이 커넥션을 붙잡고 오래 대기하게 되면 커넥션 풀이 고갈 되어 이후 요청들을 대기 큐에 들어가게 된다.이로 인해 타임 아웃이 발생하고 처리 성능이 저하될 수 있다.잠금 대기트랜잭션에서 락을 거는 경우 이후 요청들이 락을 대기하게 되며 대기 시간이 길어진다. (상황에 따라 데드락 발생 가능성도 높아짐)타임 아웃으로 인한 불일치결제 AP..
토스 결제 API 연동
·
프로젝트/트러블 슈팅
결제 동작 방식토스페이먼트 API의 동작 방식은 아래와 같이 결제 요청과 결제 승인을 따로 한다.결제 요청① 클라이언트 → 서버: orderId, amount 임시 저장② 클라이언트 → 토스 SDK: 결제 요청 메서드 호출 (결제창 오픈)③ 클라이언트 ↔ 카드사: 카드 정보 입력 및 인증↓ 인증 완료④ 토스 → 클라이언트: successUrl(paymentKey, orderId, amount 포함)로 리다이렉트결제 승인⑤ 클라이언트 → 서버 → 토스: 승인 API 호출서버: 기존 DB 저장값과 successUrl 파라미터 값 비교 검증토스 → 카드사: 금액 차감요청과 승인을 따로 받는 이유 - 데이터 정합성결제 "인증"과 "승인"이 비동기로 일어나기 때문에 데이터 정합성과 연동 편의를 위해 따로 진행 인..
S2 Geometry 로컬 캐싱으로 대규모 조회 성능 개선
·
프로젝트/트러블 슈팅
S2 Geometry를 이용한 지도 조회 최적화( vs GeoHash)S2 구현을 완료했으니 이제 캐싱을 구현하여 성능을 끌어 올려보자먼저 로컬 캐시와 글로벌 캐시 중 뭘 선택했고 캐시 전략, TTL, 빈 셀 캐싱 등 설계 근거를 설명하고 실제 구현 로직을 설명하겠다.캐시 설계캐시란?흔히 캐시를 이야기할 때 Redis를 자주 언급하곤 한다.Redis는 별도의 인스턴스에 메모리를 캐시로 사용하는 방식이고, 이는 고가용성을 위해 Scale-Out하여 동일한 서버를 여러 대 운영할 때 서버 간 데이터 정합성 문제를 완벽히 지킬 수 있다.Redis를 사용한다면 각 서버가 하나의 캐시를 바라보기 때문에 데이터 불일치 문제가 발생하지 않는다.하지만 로컬 캐시만을 사용한다면 각 서버가 캐싱한 데이터에 따라 데이터 불..
S2 Geometry를 이용한 지도 조회 최적화( vs GeoHash)
·
프로젝트/트러블 슈팅
기존 위경도 기반 조회의 한계대용량 트래픽 환경에서 위경도 기반 실시간 연산과 ST_SnapToGrid 클러스터링 방식이 목표 TPS에 도달하지 못했고, 캐싱 전략 도입이 원천적으로 불가능기존 구현 방식기존 지도 조회 API는 다음과 같은 방식으로 구현되어 있다.마커 조회: 클라이언트가 전송한 BBox(Bounding Box) 좌표로 직접 DB 조회SELECT * FROM trainer_profiles WHERE latitude BETWEEN :minLat AND :maxLat AND longitude BETWEEN :minLon AND :maxLon AND sport_type = :sportType;클러스터링: PostGIS의 ST_SnapToGrid 함수를 이용한 그리드 클러스터링SELECT ..
인근 시설 조회 기능 구현과 최적화
·
프로젝트/트러블 슈팅
전에 공간 연산이 필요해서 PostGIS를 도입했다.1. MySQL GIS vs PostgreSQL PostGIS 공간 DB 선택인근 헬스장 검색, 법정동 헬스장 검색, 지도 클러스터링 기능을 구현 방식 블라블라이번 글에서는 공간 연산의 한계와 비정규화를 통한 개선 방법을 작성해보겠다.기능 별 구현 및 성능 개선인근 헬스장 검색단순히 지도를 움직이며 대략적인 주변 정보를 볼 때는 속도를, 특정 반경 내 정보를 정확히 볼 때는 정밀도를 우선순위에 두고 구현 방식을 Bounding Box와 PostGIS(ST_DWithin)로 분리Bounding Box사각형으로 인근 위치를 조회하며, 위경도를 사용하기 때문에 B-Tree 인덱스 스캔을 사용하고 매우 빠르다.PostGISST_DWithin(A, B, 거리(미..
MySQL GIS vs PostgreSQL 공간 데이터를 다루기 위한 DB 선택
·
프로젝트/트러블 슈팅
공간 데이터를 다루려면 어떤 기술이 필요할까?최근 Bounding Box 방식으로 지도에 내 주변, 지하철 역 반경 몇 km 이내 스포츠 시설 주소를 띄우는 기능을 구현했다.이 방식은 단순히 위경도 값이 특정 범위 안에 있는지 WHERE lat BETWEEN ? AND ? 하면 되기 때문에 구현이 간단하고 인덱스를 타기 좋아 빠르다.Page findByGymLatitudeBetweenAndGymLongitudeBetween( double minLat, double maxLat, double minLng, double maxLng, Pageable pageable);-- 내부적으로 실행되는 쿼리 예시SELECT * FROM trainer_profile WHERE gym_latitude BE..