
분산 락 사용 시 상위 트랜잭션이 있으면 안되는 이유 주문 기능 중 재고 차감을 데이터 정합성을 위해 비관적 락으로 먼저 구현하고, 다음으로 Redisson을 사용하여 분산 락으로 구현하려고 했지만 주문 트랜잭션에서 상위 트랜잭션이 있는 경우에는 적용하지 못해 그 이유에 대해 작성해보고자 한다. Redisson을 사용한 분산 락 Redisson은 pub/sub 기반으로 Lock 구현을 제공한다. 채널을 하나 만들고 Lock을 점유중인 스레드가 Lock을 획득하려고 하는 스레드들에게 해제를 알려주고 안내를 받은 스레드가 Lock 획득 시도하는 방식으로 스핀락을 통해 계속해서 락을 획득할 수 있는지 요청해야 하는 Lettuce의 경우보다 부하를 덜 줄 수 있다. boolean tryLock(long wait..

페이징 성능 개선: offset vs no offset vs covering index 웹 서비스에서 페이징은 아주 흔하게 사용되는 기능이다. 일반적으로 페이징은 구현한다면 LIMIT ... OFFSET ...; 와 같은 패턴으로 OFFSET을 사용하는데 이는 점차 데이터가 많아짐에 따라 수십초 ~ 수분까지 조회가 느려질 수도 있다. 따라서 No offset과 Covering index를 통해서 페이징 기능을 개선하는 방법에 대해서 살펴보자. product 테이블에 대략 1,572만 건 상품 데이터가 있다. OFFSET LIMIT 쿼리는 결과에서 지정된 순서에 위치한 레코드만 가져오고자 할 때 사용된다. 위 쿼리는 다음과 같은 순서로 실행된다. ORDER BY id DESC: 일반적으로 최신에서 과거순으..

synchronized vs Pessimistic Lock vs Distributed Lock DB의 무결성을 보장하기 위해서는 다양한 방법이 있다. 물론 synchronized는 적합한 방법은 아니지만 왜 적합하지 않은지에 대해 살펴보고, 그 뒤 비관적 락(Pessimistic Lock)과 분산락(Distributed Lock)을 통해 성능 비교를 해보자. 재고 차감 로직을 통한 DB 부정합 문제 살펴보기 위 ProductService는 주문 관련 비즈니스 로직 중 하나로 "상품 조회 -> 상품의 재고 차감 가능 여부 확인 -> 재고 차감"의 순서로 이루어지는 로직이다. 해당 비즈니스 로직을 통해서 어떻게 DB 부정합 문제가 발생하게 되는지 테스트 코드를 작성해보자. 위 테스트 코드는 한 번에 100개..

Nginx와 WAS의 로깅 식별자(request_id) 공유하기 현재 프로젝트의 서비스 환경은 위 그림과 같다. WAS만 사용하는 것이 아니라 Nginx와 같은 Web Server를 앞단에 두고 사용하고 있다. 따라서 Nginx 로그와 WAS 로그를 함께 봐야하는 경우가 많은데, 이때 Nginx와 WAS가 동일한 request_id를 공유하면 로그 파악이 매우 용이해진다. Nginx 설정 Nginx에서는 제공하는 변수 중 하나로 $request_id가 있다. 이 변수는 각 HTTP 요청에 대해 고유한 식별자를 생성하여 주로 로깅이나 디버깅 목적으로 사용된다. 이 변수는 ngx_http_core_module 모듈에서 제공되며 32개의 16진수 문자열로 각 HTTP 요청이 도착하면 자동으로 할당된다. Log..

Blue/Green 방식으로 서비스 중단없이 배포하기 어플리케이션을 배포하는데 있어 Rolling 배포, Blue/Green 배포, 그리고 Canary 배포와 같은 다양한 배포 전략들이 있다. 각 전략의 특징과 장담점을 살펴보고 프로젝트에 어떤 전략을 선택할지 고민해보려고 한다. Rolling 배포 롤링 배포는 각 서버를 한 개씩 새로운 버전으로 (점진적) 배포하는 방법을 말한다. 즉, 위 그림처럼 기존 버전에서 새 버전으로 서비스를 전환하는 과정을 순차적으로 진행한다. 서비스 중인 인스턴스 하나를 로드밸런서에 라우팅하지 않도록 한 뒤 새 버전을 적용하여 다시 라우팅하는 방식으로 구성된 자원을 그대로 유지한 채로 무중단 배포가 가능하므로 관리가 편하다는 장점이 있지만 배포가 진행되는 동안 구버전과 신버전..

Jenkins으로 CI/CD 구축하기다른 분들과 협업 프로젝트를 진행하면서 요구사항은 계속 바뀔 수 있기 마련이다. 하지만 폭포수 모델처럼 분석, 설계 영역에 상당한 시간이 할당되고, 해당 작업이 끝난 후에는 개발 시 어떤 추가나 수정도 허용되지 않으면서 전체 개발이 끝난 후에 통합이 진행된다면 그 결과로 수 많은 통합 이슈가 가장 마지막 단계에서 발생하는 문제가 발생할 수 있다.따라서 현재 진행하는 이커머스 프로젝트는 충분히 잦은 요구사항이 발생할 수 있는 서비스이기 때문에 애자일처럼 빠르고 유연하며 조금씩 발전되는 소프트웨어 개발을 통해 목표를 계속 수정해나가는 방법론을 선택했다. 따라서 하나 혹은 그 이상의 기능을 구현하고 테스트, 빌드, 배포하는 것이 자주 발생하기 때문에 이러한 반복적인 개발 사..

세션은 어느 계층에서 처리해야 할까? 세션을 통해 사용자 관련 로그인, 로그아웃 기능을 구현하고 있을 때 현재 어떤 문제가 있는지에 대해서 살펴보고, 리팩토링해보자! 리팩토링 전 코드 먼저 리팩토링을 하기 전에 로그인은 어떻게 동작하고 있는지에 대해서 살펴보자. @MemberLoginCheck @Target(ElementType.METHOD) @Retention(value = RetentionPolicy.RUNTIME) public @interface MemberLoginCheck { } 먼저, @MemberLoginCheck 어노테이션을 생성해줬다. Controller 레이어에서 @MemberLoginCheck 어노테이션이 붙어있는 메서드는 실행 전에 로그인 검증이 일어날 수 있도록 Aspect 클래스..

Redis로 Session Store 적용하기 로그인 방식에 대한 고찰 : JWT vs Session JWT vs Session 보통 로그인 방식을 어떤 방식으로 구현했는지 보면 JWT를 사용한 토큰 기반 인증방식 또는 Session을 사용한 세션 기반 인증방식이 있다. 그리고 주위 개발자분들께 회사에서 어떠한 oneny.tistory.com 위 게시글에서 JWT 방식과 Session 방식 중 Session 방식을 선택했다. 세션은 간단히 말하면 서비스를 사용하는 클라이언트의 상태 정보를 의미하고, 어플리케이션은 현재 서비스에 로그인되어 있는 클라이언트가 누구인지, 그 클라이언트가 어떤 활동을 하고 있는지 저장하고 있으며, 유저가 서비스를 떠나면 세션 스토어에서 유저의 정보는 삭제한다. 하지만 Sessi..

JWT vs Session 보통 사용자 인증 방식을 어떤 방식으로 구현했는지 보면 JWT를 사용한 토큰 기반 인증방식 또는 Session을 사용한 세션 기반 인증방식이 있다. 그리고 주위 개발자분들께 회사에서 어떠한 방식을 쓰는지 여쭤보면 JWT 방식을 사용하고 있다고 있다고 한다. 근데 왜 JWT를 사용하는지에 대해서는 쉽게 말씀해주시지 못하는데 이번 기회를 통해 각 방식의 장단점에 대해 비교해보고, 현재 하고 있는 프로젝트에 어떤 방식을 선택해 사용할지 고민해보자. JWT(Json Web Token) JSON Web Token(JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. Th..
- Total
- Today
- Yesterday
- spring session
- 트랜잭션
- EKS
- Java
- postgresql
- 넥스트스탭
- 구름톤 챌린지
- socket
- spring webflux
- redis session
- Synchronized
- 람다
- transaction
- mdcfilter
- jvm 메모리 구조
- Redisson
- pessimistic lock
- nginx configuration
- 구름톤챌린지
- mysql
- 분산 락
- nginx
- 비관적 락
- sql
- TDD
- 낙관적 락
- Kafka
- 카프카
- annotation
- NeXTSTEP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |