개요 🔖
이유 🤔
- 스룸 프로젝트에서는 영상 정보를 불러오기 위해 Youtube Data API를 사용합니다. 영상 API는 약 100ms의 응답시간이 존재하는데, 이 시간동안 다른 유저가 같은 영상을 조회하게 되면 이미 요청된 영상 API를 또다시 호출하는 문제가 발생합니다.
- 하루 100,000으로 한정되어 있는 Youtube Data API 를 같은 영상조회로 낭비하게 됩니다.
- 캐시를 사용하더라도 영상정보가 캐시되기 전까지는 전까지는 같은 요청을 보낼 수 밖에 없습니다.
- 응답시간 안에 요청을 보내는 횟수조차 제어할 수 없습니다.
- 해당 문제에 대해 고려된 해결방안은 다음과 같습니다.
- 자바 Atomic
- 여러 스레드가 공유변수를 안정적으로 수정해야 하는 상황에 쓰일 수 있습니다.
- AtomicReference를 사용해서 영상코드 Set을 관리할 수 있습니다.
- 하지만 하나의 서버에서만 적용되며, 서버가 늘어나게 되면 동시성 문제를 피할 수 없습니다.
- 카프카
- 카프카(Kafka)란 실시간으로 스트리밍 데이터를 수집하고 처리하는 데 최적화된 분산 데이터 스토어입니다. (모든 데이터 흐름을 중앙에서 관리)
- 레코드 스트림 게시 및 구독
- 레코드가 생성된 순서대로 레코드 스트림을 효과적으로 저장
- 레코드 스트림을 실시간 처리
- 따라서 분산환경에 특화된 카프카를 사용해 처리중인 영상정보 API를 중복시키지 않을 수 있습니다.
세부 사항 📃
Atomic의 set(), lazySet() 차이
- set은 변수의 값을 즉시 변경합니다. 사용한 후 원자변수에 엑세스하는 모든 스레드가 업데이트 된 값을 보게 됩니다. (메모리 가시성 보장)
- lazySet()은 변경된 값이 다른 스레드에 표시되는 것이 지연될 수 있습니다.
- 메인 메모리에 대한 쓰기 횟수를 줄여 어플리케이션 성능을 향상시킬 수 있습니다.
메모리 가시성(Memory Visibility), 메모리 장벽(Memory Barrier)
- 메모리 가시성 : 하나의 스레드에서 수행한 변수 업데이트가 다른 스레드에 표시되는지 여부입니다.
- 리테일 데이터를 사용하는 이유는 재배치(Reordering) 때문인데, JVM이 프로그램 코드가 실행되는 순서를 바꿔 실행하는 경우가 있다는 것이다.
- CPU cache를 사용하지 않고, 메인 메모리에서만 변수값을 참조하도록 synchronized, volitile 을 사용할 수 있다. (volitile로 동시성이 보장되는 것은 아니며, 공유객체에 대한 동기화 처리를 synchronized로 해줘야한다.)
- 메모리 장벽 : 메모리 작업에 대한 순서 제약 조건을 제공하는 매커니즘입니다.
- 로드 장벽 : 스레드가 변수의 최신 값을 읽을 수 있도록 보장합니다. 이는 다른 스레드에 의해 수정된 변수의 값을 캐시에 반영하기 위해 사용됩니다.
- 스토어 장벽 : 스레드에 의해 변경된 변수의 값을 다른 스레드가 볼 수 있도록 메인 메모리에 즉시 반영하도록 합니다.
- volatile로 메모리 장벽을 설정할 수 있습니다.
메시지 큐 (Message Queue, MQ)
- producer : 정보 제공자
- consumer : 정보 수신자
- MQ : 데이터 임시저장 및 consumer에게 전달
MQ의 장점
- 비동기: 데이터 임시 저장소가 있으니 나중에 처리가능
- 낮은 결합도 : 어플리케이션과 분리
- 탄력성 : 어플리케이션에 장애가 발생하더라도 데이터는 지속하여 남아있음
- 보장성 : 데이터가 결국 consumer에게 전달됨
Pub/Sub 모델 <-> Point to Point
- 이벤트(메시지)를 발생시키는 Publisher가 존재하고, Publisher는 Topic에 이벤트를 전송합니다.
Kafka 요소
Zookeeper: Kafka 의 클러스터 메타데이터와 상태 정보를 저장하고 관리하는 분산 코디네이터 시스템입니다.
Broker: Kafka 클러스터를 구성하는 개별 서버 노드로, 메시지 수신, 저장, 분배 등의 역할을 수행하는 Kafka 서버입니다.
Topic: Kafka 에서 데이터를 주고받는 주제를 나타내는 단위로, 관련된 메시지들이 그룹화되는 카테고리 또는 피드입니다.
Partition: Kafka Topic 을 분할하여 여러 파티션으로 나누는 것으로, 각 파티션은 순서가 있는 메시지 스트림을 포함하며 별도의 오프셋을 가지고 있습니다.
Offset: Kafka Topic 내에서 메시지의 위치를 식별하는 고유한 식별자로, Consumer 가 읽은 메시지의 위치를 추적하고 관리하는데 사용됩니다.
Producer: Kafka 에 데이터를 생성하여 특정 Topic 으로 보내는 역할을 하는 애플리케이션 또는 컴포넌트입니다.
Consumer: Kafka 로부터 데이터를 소비하는 역할을 하는 애플리케이션 또는 컴포넌트로, Topic 의 메시지를 읽고 처리합니다. Consumer 는 Consumer Group 에 속할 수 있으며, 메시지를 병렬로 처리할 수 있습니다.
스룸에서 Kafka를 사용한다면?
- Producer는 영상정보를 제공하는 Youtube Data API를 다루는 컴포넌트일 것입니다. 이는 Topic에 데이터를 전송할 것입니다.
- Consumer는 영상정보를 필요로 하는 어플리케이션일 것입니다. 같은 영상정보를 원하는 Consumer들은 같은 Consumer Group에 속하게 될 것입니다.
- Topic은 Video 또는 Playlist가 될것입니다.
- 메시지 큐(Topic)에 영상정보가 쌓이게 되며, 해당 영상을 필요로 하는 Consumer Group에 데이터를 전송합니다.
개요 🔖
이유 🤔
- 해당 문제에 대해 고려된 해결방안은 다음과 같습니다.
- 여러 스레드가 공유변수를 안정적으로 수정해야 하는 상황에 쓰일 수 있습니다.
- AtomicReference를 사용해서 영상코드 Set을 관리할 수 있습니다.
- 하지만 하나의 서버에서만 적용되며, 서버가 늘어나게 되면 동시성 문제를 피할 수 없습니다.
- 카프카(Kafka)란 실시간으로 스트리밍 데이터를 수집하고 처리하는 데 최적화된 분산 데이터 스토어입니다. (모든 데이터 흐름을 중앙에서 관리)
세부 사항 📃
Atomic의 set(), lazySet() 차이
메모리 가시성(Memory Visibility), 메모리 장벽(Memory Barrier)
메시지 큐 (Message Queue, MQ)
MQ의 장점
Pub/Sub 모델 <-> Point to Point
Kafka 요소
Zookeeper: Kafka 의 클러스터 메타데이터와 상태 정보를 저장하고 관리하는 분산 코디네이터 시스템입니다.
Broker: Kafka 클러스터를 구성하는 개별 서버 노드로, 메시지 수신, 저장, 분배 등의 역할을 수행하는 Kafka 서버입니다.
Topic: Kafka 에서 데이터를 주고받는 주제를 나타내는 단위로, 관련된 메시지들이 그룹화되는 카테고리 또는 피드입니다.
Partition: Kafka Topic 을 분할하여 여러 파티션으로 나누는 것으로, 각 파티션은 순서가 있는 메시지 스트림을 포함하며 별도의 오프셋을 가지고 있습니다.
Offset: Kafka Topic 내에서 메시지의 위치를 식별하는 고유한 식별자로, Consumer 가 읽은 메시지의 위치를 추적하고 관리하는데 사용됩니다.
Producer: Kafka 에 데이터를 생성하여 특정 Topic 으로 보내는 역할을 하는 애플리케이션 또는 컴포넌트입니다.
Consumer: Kafka 로부터 데이터를 소비하는 역할을 하는 애플리케이션 또는 컴포넌트로, Topic 의 메시지를 읽고 처리합니다. Consumer 는 Consumer Group 에 속할 수 있으며, 메시지를 병렬로 처리할 수 있습니다.
스룸에서 Kafka를 사용한다면?