본문 바로가기

전체 글

(225)
분산 환경에서 데이터 일관성 확보하기 0. 개요프로젝트에서 PT 수업 예약 API를 개발하며 고려한 점들을 정리하고자 한다. PT 수업 예약 요청은 Pt 서버와 Auth 서버를 거치는 분산 환경에서 처리된다. 단일 서버에서 모든 로직을 수행한다면 구현이 간단하지만, 여러 서버를 거치게 되면 트랜잭션의 원자성 및 데이터 일관성을 유지하기 위해 다양한 상황을 고려해야 한다. 이 글은 분산 환경에서 어떤 것들을 고려했는지 그 고려 사항들을 정리한 글이다.1. 분산 환경에서 로컬 트랜잭션들 간 원자성 보장하기분산 환경에서의 원자성분산 환경에서는 여러 개의 로컬 트랜잭션들이 묶여 하나의 논리적인 트랜잭션을 구성한다. 그렇기 때문에 로컬 트랜잭션들이 순차적 또는 병렬로 실행되면서 원자성이 깨지는 문제가 발생할 수 있다. 예를 들어, 마이크로서비스 A..
Transactional Outbox Pattern을 이용한 분산 환경에서의 결과적 일관성 확보 문제 상황사용자 정보를 변경한 후 커밋되었지만 메시지가 발행되지 않는 경우메시지를 발행했지만 사용자명 변경 내역이 롤백된 경우다음과 같이 컨트롤러에서 userService를 호출해서 사용자 정보를 변경하여 DB에 커밋한 후 kafkaService를 호출해서 변경된 사용자 정보를 카프카 메시지로 발행한다고 가정하자.@RestController@RequiredArgsConstructorpublic class UserController { private final JwtUtils jwtUtils; private final UserService userService; private final KafkaService kafkaService; @PutMapping("/edit") publ..
카프카란 무엇인가? 카프카의 탄생 배경카프카는 미국의 대표적인 소셜 네트워크 서비스인 링크드인에서 처음 시작된 기술로, 링크드인 서비스가 급속도로 성장하면서 발생하게 된 여러 이슈들을 해결하기 위해 탄생했다. 링크드인 서비스가 성장하면서 어떤 상황에서 어떤 새로운 시스템에 대한 개발 요구가 높아졌길래 카프카가 탄생하게 된 것일까? 다음 그림은 카프카가 개발되기 전 링크드인의 시스템 구성도이다.  카프카 등장 전에는 각 서비스가 엔드투엔드로 연결되어 있었다. 이러한 엔드투엔드 연결 방식의 아키텍처는 많은 문제점이 있었다.첫 번째로, 통합된 전송 영역이 없으니 시스템 복잡도가 증가할 수밖에 없다. 따라서 문제를 발견하기 위해서는 이와 관련된 여러 데이터 시스템을 확인해야 했다.두 번째로, 데이터 파이프라인 관리의 어려움이다. ..
토큰(JWT) 인증 방식을 좀 더 안전하게 설계하기 JSON Web Token의 약자인 JWT는 온라인 네트워크에서 정보를 안전하게 통신할 때 사용하는 인터넷 표준 토큰이다. JWT는 인증, 정보 교환 등 다양한 용도에 사용된다. 이때 주고받는 정보를 클레임(Claim)이라고 하고, 클레임의 집합은 JSON 객체로 표현한다.1. JWT의 두 가지 유형JWT에는 두 가지 유형이 있다. 더 널리 사용되는 첫 번째 방식은 JWS(JSON Web Signature)이다. JWS 방식을 사용하면 클레임의 내용을 누구나 읽을 수 있지만, 서명되어 있기 때문에 데이터의 무결성이 보장된다. 두 번째 방식인 JWE(JSON Web Encryption)이다. JWE에서는 클레임 자체를 암호화한다. 그래서 복호화 방법을 알고 있어야만 페이로드를 읽을 수 있다. 보안 측면에서..
[백준] 1058. 친구 https://www.acmicpc.net/problem/10581. 플로이드워셜로 푸는 방법플로이드워셜은 N개의 노드에서 N개의 노드로 이동하는데 걸리는 최단 거리(비용)을 구할 수 있다. 즉, 각 노드에서 다른 N-1개의 노드로 몇 번의 이동으로 도달 가능한지 구한 후(=사람 a와 사람 b의 관계), 1번 또는 2번으로 이동이 가능하면 2-친구 관계이므로 카운트해주면 된다.import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.*;public class Main { static BufferedReader br = new BufferedReader(new Inpu..
스프링 스케줄러(@Scheduled) 사용 시 주의사항 1. 여러 스케줄링 작업이 있을 때 싱글 스레드로 인한 문제* 참고: https://olsohee.tistory.com/239 스프링은 스케줄링 작업을 위한 TaskScheduler라는 인터페이스를 제공하고, 구현체로는 다음 두가지가 사용된다.가상 스레드가 활성화된 경우(Java 21 이상 및 spring.threads.virtual.enabled가 true로 설정된 경우), SimpleAsyncTaskScheduler가상 스레드가 활성화되지 않은 경우, ThreadPoolTaskScheduler그리고 ThreadPoolTaskScheduler는 기본적으로 하나의 스레드를 사용하며, spring.task.scheduling을 통해 설정 값을 변경할 수 있다. If virtual threads are en..
레디스에서 다중 명령에 대한 원자성을 보장하는 방법 레디스는 싱글 스레드로 동작하므로 동시성 제어를 위한 복잡한 설계와 오버헤드가 적다. 그러나 싱글 스레드는 parallel 할 수 없는 것이지 concurrent 할 수 있다. 즉, 여러 레디스 클라이언트가 있고, 각 클라이언트가 여러 개의 명령을 한 번에 보낸다면, 레디스의 싱글 스레드는 여러 클라이언트들의 명령을 번갈아 하나씩 실행하게 되며 동시성 문제가 발생할 수 있다. 이를 방지하기 위해 크게 Redis Transaction과 Lua Script 2가지를 사용할 수 있다.Redis Transaction트랜잭션은 주로 관계형 데이터베이스에서 많이 쓰이는 용어인데, 레디스에서도 트랜잭션을 사용할 수 있다. 레디스에서 트랜잭션을 사용하면 여러 개의 커맨드에 대해 원자성이 보장된다. 따라서 concurr..
Redis를 통한 좋아요 수 동시성 문제 해결 앞서 프로젝트에서 게시글 조회 성능을 위해 반정규화를 적용했다. (반정규화를 통한 조회 성능 개선) 그런데 좋아요 수를 의미하는 likeCount 필드를 추가함으로써 동시성 문제가 발생한다. 예를 들어, 멀티 스레드 환경에서 두 명의 사용자가 동시에 게시글 좋아요 요청 시, 좋아요 수가 0에서 1 그리고 1에서 2로 증가하는 것이 아니라, lost update가 발생하며 0에서 1로 업데이트 될 수 있다. 이에 대한 해결 과정은 다음과 같다.1. 자바 락가장 기본적으로 자바에서 제공하는 synchornized, ReentrantLock과 같은 락이 있다. 그러나 이는 애플리케이션 단의 락이기 때문에 멀티 인스턴스 환경에서는 동시성 제어가 불가하다.2. JPA 낙관적 락JPA가 제공하는 낙관적 락은 엔티티..