[댕댕어디가] 선착순 이벤트 시스템 구현기 - 동시성 문제 해결
·
댕댕어디가 프로젝트/트러블슈팅
선착순 이벤트 시스템이란?댕댕어디가에는 펫 페스티벌 티켓을 선착순으로 받을 수 있는 이벤트가 존재합니다. 빠른 저장과 부하를 위해 이벤트 당시에는 티켓을 발급한 유저의 정보를 Redis에 저장한 후, MySQL에 영속화하는 과정을 거칩니다. 이전 글에서는 이러한 선착순 이벤트 시스템 구현 과정을 글로 정리하여 남겼으며 부하테스트를 진행하여 목표 시간내 실행되는 것을 확인하였습니다. 그런데 테스트 중간 중간에 원하는 발급량보다 더 많이 발급하는 것을 확인하였고, 이번엔 이를 해결하기 위해 글로 남기고자 합니다.https://gani-dev.tistory.com/154 1. 동시성 문제 발견여러번의 부하 테스트 도중, 300개보다 더 많이 티켓을 발급한 경우를 확인할 수 있었습니다.2. 동시성 문제 발생 원..
[댕댕어디가] 땅따먹기 주인 조회 API 속도 개선
·
댕댕어디가 프로젝트/트러블슈팅
1. 땅따먹기란댕댕어디가에는 땅따먹기 서비스가 존재합니다.'땅따먹기'란, 각 지역에 있는 반려동물 동반 가능 시설을 가장 많이 방문한 유저가 땅 주인이되는 기능을 말하며, 땅 주인이 되면 보상으로 스토리 업로드 혜택이 주어집니다.  2. 부하테스트그러나 모든 지역의 땅 주인을 조회하는 API가 응답 속도가 느린 문제가 있었습니다.잦은 요청이 있는 API임에도 불구하고 다른 API보다 속도가 느려 부하테스트를 진행하였습니다. DAU가 2만명인 것을 가정하여, 10%인 2000명이 동시에 요청했을 때의 시나리오로 테스트해 봤습니다..결과는 실패율 100%..! 아래와 같은 오류가 발생했습니다. DB 연결시 파일 디스크립터를 할당받는데, 할당 받을 수 있는 파일 디스크립터가 초과했다는 뜻입니다.허용 가능한 파..
[댕댕어디가] 선착순 이벤트 시스템 구현기
·
댕댕어디가 프로젝트/트러블슈팅
'댕댕어디가' 서비스에는 선착순으로 티켓을 발급받을 수 있는 기능이 있습니다. (ex. 펫 페스티벌 입장권)1.이벤트 시스템 구현 유저의 티켓 발급 요청을 받으면, 애플리케이션에서 유저의 아이디를 추출해 Redis에 저장합니다.이때, Redis에는 HashMap 자료형으로 {"유저ID" : "발급시간"} 값을 저장합니다. 기존 발급 가능 인원까지 저장한 후,  목표 인원이 모이면 마감되었다는 응답을 전달합니다.  이벤트가 마감되면 Redis에 저장된 유저의 정보와 발급시간을 활용해, 가장 빨리 발급한 순서대로, 가능 인원수만큼 DB에 저장하여 영속화하는 과정을 거칩니다. Redis에 저장하는 이유선착순 이벤트 기능은 동시에 트래픽이 가장 많이 몰리는 기능 중 하나입니다.이때, 유저가 요청할 때마다 유저 ..
[댕댕어디가] MSA 아키텍처 전환기(8) - 서비스간 트랜잭션
·
댕댕어디가 프로젝트/MSA
지금까지, 모놀리식 아키텍처를 MSA 아키텍처로 분리하고 연결하는 과정을 경험해봤습니다.하지만, 서비스가 분리되면서 생긴 트랙잭션 문제가 있는데요, 이를 해결하기 위해 어떤 방법들이 있는지 알아보겠습니다. 1. 분산 트랜잭션 문제이전 글에도 나왔던 상황인, '실시간 장소 방문 인증' 로직은 두개의 서비스가 분리되어 통신하면서 로직을 처리합니다. flow사용자 : 실시간 리뷰 작성 -> project-service : 실시간 리뷰 저장 -> region-service : 지역 방문 횟수 증가 하지만 지역 방문 횟수를 증가시키는 과정에서 장애(DB 연결 실패,저장 실패)가 발생한다면, 실시간 리뷰 저장은 롤백되지 않아, 실시간 리뷰 개수와 방문 횟수 사이에 원자성이 깨지게됩니다. 이를 해결하기 위해 2가지 ..
[댕댕어디가] MSA 아키텍처 전환기(7) - 인증서버 연결
·
댕댕어디가 프로젝트/MSA
기존 모놀리식 아키텍처에서는 JWT 기반 인증을 진행했었습니다.서비스가 나뉜 지금도 각 서비스마다 시큐리티 필터를 거쳐 jwt 인증이 필요한데, 여기서 문제는 서비스마다 인증이 따로 된다는 점과 DB가 분리되어 인증에 필요한 유저 정보를 조회할 수가 없다는 점입니다. 이를 해결하기 위해 선택한 방법은, 각 서비스마다 인증 필터를 두는 것이 아닌 api gateway에서 pre filter로 인증/인가 작업을 진행하기로 결정하였습니다. 인증 서버까지 따로 분리하면 좋겠지만 아직은 MSA 아키텍처 전환 초기 셋팅이 완료되지 않아 이후에 분리할 예정이고, 현재는 project-service에서 인증 역할을 맡으려고 합니다. 목표 flow사용자 요청 -> api gateway - pre filter에서 jwt ..
[댕댕어디가] MSA 아키텍처 전환기(6) - 서비스간 동기 통신(Spring Cloud Open Feign)
·
댕댕어디가 프로젝트/MSA
이번에는 서비스간 동기 통신이 필요한 경우 어떻게 해결했는지 이야기해보려 합니다. 1. 문제 발생 : 동기 통신이 필요하게 된 계기region-service에는 모든 지역의 땅 주인 정보를 조회하는 API가 있습니다. 각 지역의 땅 주인 닉네임과 펫 정보를 함께 제공해야 하지만, 서비스 분리로 인해 DB가 나뉘면서 region-service DB에서는 최근 땅 주인들의 userId 정보만 조회할 수 있고, 해당 userId에 대한 추가 정보는 조회할 수 없습니다. 이를 해결하기 위해, 유저의 닉네임과 펫 정보를 project-service에 동기적으로 요청하기로 결정했습니다.  2. 동기 통신 구성 : Spring Cloud OpenFeignOpen Feign이란 ?선언적인 http 클라이언트 도구로, ..
[댕댕어디가] MSA 아키텍처 전환기(5) - 서비스간 비동기 통신 (kafka 연결)
·
댕댕어디가 프로젝트/MSA
이번 시간에는, 지역별 방문 횟수 증가 로직에 필요한 통신을 연결해 보겠습니다. 지역별 방문 횟수 증가 로직 : 유저가 A라는 지역의 A1 시설을 방문하면, 이를 인증하기 위해 실시간 리뷰를 작성하여 방문 횟수를 증가시킵니다. 이때, A 지역에서 방문 횟수가 가장 많은 유저가 땅의 주인이됩니다. service별 역할유저 실시간 리뷰 작성 요청 -> project-service 에서 실시간 리뷰 저장 -> region-service에서 방문 횟수 증가 및 새로운 땅의 주인 판별 통신이 필요한 부분projdect-service에서 실시간 리뷰를 저장한 후, 방문 횟수를 증가시키기 위해 region-service에 요청을 전달해야합니다. 1. Kafka 클러스터 구성kafka 클러스터 구성 과정에 대해서는 간..
[댕댕어디가] MSA 아키텍처 전환기(4) - 서비스간 비동기 통신하기
·
댕댕어디가 프로젝트/MSA
project-service와 region-service 간에는 통신이 필요합니다. 그 중에서 이번에는 비동기 통신이 필요한 경우 어떻게 해결했는지 이야기해보려 합니다. 대표적인 예시에는 방문 횟수 증가 로직이 있습니다.: 유저가 A라는 지역의 A1 시설을 방문하면, 이를 인증하기 위해 실시간 리뷰를 작성하여 방문 횟수를 증가시킵니다. 이때, A 지역에서 방문 횟수가 가장 많은 유저가 땅의 주인이됩니다. 해당 로직을 service별로 역할을 나누어보면 다음과 같습니다. 유저 실시간 리뷰 작성 요청 -> project-service 에서 실시간 리뷰 저장 -> region-service에서 방문 횟수 증가 및 새로운 땅의 주인 판별위의 로직을 처리하기 위해서는 MSA 아키텍처에서는 서비스 간의 통신이 필요..