Skip to content

About Concurrency #155

Description

@D-w-nJ

개요 🔖

  • 동시성 문제에 대해 알아보려 합니다.

이유 🤔

  • 스룸 프로젝트에서는 영상 정보를 불러오기 위해 Youtube Data API를 사용합니다. 영상 API는 약 100ms의 응답시간이 존재하는데, 이 시간동안 다른 유저가 같은 영상을 조회하게 되면 이미 요청된 영상 API를 또다시 호출하는 문제가 발생합니다.
    • 하루 100,000으로 한정되어 있는 Youtube Data API 를 같은 영상조회로 낭비하게 됩니다.
    • 캐시를 사용하더라도 영상정보가 캐시되기 전까지는 전까지는 같은 요청을 보낼 수 밖에 없습니다.
    • 응답시간 안에 요청을 보내는 횟수조차 제어할 수 없습니다.

- 해당 문제에 대해 고려된 해결방안은 다음과 같습니다.
  1. 자바 Atomic
    - 여러 스레드가 공유변수를 안정적으로 수정해야 하는 상황에 쓰일 수 있습니다.
    - AtomicReference를 사용해서 영상코드 Set을 관리할 수 있습니다.
    - 하지만 하나의 서버에서만 적용되며, 서버가 늘어나게 되면 동시성 문제를 피할 수 없습니다.
  2. 카프카
    - 카프카(Kafka)란 실시간으로 스트리밍 데이터를 수집하고 처리하는 데 최적화된 분산 데이터 스토어입니다. (모든 데이터 흐름을 중앙에서 관리)
    • 레코드 스트림 게시 및 구독
    • 레코드가 생성된 순서대로 레코드 스트림을 효과적으로 저장
    • 레코드 스트림을 실시간 처리
  • 따라서 분산환경에 특화된 카프카를 사용해 처리중인 영상정보 API를 중복시키지 않을 수 있습니다.

세부 사항 📃

Atomic의 set(), lazySet() 차이

  • set은 변수의 값을 즉시 변경합니다. 사용한 후 원자변수에 엑세스하는 모든 스레드가 업데이트 된 값을 보게 됩니다. (메모리 가시성 보장)
  • lazySet()은 변경된 값이 다른 스레드에 표시되는 것이 지연될 수 있습니다.
    • 메인 메모리에 대한 쓰기 횟수를 줄여 어플리케이션 성능을 향상시킬 수 있습니다.

메모리 가시성(Memory Visibility), 메모리 장벽(Memory Barrier)

  • 메모리 가시성 : 하나의 스레드에서 수행한 변수 업데이트가 다른 스레드에 표시되는지 여부입니다.
    • 리테일 데이터를 사용하는 이유는 재배치(Reordering) 때문인데, JVM이 프로그램 코드가 실행되는 순서를 바꿔 실행하는 경우가 있다는 것이다.
    • CPU cache를 사용하지 않고, 메인 메모리에서만 변수값을 참조하도록 synchronized, volitile 을 사용할 수 있다. (volitile로 동시성이 보장되는 것은 아니며, 공유객체에 대한 동기화 처리를 synchronized로 해줘야한다.)
  • 메모리 장벽 : 메모리 작업에 대한 순서 제약 조건을 제공하는 매커니즘입니다.
    • 로드 장벽 : 스레드가 변수의 최신 값을 읽을 수 있도록 보장합니다. 이는 다른 스레드에 의해 수정된 변수의 값을 캐시에 반영하기 위해 사용됩니다.
    • 스토어 장벽 : 스레드에 의해 변경된 변수의 값을 다른 스레드가 볼 수 있도록 메인 메모리에 즉시 반영하도록 합니다.
    • volatile로 메모리 장벽을 설정할 수 있습니다.

메시지 큐 (Message Queue, MQ)

image
  • producer : 정보 제공자
  • consumer : 정보 수신자
  • MQ : 데이터 임시저장 및 consumer에게 전달

MQ의 장점

  • 비동기: 데이터 임시 저장소가 있으니 나중에 처리가능
  • 낮은 결합도 : 어플리케이션과 분리
  • 탄력성 : 어플리케이션에 장애가 발생하더라도 데이터는 지속하여 남아있음
  • 보장성 : 데이터가 결국 consumer에게 전달됨

Pub/Sub 모델 <-> Point to Point

image
  • 이벤트(메시지)를 발생시키는 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를 사용한다면?

  1. Producer는 영상정보를 제공하는 Youtube Data API를 다루는 컴포넌트일 것입니다. 이는 Topic에 데이터를 전송할 것입니다.
  2. Consumer는 영상정보를 필요로 하는 어플리케이션일 것입니다. 같은 영상정보를 원하는 Consumer들은 같은 Consumer Group에 속하게 될 것입니다.
  3. Topic은 Video 또는 Playlist가 될것입니다.
  4. 메시지 큐(Topic)에 영상정보가 쌓이게 되며, 해당 영상을 필요로 하는 Consumer Group에 데이터를 전송합니다.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions