- 실시간으로 스트림 데이터를 수집하고 처리하는 데 최적화된 ‘분산 이벤트 스트리밍 플랫폼(Distributed Data Streaming Platform)’입니다. 이는 실시간으로 발생하는 대량의 데이터를 중앙 허브를 통해 흐르도록 설계되어 있습니다. 이를 통해 데이터의 일관성을 유지하고 시스템 전반의 복잡성을 줄일 수 있습니다.
- 이러한 다량의 데이터는 A 지점에서 B 지점까지 만의 데이터가 이동되는 것뿐만 아니라, A 지점에서 Z지점까지의 필요한 모든 곳에 대규모 데이터를 동시에 전달할 수 있습니다. - 현대적인 데이터 파이프라인 구축에 필수적인 도구로 자리 잡았으며, Netflix, LinkedIn, Uber 등 많은 기업들이 핵심 인프라로 사용하고 있습니다.
[ 더 알아보기 ] 💡 메타데이터(Metadata) - 데이터에 대한 데이터를 의미하며 다른 데이터를 설명하는 데이터를 의미합니다 - Kafka의 메타데이터는 브로커 목록 및 상태 정보, 토픽 구성, 파티션의 리더와 팔로워 정보, 접근 제어 목록(ACL)등이 해당됩니다.
💡 쿼럼(Quorum) - 분산 시스템에서 합의를 이루기 위한 최소한의 투표수 또는 동의하는 노드의 수를 의미합니다. - 과반수의 원칙으로 전체 노드 수의 과반수(N/2 + 1)를 쿼럼으로 설정을 합니다. - 예를 들어서 5개의 노드로 구성된 시스템에서 최소 3개의 노드가 동의해야 의사결정이 이루어집니다.
💡 [참고] Zookeepr의 유래
- Zookeepr는 동물원의 사육사에서 유래가 되었습니다. - 동물원에서 사육사가 여러 동물들을 관리하고 돌보듯이, Apache Zookeeper는 분산 시스템의 여러 노드(서버)들을 관리하고 조정하는 역할을 수행하기에 이에 대해 유래가 되었습니다.
- Zookeeper는 내부적으로 크게 클라이언트와 서버(리더/팔로워)의 관계로 구성이 되어 있습니다. 이 클라이언트는 Kafka 브로커(Client)들을 의미하고, 서버는 Zookeeper 서버들을 의미합니다.
- Client(Kafka 브로커)는 정보를 읽거나(Read) 혹은 쓰는(Write) 요청을 서버에게 합니다. - 서버(Zookeeper)는 읽기 처리는 리더 서버, 팔로워 서버에서 둘 다 처리할 수 있지만, 쓰기 처리는 리더 서버만 수행할 수 있고 팔로워 서버에게 요청이 들어오면 리더 서버에게 이를 전달합니다. - 또한, 리더 서버는 모든 팔로워 서버에게 전달하여 과반수 이상의 확인을 받은 경우 쓰기 작업을 수행합니다.
- 모든 서버 간의 주기적으로 동기화를 수행합니다. 이를 통해서 데이터 일관성, 고 가용성, 데이터 안정성을 얻을 수 있습니다.
💡 Zookeer 상세 구성 요소
구성 요소
설명
클라이언트(Client)
Zookeeper 서버에 접속하여 정보를 읽고 쓰는 주체입니다.
서버(Server)
Zookeeper 서비스를 제공하는 노드로, 데이터를 저장하고 클라이언트의 요청을 처리합니다. 서버는 크게 리더(Leader)와 팔로워(Follower)로 구분이 됩니다.
리더(Leader)
쓰기 요청을 처리하고 업데이트 순서를 관리하는 ‘주 서버’로, 읽기와 쓰기 모두 가능하며 특히 쓰기 작업의 순서와 조정을 전담합니다.
팔로워(Follower)
주로 읽기 요청을 처리하며, 쓰기 요청이 들어올 경우 리더에게 전달합니다. 리더의 결정사항을 복제하여 저장하는 ‘백업 서버’입니다.
앙상블(Ensemble)
Zookeeper 서버들의 그룹으로, 홀수 개의 서버로 구성됩니다. 홀수 개의 서버로 구성하여 과반수(Quorum) 기반의 합의를 통해 시스템 안정성을 보장합니다
- 서버 A, B, C, D, E는 Zookeeper Ensemble 형태로 클러스터로 구성이 되어 있습니다. 클라이언트는 A, B, C로 Kafka의 브로커들을 의미합니다. - 해당 Zookeeper Ensemble형태로 구성된 이유는 서버들이 3, 5, 7개로 구성되어서 과반수 기반의 합의를 통해 처리가 되기에 홀수 형태로 구성이 됩니다. - 이 경우 리더 서버에 장애가 발생하면 남은 서버들 중에서 새로운 리더를 자동으로 선출하며, 모든 서버가 동일한 데이터를 유지하도록 동기화가 됩니다.
1. 읽기 요청 처리 과정
1.1 클라이언트는 Zookeeper 서버(리더 또는 팔로워)에 읽기 요청을 보냅니다. - Client A는 Server C(Leader Server)로 요청, Client B는 Server B(Follower Server)로 요청합니다. 1.2. 해당 서버는 자신의 로컬 데이터베이스에서 데이터를 조회하여 직접 응답합니다. 1.3. 모든 서버가 동일한 데이터 복제본을 가지고 있어 빠른 읽기 처리가 가능합니다.
2. 쓰기 요청 처리 과정
2.1. 클라이언트는 서버에 쓰기 요청을 전송합니다. 2.2. 팔로워가 요청을 받은 경우, 해당 요청을 리더에게 전달합니다 - Client B는 Server D(팔로워 서버)에게 요청을 하였습니다. Server D는 Server C(리더 서버)에게 요청을 전달합니다. 2.3. 리더는 받은 쓰기 요청을 모든 팔로워들에게 전파합니다. 2.4. 과반수 이상의 팔로워로부터 확인을 받으면 쓰기 작업 완료합니다. 2.5. 리더는 클라이언트에게 쓰기 작업 완료 응답을 전송합니다.
3. 동기화 과정
3.1. 리더는 주기적으로 모든 팔로워들과 동기화를 수행합니다. 3.2. 새로운 팔로워가 추가되거나 장애 복구 후 재참여 시, 리더와 전체 데이터 동기화합니다. 3.3. 지속적인 동기화를 통해 클러스터 전체의 데이터 일관성 보장합니다.
- Zookeeper에서 데이터를 저장하고 관리하는 방식을 의미합니다. - 이는 계층적인 네임스페이스를 사용하며, 이는 파일 시스템과 유사한 구조를 가집니다. - 데이터는 ZNode라고 불리는 노드에 저장되며, 각 ZNode는 고유한 경로를 가집니다.
[ 더 알아보기] 💡 계층적인 네임스페이스(Hierarchical Namespace)
- 디렉터리와 파일처럼 상위/하위 관계를 가지는 구조를 의미하며, 각 노드들이 가지는 고유한 경로(path)를 통해서 접근이 가능합니다.
- 예를 들어서 아래와 같은 고유한 경로(path)에 따라 정보를 확인하고 가져올 수 있습니다 - /kafka/brokers/ids/1 → broker 1의 정보 - /kafka/brokers/topics/orders → orders 토픽 정보 - /kafka/controller → 컨트롤러 정보
- ZNode는 노드를 의미하며, 데이터 그 자체를 의미합니다. 위의 이미지를 확인하면 경로는 ‘/’ 구분자를 가지며 고유한 경로를 가집니다.
- '/' : 루트 디렉터리를 의미하며, 모든 ZNode의 최상위 경로입니다. - '/app1' : 루트 디렉토리 아래에 있는 'app1'이라는 애플리케이션 또는 서비스를 위한 노드입니다. - '/app1/p_1' : 'app1' 아래에 있는 하위 노드로, 특정 프로세스나 데이터를 나타냅니다.
- 이러한 계층 구조를 통해 각각의 애플리케이션이나 서비스에 대한 설정, 상태 정보 등을 체계적으로 관리할 수 있습니다.
- Kafka에서는 ZooKeeper 모드가 아닌 KRaft 모드를 사용하면서 kafka를 실행하면 모든 Kafka 클러스터와 함께 Zookeeper 클러스터를 실행할 필요가 없습니다. 즉, KRaft 모드를 사용하면 Zookeeper 없이도 Kafka를 운영할 수 있다는 것을 의미합니다.
- 기존 Zookeeper를 이용한 경우, Client(Kafka 브로커)의 모든 중요 메타데이터는 Server(Zookeeper)와의 지속적인 통신을 통해서 상호 조정 및 상태 정보를 공유했었습니다. - 그러나 Raft 내에서는 외부 Zookeeper와의 통신이 아닌 브로커의 일부가 컨트롤러의 역할을 수행하면서 Zookeeper가 제공하던 합의 서비스를 대체합니다.
- 즉, 모든 Kafka 클러스터의 메타데이터는 Kafka 토픽에 직접 저장이 되어서 ‘내부적’으로 관리가 됩니다. 이를 통해, 시스템 구조가 단순화되고 별도의 외부 시스템 없이 Kafka를 운영할 수 있게 되었습니다
- 분산 시스템에서 ‘노드 간에 합의’를 이루기 위한 알고리즘을 의미합니다. 이를 통해 시스템의 모든 노드가 동일한 상태를 유지하도록 하고, 일부 노드에 결함이 생기더라도 전체 시스템이 문제없이 동작하도록 만들기 위해 고안된 알고리즘을 의미합니다.
💡 라프트 컨센서스 알고리즘의 용어의 의미
- Raft는 뗏목을 의미합니다. - 여러 개의 통나무를 단단히 묶어서 안정적인 구조로 만드는 것처럼 Raft 알고리즘도 여러 노드들을 하나의 일관된 시스템으로 묶어줍니다. 그리고 리더와 팔로워 간의 동일한 일관성을 유지를 해야 하는데, ‘로그 복제’를 통해서 서로 간의 노드 간의 일관성을 유지합니다.
- KRaft는 Kafka 클러스터 내에서 이러한 데이터 처리과정이 이루어집니다. - 데이터 처리는 컨트롤러 노드에서 이를 수행하며, 브로커 중 일부가 컨트롤러 노드로 선택되어 메타데이터 관리 역할을 수행합니다. 또한 동일한 노드에서 브로커와 컨트롤러 역할을 동시에 수행할 수 있습니다.
1. 단순화된 아키텍처 - 외부에서 호출이 되던 Zookeeper와의 의존성을 완전히 제거하고 Kafka가 자체적으로 메타데이터를 관리할 수 있게 되었습니다
2. 향상된 성능 - 메타데이터 관리를 위한 추가적인 시스템 호출이 감소되어 전체적인 시스템 성능이 향상되었습니다 3. 높은 확장성 - 대규모 클러스터 환경에서도 효율적인 운영이 가능하며, 특히 옵저버 노드를 통해 읽기 전용 복제로 클러스터의 확장성을 더욱 향상할 수 있습니다
4. 단일 쿼럼 - 단일 쿼럼을 사용하여 메타데이터를 관리함으로써 전체 시스템의 복잡도가 낮아졌습니다
- KRaft에서 안정적이고 일관된 클러스터를 관리하기 위해서 Raft 합의 알고리즘을 이용합니다 - 아래와 같은 구성 요소들은 Kafka 클러스터 내부에 컨트롤러 노드에서 이러한 역할을 수행합니다. - 또한 이를 통해서 메타 데이터를 읽고 쓰고, 관리할 수 있고 서로 협력하여 클러스터 데이터 일관성과 안정성을 유지하게 됩니다.
- KRaft에서 데이터를 저장하고 관리하는 방식을 의미합니다. - KRaft의 모든 데이터 변경사항은 데이터 토픽 내에 저장이 됩니다. 이러한 토픽 내에는 레코드로 실제 데이터가 저장이 됩니다. 즉, 토픽 내에 여러 개의 래코드가 포함할 수 있습니다. - 이벤트 토픽 내에서 브로커들은 이벤트들을 조회해 옵니다. 또한 브로커의 리더는 다수의 권한을 받아서 이벤트를 쓰기 합니다. - 주기적으로 해당 브로커의 리더는 스냅샷을 통해서 전체 클러스터 상태를 압축하여 저장해 둡니다.
요소
설명
메타데이터 토픽 (Metadata Topic)
Kafka 클러스터의 모든 메타데이터 변경사항을 저장하는 특별한 토픽으로, 브로커 정보, 토픽 구성, 파티션 할당 등의 클러스터 상태 정보를 포함
메타데이터 레코드(Metadata Record)
메타데이터 토픽에 저장되는 개별 변경사항을 나타내는 레코드로, 각각의 클러스터 구성 변경을 시간 순서대로 기록
쿼럼 로그(Quorum Log)
Raft 합의 프로토콜을 구현하기 위한 로그로, 컨트롤러 선출과 메타데이터 변경의 합의 과정을 기록하고 추적
스냅샷(Snapshots)
특정 시점의 전체 클러스터 상태를 압축하여 저장한 데이터로, 빠른 복구와 새 노드 초기화에 사용되며 로그 크기를 효율적으로 관리