kafka

Kafka가 대용량 트래픽에 뛰어난 성능을 보이는 이유

downfa11 2024. 11. 21. 16:15

Kafka가 메시징 애플리케이션을 넘어서 이벤트 스트리밍 플랫폼으로 군림할 수 있었던 이유가 뭘까?

 

그야말로 신강을 넘어 중원 무림을 점령해버린 천마..

 

통상적인 인식으로, Apache Kafka에 따라오는 키워드는 확장성, 고성능높은 처리량이다.

 

분산 메시징 시스템으로 처리량이 높은건 건 알겠는데, Redis와 다르게 Kafka는 데이터를 Broker의 disk에 저장한다.

 

disk I/O 비용이 상당히 큰 출혈인데, 얜 도대체 왜 빠른거지?????????????

 

왜빠른데요?왜Kafka는신이죠?왜다들이거에목메는거죠?왜성능이좋은건데요?전문엔지니어가필요한데도왜다들공부하는건데요???

 

순차적 I/O(Sequential I/O)

disk 접근은 어떻게 사용하는지에 따라 느릴수도 있고 빠를 수도 있다.

순차적으로 디스크에 접근하는 속도는 random access보다 150,000배 빠르고, 이는 메모리에 random access하는것 보다도 빠르다. 이 순차적 접근은 데이터를 segments로 저장하기에 가능하다.

  1. immutable : 한 번 쓰이면 변하지 않는 성질. 소비해도 데이터가 지워지지 않는다
  2. append-only : 오직 맨 끝에 추가될뿐
  3. sequential(↔fragments) : disk에 조각으로 나뉘지 않고 가능한 연속적인 블록에 저장

따라서, Kafka는 데이터를 메시지 큐로 저장하기에 순차적 I/O 혜택을 볼 수 있어 빠른 성능을 제공한다.

 

이 경우 Sequential Access가 항상 보장되는 것이 아니라, 다른 애프리케이션으로 인해 디스크 단편화가 발생할 소지가 있다.

 

Kafka의 데이터를 가급적 독립된 파일 시스템에 유지할 것을 권장하는 이유

Page Cache

  1. 디스크 검색을 줄이고 처리량을 높히기 위해 최신 OS들은 디스크 캐시(Page Cache)를 위해 더욱 공격적으로 메모리를 사용하게 되었다.
  2. 모든 disk 작업은 페이지 캐시를 거치며 유저 모드와 커널 모드의 중복 저장 없이 2배 정도의 캐시를 저장한다.
  3. page cache는 파일이나 소켓 I/O 연산에 대한 캐시로 사용된다.

 

또 Kafka는 Java와 Scala로 개발되었다.

JVM 위에서 작동하기에 Heap 메모리에 객체를 저장하는 비용이 크고, 힙이 커질수록 GC가 느려지는 단점이 있다.

그치만!!! 순차적 작업을 할 수 있는 Page cache를 사용하는게 다른 구조를 쓰거나, 메모리 캐시를 사용하는 것보다 좋은 성능을 낼 수 있다.

Zero Copy

zero copy는 서로 다른 메모리에서 복사되는 횟수를 줄여서 성능을 크게 향상 시키는 기술

일반적으로 네트워크를 통해 데이터가 전달되는 과정

  • OS는 Disk로부터 데이터를 읽어 커널 영역의 page cache에 저장
  • 애플리케이션은 page cache의 데이터를 사용자 영역으로 읽는다
  • 애플리케이션은 커널의 socket buffer로 데이터를 쓴다
  • OS는 socket buffer에 있는 데이터를 NIC buffer로 복사하고, 네트워크를 통해 전송

left= 일반적인 경우, right= zero-copy

원래대로면 4번의 복사와 2번의 system call, 4번의 컨텍스트 스위칭이 발생한다.

Zero Copy 원칙을 따르면, 데이터를 read buffer→socket buffer 직접 보내서 컨텍스트 스위칭이 2번밖에 없어지게 된다.

Zero-copy 원칙을 구현하는 방법

1. Memory mapping - mnap()

사용자의 가상 메모리 주소를 커널 메모리 주소에 Mapping하는 방식

2. Direct memory access(DMA) - sendfile()

Topic에서 메시지를 소비할때, 데이터를 별도의 buffer로 복사하지 않고 Log를 직접 읽는다.

Linux의 sendfile() : read()와 write()를 대체한 새로운 system call

page cache에서 데이터를 직접 네트워크로 보내서 중복 복사 방지한다.

데이터를 page cache에서 socekt으로 전송하여 NIC buffer로의 복사만 이뤄진다

Context-Switching 절감하니 당연히 성능적 이점을 가져간다.

이외에도 몇몇 요소들이 있는데, 좀 중요하게 생각되는게 Topic Partitioning 정도라고 생각한다.

Topic Partitioning

Log Segments는 순차적이라 여러 쓰레드가 동시에 접근하는게 의미 없다.

최근의 것만 한 번 읽으면 되기에 병렬 처리가 불가능하다

같은 Topic이라도 데이터를 Sharding하여 저장하고, 각 파티션에 독립된 쓰레드를 붙여서 작업하도록 구성

→ 결과적으로 Topic 하나에 여러 쓰레드가 나눠서 병렬적으로 작업 수행 (=안됐는데 됐어요)

한 건의 경우 성능에 큰 영향이 없지만, 수십- 수백만 이상의 대량의 데이터가 Kafka를 통해 전달될 수록 더욱 큰 성능 차이를 맛보여 줄테다

Data Batch & Compression

데이터에 대한 배치와 압축을 지원해서 네트워킹 횟수를 대폭 줄였다.

 

+ 추가적인 자료

 

Java 11에서 여러 Zero-copy간의 성능 퍼포먼스를 비교하는 글을 찾았다.

 

도식에 따르면, mmap()으로 81% 성능 향상과 sendfile()로는 91%의 향상이 있다고 한다.

 

Meanwhile, there are also spaces to improve, such as the high expense of mapping operation, the limited use cases of sendfile() and the space restrictions.

Mapping 의 비용, sendfile()의 좁은 사용처나 공간 제약 등의 개선 여지가 있다고 한다.

인용 및 사진 자료 출처.

paka

https://docs.confluent.io/home/overview.html - Kafka and the File System

https://www.linkedin.com/pulse/why-kafka-so-fast-aman-gupta