2020. 5. 30. 20:22ㆍComputer Science/Backend
Apache Kafka는 분산 메시징 시스템(A high-throuhput distributed messaging system)이다. 2011년 링크드인에서 처음 개발 됐다. 자사 웹사이트의 이벤트 체크 목적으로 만들어지기 시작했고 2014년 아파치 재단으로 이관 됐다.
Architecture
카프카는 발행-구독(publish-subscribe) 모델을 기반으로 동작한다. Producer가 데이터를 발행하고, Consumer가 구독하는 토픽의 데이터를 가져오는 구조다. 중간에서 Producer가 전달하는 데이터를 받는 클러스터를 Broker라고 한다.
고가용성(Fault tolerant, High Availability) 및 확장성(Scalability)
카프카를 논할 때 이 두 가지 특성이 빠지면 섭하다.
고가용성이란 장애대응에 관한 용어다. 카프카가 제공하는 Replica 덕분에 취할 수 있는 특성인데, 한 개의 파티션에 대해 두 대 이상의 브로커에 데이터를 분산 저장함으로써 한 브로커에 장애가 나더라도 데이터 유실에 대한 걱정을 덜 수 있다.
확장성에 대해서는 카프카가 쉽게 서버를 늘리는 Scale-out이 가능하기 때문이다. 서버가 늘어나면 안정성과 성능 향상을 기대할 수 있다.
Kafka Producer
프로듀서는 카프카 토픽으로 데이터를 publishing 한다. bootstrap-server ip와 port number를 잘 입력해주자. 데이터를 전송할 때는 어떤 파티션으로 데이터를 보내줄 지 key값을 지정해준다. key값이 null이라면 Round-robin 방식으로 데이터가 할당된다.
Kafka Consumer
컨슈머는 구독하는 토픽으로부터 데이터를 가져온다(이것을 polling이라고 한다.). 1컨슈머당 1파티션이 원칙이다. 용도에따라 컨슈머들을 묶은 컨슈머그룹을 구현할 수 있다. 컨슈머가 데이터를 가져가도 데이터는 삭제되지 않는다. 컨슈머는 파티션 polling할 때 마다 offset값을 커밋하기 때문에 에러가 발생했을 때 어디까지 데이터를 가져왔는지 쉽게 확인 가능하다. 중단 된 지점을 시작점으로 프로그램을 재가동 시킬 수 있고, 이것 역시 카프카의 고가용성 특징 중 하나다.
Consumer num <= Partition num 여야 한다. 파티션이 두개인데 컨슈머가 한 개인 경우, 하나의 컨슈머가 두개의 파티션에 접근해서 데이터를 가져온다. 2Par 2Con인 경우 일대일로 접근해서 데이터를 가져온다. 만약 2Par 3Con인 경우 하나의 컨슈머는 놀게 된다.
Kafka Topic & Partition
카프카 토픽은 데이터가 들어가는 장소다. 프로듀서와 컨슈머가 토픽을 기준으로 데이터를 발행하고 구독한다. 토픽은 목적에 따라 여러개 생성할 수 있다. 토픽 이름은 click_stream, products_list처럼 직관적으로 명시해주는 게 좋다.
파티션 넘버, offset
토픽은 여러개의 파티션으로 구성 돼 있다. 파티션은 Queue와 같은 First-In-First-Out형태로, 컨슈머가 데이터를 가져갈 때 가장 오래 된 순서부터 가져간다. 각 파티션에는 파티션 넘버가 붙는데, zero-based index 형태라서 파티션 넘버는 0번부터 생성된다. 파티션 넘버와 함께 64-bit로 된 offset value도 생성된다.
개인적으로, Hadoop은 디렉토리 안에 파일구조로 데이터가 저장되는 반면 카프카는 이 offset number가 있어서 특정 데이터(record)에 접근하기가 훨씬 수월하다고 생각한다. 아키텍쳐에서 인덱싱이 이렇게나 중요하다.
★ 중요
컨슈머가 토픽 내부에서 데이터(record)를 가져가도 데이터는 삭제 되지 않는다. 카프카에서 데이터가 삭제 되는 시점은 옵션으로 따로 지정해준다. 토픽 내부에 데이터는 계속 남아있고, 새로운 컨슈머가 해당 토픽을 구독한다면 언제든지 데이터를 가져갈 수 있다. 다만 Consumer Group이 달라야 하고, auto.offset.reset=earlist여야 한다. 동일 데이터가 여러 번 쓰일 수 있다는 것은 카프카의 중요한 이점 중 하난데, 같은 데이터가 용도에 따라 Elastic Search로 넘어가고, 동시에 HDFS에도 저장 될 수 있다는 의미다.
Partition의 분배
위 그림처럼 3개의 브로커로 이루어진 클러스터를 예로 들어보자. 하나의 토픽(예, click_stream)이 여러개의 파티션에 분산 저장 되도록 구현했다면, 어떤 브로커로 보내주는 게 맞을까? 일반적으로 파티션이 2개 이상일 때 어떤 파티션에 데이터를 보낼 건지 key값을 준다. key값이 null인 경우 디폴트값은 Round-robin으로 골고루 할당 된다. key값이 주어졌다면 해당 키의 hash값을 구하고, 그것이 가리키는 파티션에 데이터를 저장한다.
굳이 파티션을 늘리는 이유는 무엇일까? 원칙적으로 1파티션당 1컨슈머가 최대다. 컨슈머 그룹이 다르지 않은 이상 말이다. 파티션을 늘리는 이유는, 파티션이 늘어나면 컨슈머 개수를 늘려서 데이터를 분산 처리할 수 있기 때문이다.
Partition의 복제 (Replication, In Sync Replica)
아 슬슬 복잡해지고 있다. 최대한 쉽게 풀어 설명해보겠음.. 자, 위 그림 같은 경우 브로커 3개에 파티션을 Replication 한 형태다. 한 개의 원본과 두 개의 복제본이 있다. 여기서 유추할 수 있는 것은 브로커의 개수로 Replication의 개수가 제한된다는 점이다. 브로커가 3개인데 4개의 Replication이 생겨날 수 없다. 빨간색으로 표시 된 원본 파티션을 Leader라고 부른다. 복제본인 파란색 파티션들을 Follower라고 부른다. 그리고 이러한 형태가 바로 ISR(In Sync Replica)다.
위에서 설명했던 Fault tolerant를 위한 고가용성이 Replication과 ISR덕분에 가능하다. 데이터가 유실되어도 복제본이 있기 때문에 안심이다. 만약 Leader Partition이 유실 되었다면 Follwer Partition중 하나가 리더가 된다. 원본 복구가 아니라 리더를 승계하는 방식인 것 같다.
용어가 많아서 가독성은 떨어지지만 어려운 내용은 아닙니다. 틀린 내용이나 오타 지적 환영해요.
Reference
'Computer Science > Backend' 카테고리의 다른 글
Spark로 HDFS 데이터 활용하기 (+ pandas, time range filter) (2) | 2020.07.22 |
---|---|
[Linux] screen 명령어로 백그라운드 프로세스 띄우기 (0) | 2020.07.13 |
[Kafka] 카프카 실행, 토픽 생성, 메시지 테스트 (0) | 2020.05.24 |
Spring Boot 의존성 설정 (spring-boot-starter, spring-boot-starter-parent) (0) | 2020.05.21 |
Flume OG, NG, Property (0) | 2020.04.14 |