일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 구현
- 누적합
- 크롤링
- JPA
- 관측가능성
- dau 3만명
- piplining
- langgraph
- 몽고 인덱스
- ipo 매매자동화
- 이분탐색
- 디버깅
- 아키텍쳐 개선
- spring event
- 완전탐색
- gRPC
- 추천 검색 기능
- docker
- next-stock
- 쿠키
- 백준
- 베타적락
- 카카오
- 결제서비스
- 알람시스템
- 프로그래머스
- AWS
- BFS
- 셀러리
- ai agent
- Today
- Total
코딩관계론
일평균 700건 이상의 요청에서 "세션 점유 중" 오류를 10건 이하로 본문
회사에서 홈택스 데이터를 스크래핑하는 일을 맡았다. 사용자에게 제공해야 하는 세금 정보는 크게 두 가지, **세와 **세. 문제는 이 두 스크래핑이 동시에 실행되면 서로의 세션을 덮어쓰는 문제가 발생한다는 점이었다. 세션 충돌은 곧 사용자 경험의 악화로 이어지고, 안정성이 생명인 서비스에서는 반드시 해결해야 할 사안이었다.
[Z5004]: [LOGIN-999] 통합인증(중복 로그인) 오류입니다.
그래서 선택한 해법이 Redis 기반의 분산락이었다. 우리 회사 인프라는 AWS의 관리형 ElastiCache를 사용하고 있고, Latency 측면에서도 EKS 내에서의 접근이라 꽤 빠른 편이었다.
처음에는 Redis I/O 비용을 줄이자는 생각으로. 락 획득 여부를 Redis에 일일이 물어보는 대신, 로컬 메모리에서 상태를 관리하면 더 효율적일 거라고 생각했다. 실제로 응답 속도는 빨라졌고, 서비스 초반엔 큰 문제가 없어 보였다. 실제로 시스템을 모니터링하고 있었는데 락 평균 유지시간이 대체로 2분에서 4분정도로 예상하는 범위안에 들어오고 있었다.
그런데 이상한 일이 생겼다. 모니터링 시스템에서는 락이 4분 이상 점유되는 경우가 거의 없었는데, 애플리케이션 로그에서는 특정 요청들이 계속 sleeping 상태로 대기하고 있는 것이었다.
황급히 다시 그라파나를 확인했었지만 락 대기자가 많지 않았었고, 상당히 모순적인 로그였다. 중성의 원인은 Redis가 아니었다. 진짜 문제는 우리가 락 상태를 Redis와 통신하지 않고, 애플리케이션 내 로컬 해시맵으로 관리하고 있었던 방식에 있었다. 락을 잡지 못했을 때도 finally 블럭에서 로컬 락을 해제하지 않고 남겨둔 코드가 누적되면서, 가짜로 "락을 점유 중"인 상태가 계속 유지되고 있었던 것이다. 이 상태에서 들어오는 요청은 모두 대기 상태에 들어가며, 마치 실제 락을 점유 중인 것처럼 오인하게 만들었다.
문제를 해결하기 위해 로컬 락 관리 로직을 전면 재정비했다. 락 획득에 실패했을 경우에도 반드시 finally 블럭에서 로컬 락을 정리하도록 수정했고, 락이 점유된 시간과 재시도 횟수에 대한 로그를 추가로 남기도록 했다.
private async lockAndScrapeCompanyData(
company: Company, userCache:boolean
): Promise<Record<string, any> | CompanyLockAcquireFailException> {
await this.companyRedisLockService.acquireLock(company);
try{
const scraped = await this.scrapeLambdaHometaxData(company, {
useCache: userCache,
});
return scraped;
}finally {
await this.companyRedisLockService.releaseLock(company);
}
}
그 결과는 숫자로도 드러났다. 기존에는 하루 평균 700건 이상의 요청에서 "세션 점유 중" 오류가 발생했는데, 수정 이후에는 10건 이하로 급감했다.
'개발' 카테고리의 다른 글
20만명 이벤트와 서버 다운 (0) | 2025.07.10 |
---|---|
DAU 3만명 이 구조로는 못 버텨요… 내가 직접 설계한 비동기 설문 시스템 (1) | 2025.06.22 |
DB Exclusive Lock 에러 (0) | 2025.06.07 |
결제서비스 (0) | 2024.09.02 |
Redis 분산 시스템에서의 동시성 문제 해결 (0) | 2024.08.25 |