본문 바로가기

Spring boot

(33)
동시성 관리하기 3탄) Redis - Lettuce, Redisson DB가 스케일 아웃된 상황에서 동시성 관리하기 !동시성 관리하기 2-2탄에 이어서, 오늘은 Redis를 이용해 보겠습니다.  우선 같은 데이터 셋을 공유하는 분산 DB 상황에서는 아래 사진과 같은 상황이 벌어질 수 있습니다.여러 요청들이 한 자원에 대해서 공유할 때, 각 분산 DB의 동기화가 여러 요청의 동기화 속도를 못 따라 가는 상황이 발생합니다.이에 대해 데이터 정합성은 깨지게 되고, 데이터 동시성 문제가 발생하게 됩니다.예를 들어, 위와 같이 한 번에 여러 구매 요청이 들어왔을 경우 수량이라는 자원을 동시에 사용할 경우 여러 수량의 커밋되거나 롤백되는 수량의 동기화가 다른 서버가 따라가지 못해서 정합성이 깨지고, 동시성 문제가 발생할 수 있습니다. 이를 방지하기 위해,위 사진과 같이, 공유 자원인..
동시성 관리하기 2-2탄) Database 레벨 - User-Level Lock (Named Lock) 지난 게시글에서 살펴본 낙관적 Lock과 비관적 Lock은 분산 서버에서도 동시성을 보장했습니다. 이제 비관적 Lock과 비슷한 Named Lock에 대해 살펴보겠습니다.  User-Level Lock (Named Lock)User-Level Lock은 MySQL 데이터베이스에서 제공해주는 분산락입니다. 데이터베이스를 사용하는 사용자가 특정 문자열에 Lock을 걸 수 있는 기능이며아래와 같은 함수를 제공합니다.  지금부터 Locking Functions에 대해 알아보겠습니다. GET_LOCK(str, timeout)주어진 str(문자열)에 timeout동안 Lock 획득을 시도한다. (str의 길이는 최대 64글자)= 이미 다른 세션에서 Lock을 획득한 경우, Lock 획득을 위해 timeout만큼 ..
동시성 관리하기 2-1탄) Database 레벨 - 낙관적 Lock, 비관적 Lock 이전 글(https://baeji-develop.tistory.com/127)을 보면 Spring은 멀티 스레드이기 때문에 Application 레벨에서 해결할 수 없는 동시성 문제가 있습니다. 문제 한 메서드에 대해 Lock을 걸어도 단일 서버에서 서로 다른 두 메서드가 한 자원에 동시에 접근하면 나타나는 문제. 한 메서드에 대해 Lock을 걸어도 분산 서버에서는 각 서버의 동일한 매서드를 실행 중인 스레드가 한 자원에 동시 접근하면 나타나는 문제.  등등 이외 여러 문제가 발생할 수 있다고 생각되어 Database 레벨인 낙관적 Lock과 비관적 Lock에 대해 고민해보려고 합니다.* 낙관적 Lock을 Application 레벨이라고 하기도 하는데, 필자는 낙관적 Lock에 DB가 사용되기 때문에 D..
동시성 관리하기 1탄) Application 레벨 - synchronized, ConcurrentHashMap * 이 글은 정보제공을 우선으로 하여 구어체를 사용합니다. 🥹Spring은 멀티 스레드 방식이기 때문에 성능은 좋지만한 자원에 대해 여러 스레드가 접근할 시, 동시성 문제가 발생할 수 있다.  예를 들어, 제한 인원이 100명으로 정해져 있는 한 그룹에 참여하고 싶을 때, 동시에 100명이 참여 신청을 한다면 최종적으로 참여 인원은 100명 이하 일 것이다.이 문제의 원인은 Race condition이 발생한 것이다. * Race condition이란?   두 개 이상의 프로세스(혹은 스레드)들이 하나의 자원에 접근하여 변경하는 경우, 접근 순서에 따라 실행 결과가 달라지는 현상 참여 인원 뿐만 아니라 예금 인출이나 재고 처리 등, 동시성 처리는 매우 중요한 과정이다.지금부터 자원의 신뢰성과 안정성을..
@Builder, @AllArgsConstructor, @NoArgsConstructor의 관계 보통 Entity를 생성할 때, @Builder, @AllArgsConstructor, @NoArgsConstructor 를 모두 사용한다. 이유는 무엇일까? @AllArgsConstructor @AllArgsConstructor는 전체 필드가 들어갈 수 있도록 전체 생성자를 생성해주는 어노테이션이다. @NoArgsConstructor @NoArgsConstructor는 기본 생성자를 생성해주는 어노테이션이다. 위 사진과 같이 (access = AccessLevel.PROTECTED)를 설정해주면 필드값이 (단 하나라도) 없이 생성해줄 경우, 객체 생성을 막아주어 무분별한 또는 불완전한 객체 생성을 막을 수 있다. @Builder @Builder는 @NoArgsConstructor에 유연함을 넣어 필요한..
[Spring Security] Security Config 적용법 (Jwt Filter와 관계) public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(requests -> requests.requestMatchers("/signUp", "/signIn", "/reissue").permitAll() ) } } "저 주소들은 permitAll이니까 모든 요청을 허용한다." ( = jwt 검사를 안 한다. -> jwt filter 검증을 거치지 않는다.)라고 생각했다. 하지만 저 주소에 요청을 보내도 filter에서 jwt null exception이 잡혔습니다. 그래서 알게된,, 저 주소로 요청..
[Spring Security] JWT사용할 때 filter, Interceptor 차이 실행 순서: Filter → Interceptor → AOP → Interceptor → Filter Filter와 Interceptor의 간단한 차이 Filter Interceptor - Filter는 Dispatcher Servlet의 밖에 위치함. - Web Context에 존재하며 Spring context와 무관함. - Interceptor는 Dispatcher Servlet 안에 위치함. - Spring context에 존재, 모든 Spring Bean에 접근 가능 - Request, Response 조작 가능 (여기서 조작이란 Request 와 Response 의 내부 상태를 변경한다는 것이 아닌 다른 객체로 바꿔친다는 의미) - Request, Response 조작 불가능 - Applica..
Entity의 Id 직접 주입 시, select 쿼리가 발생하는 이유와 isNew()오버라이딩하기 (성능 개선) 문제 발생 로직은 1. 사람 정보를 주는 외부 api 호출 시, 응답으로 Id와 그 외 정보를 받는다. 2. 이 Id를 그대로 user entity의 id로 사용하고 그 외 정보와 함께 저장한다. 입니다. 따라서, 원인은 id를 @generatedValue 으로 저장하지 않고 우리가 직접 값을 넣어줄 경우입니다. 문제는 엔티티를 저장할 때, select query가 다량으로 발생하는 것이죠. 100개를 저장했는데 100개의 select query + 100개의 insert query가 발생하네요! 왜인지 디버깅해서 천천히 뜯어보겠습니다. 동작 과정 우리는 새로운 데이터를 저장해주지만 save 호출 시, isNew()가 false이기 때문에 persist가 아닌 merge로 동작하고 있습니다. 왜 isNe..