데이터 엔지니어 기술 블로그

[회사별 사례] 카프카(Kafka) 적용 사례(라인, 링크드인) 본문

데이터 엔지니어링

[회사별 사례] 카프카(Kafka) 적용 사례(라인, 링크드인)

jun_yeong_park 2021. 3. 10. 16:08
반응형

카프카란?

카프카

- 실시간으로 게시, 구독, 저장 및 처리할 수 있는 분산 데이터 스트리밍 플랫폼입니다.

- 여러 소스에서 데이터 스트림을 처리하고, 여러 사용자에게 전달합니다.

- FIFO(First In First Out)큐를 사용합니다. 

 

마이크로서비스에서의 카프카

- 다른 개발팀의 데이터를 스트리밍하여 데이터 스토어를 채우면, 데이터를 여러 팀과 공유할 수 있습니다.

 

라인

사용하는 이유

- LINE 메세지 개발 서버 팀에서 복잡해진 아키텍처를 간소화하기 위한 중간 레이어로 사용하고자 채택했습니다.

 

사용 방식

크게 아래의 두가지로 구성됩니다.

1. 분산 큐잉 시스템으로 사용하는 방법

   - 웹 서버에서 비싼 비용의 작업을 처리해야 할 때 백그라운드의 태스크 프로세서에 요청하기 위한 큐를 사용하는 경우

2. 데이터 허브 방법

   - 어떤 서비스에서 데이터가 업데이트 되었을 때, 다른 여러 서비스에 전파하기 위한 허브로 사용하는 방법

   - 데이터에 접근하는 수단을 통일시켜 단순화할 수 있습니다. 

출처: https://engineering.linecorp.com/ko/blog/how-to-use-kafka-in-line-1/

 

사용량

1. 매일 2500억 건(210TB)이 넘는 레코드가 입력됩니다.

2. 1초에 4기가가 넘는 데이터가 입력되는 경우도 있습니다.

 

운영 환경에서 발생한 문제

  • 데이터 입력할 때 사용되는 Produce라는 API의 사용량이 50~100배까지 악화된 경우가 있었습니다.

원인 조사

  1. Kafka가 요청을 처리할 때 크게 두 개의 스레드 레이어를 사용합니다.
    • 네트워크 스레드: 클라이언트와 I/O를 담당하는 스레드입니다. 클라이언트 소켓에 도착한 요청을 가져와서 요청 객체를 생성하고 준비된 응답 객체를 클라이언트에 입력하는 역할을 합니다. 이벤트 기반 비동기 I/O 처리를 수행합니다.
    • 요청 핸들러 스레드: 네트워크 스레드가 가져온 요청을 처리해서 필요한 응답 객체를 네트워크 스레드에 반환합니다.
  2. 전체적인 순서는 다음과 같습니다.
    1. 클라이언트 소켓에 요청이 도착
    2. 네트워크 스레드가 요청 객체 생성
    3. 요청 객체를 큐에 저장(브로커 내에만 하나만 존재)
    4. 요청 핸들러 스레드가 요청을 가져옴
    5. 가져온 요청을 처리하고 응답 객체를 생성함
    6. 응답 개체를 응답 큐에 저장함
    7. 네트워크 스레드가 응답 큐에서 응답을 가져감(네트워크 스레드 하나당 응답 큐 하나씩 존재)

원인 검증

 

네트워크 스레드가 처리를 수행하는 과정인 이벤트 루프 내의 특정 처리에서 차단된 경우

  1. Fetch
    1. 로컬 디스크에 저장되어 있는 topic의 데이터를 클라이언트 소켓에 복사해야 하는 과정이 있다.
    2. 리눅스의 sendfile이라는 시스템 콜을 이용하는데 메모리에 복사하지 않고 바로 소켓으로 넘겨주기 때문에 효율적이라고 알려져있다. 페이지 캐시가 존재할 경우 매우 짧은 시간 내에 처리가 된다. 하지만 디스크에서 가져와야 할 경우 오래 걸린다.
      1. 페이지 캐시란 리눅스 파일 I/O 성능 향상을 위해 메모리 영역을 만들어서 사용하는데, 한 번읽은 파일을 여기에 저장시켰다가 다시 읽게 되면 여기에서 가져옵니다.
  2. 그 외 API 응답 처리 방식
    1. 응답 큐에서 응답 객체를 취득한 시점에 클라이언트 소켓에 입력해야 할 데이터가 모두 메모리에 저장되어 있습니다.
    2. 네트워크 스레드는 저장되어 있는 클라이언트를 소켓에 그냥 복사하면 됩니다.

 

조사 결과

리눅스의 sendfile 시스템 콜은 대부분 매우 짧은 시간내에 해결이 되지만 디스크에서 가져와야 할 경우 오래 걸립니다.

그럴 경우 네트워크 스레드의 이벤트 루프가 차단됩니다.

 

해결 방법

sendfile이 네트워크 스레드 내에서 호출될 경우 반드시 페이지 캐시에 존재하도록 브로커를 개선하는 방법

  1. 디스크 데이터 로딩을 요청 핸들러 스레드 쪽으로 옮깁니다.
  2. 요청 핸들러 스레드는 하나의 큐를 전체가 polling 하는 모델이기 때문에 차단이 발생해도 다른 스레드에 영향을 주지 않습니다.
  3. sendfile을 호출하면서 목적지를 /dev/null로 설정합니다. 리눅스 커널은 /dev/null로 목적지를 호출할 때는 메모리 복사를 수행하지 않게 구현되어 있습니다. 디스크에 페이지 캐시로는 데이터가 로딩되지만 메모리 복사는 진행되지 않습니다.

 

 

 

 

높은 신뢰성과 성능 확보

 

요청 수 제어하기 - 데이터의 양보다 요청수를 제어하는 것이 중요합니다. 

  • Kafka에는 캐시 레이어가 없습니다.
  • batching 기능을 사용하여 여러 레코드를 하나로 묶어서 전달할 수 있도록 합니다.
  • 요청 쿼터(request quota) 라는 기능을 사용합니다.
    • 특정 클라이언트가 사용할 수 있는 브로커의 자원(시간)을 제한합니다.
    • 하나의 클라이언트가 폭발적인 수준으로 클러스터에 요청을 보내더라도 안정적입니다.

링크드인

링크드인에서 스트림 처리 플랫폼으로 사내에서 사용되었으며 수석 엔지니어 제이 크랩스가 고안했습니다. 

 

생태계 구성요소

  • 브로커로 구성된 카프카 클러스터
  • Kafka 클라이언트를 사용한 애플리케이션
  • REST Proxy API
    • Kafka REST  프록시를 사용하면 REST API를 통해 Kafka 클러스터와 상호작용할 수 있습니다.
  • Avro 스키마를 유지하기 위한 스키마 레지스트리
  • 클러스터 간 미러링을 위한 Brookin
  • 클러스터 유지 관리 및 자가치유를 위한 Cruise Control
  • 파이프라인 완전성 감사 및 Bean Counter 모니터

 

출처: https://engineering.linkedin.com/blog/2019/apache-kafka-trillion-messages

 

 

사용량

이름 사용량
주제 100,000개 이상
파티션 7,000,000개 이상
브로커 4,000개 이상
클러스터 1,000,000개 이상

 

 

 

 

반응형
Comments