프로젝트를 진행하면서 카프카를 처음공부하고 적용해보면서 흥미로웠습니다.
배울때는 유튜브에 데브원영님이 완전 상세하고 친절하게 설명해주셔서 어렵지는 않았습니다.
🔗 https://www.youtube.com/channel/UCPdTFQUHzAzFobngtw1sFKg
처음에는 소스어플리케이션과 타겟어플리케이션이 단방향으로 많이 진행이 되었습니다.
하지만 소스어플리케이션과 타겟어플리케이션이 증가하면서 데이터들을 전송하는 라인이 많아지면서 복잡해져
관리가 필요했습니다.
위와같은 이유로 카프카가 개발되었습니다.
즉, 소스어플리케이션과 타겟어플리케이션의 커플링을 약하게 하기 위해서 나왔습니다.
Apache Kafka는 실시간 데이터 스트림 처리를 위한 오픈소스 플랫폼입니다. LinkedIn에서 개발되었습니다.
카프카에는 크게 5가지의 기능을 제공합니다.
Publish-Subscribe 모델: Kafka는 메시지를 주제(topic)별로 분류하고, 생산자(producer)가 메시지를 생성하여 특정 주제에 게시(publish)하면, 그 주제를 구독(subscribe)하는 소비자(consumer)들이 메시지를 받아 처리하는 방식을 지원합니다.
분산처리: Kafka는 클러스터 형태로 구성될 수 있으며, 여러 서버에 걸쳐 데이터 스트림을 분산 저장하고 처리할 수 있습니다. 이를 통해 높은 확장성과 내구성을 보장합니다.
실시간 처리: Kafka는 대용량의 실시간 데이터 스트림을 빠르게 처리할 수 있습니다. 따라서 로그 수집, 실시간 분석 등 다양한 사용 사례에서 활용됩니다.
내결함성(Fault-tolerance): Kafka 클러스터 내에서 각 메세지와 상태들은 복제(replication)되어 저장되므로, 한 노드가 실패해도 데이터 손실 없이 운영이 가능합니다.
영속성(Persistence): Kafka에서 모든 메세지는 디스크에 영속적으로 저장되며, 사용자 설정에 따라 일정 시간 동안(또는 용량이 충분한 한 계속해서) 보관됩니다.
💡 Kafka의 이러한 특징들 때문에 많은 기업들이 실시간 로그처리나 스트리밍 데이터 처리 등의 목적으로 Kafka를 활용하고 있습니다.
카프카에는 각종 데이터를 닮는 토픽이라는 개념이 있는데 쉽게 이야기해서 큐라고 생각하면 좋습니다.
이 둘은 라이브러리로 되어있어 어플리케이션에서 구현 가능
카프카에서 토픽은 메시지(이벤트)를 구분하는 단위입니다.
하나의 토픽은 여러 개의 파티션으로 구성될 수 있으며, 각 파티션은 메시지를 저장하는 물리적인 파일입니다. 카프카 프로듀서는 토픽에 메시지를 발행하고, 카프카 소비자는 토픽에서 메시지를 소비합니다.
하나의 토픽은 여러개의 파티션으로 구성이 가능합니다.
첫번째 파티션은 0번부터 시작하고 하나의 파티션은 큐와같이 내부의 데이터가 파티션의 끝부터 쌓이게 됩니다.
이때 컨슈머는 메세지가 오래된 순서대로 가져가게 됩니다.
그리고 카프카는 이벤트 브로커 이기때문에 컨슈머가 메세지를 가져가도 사라지지 않습니다.
남은 메세지는 또 다른 컨슈머가 붙었을때 그 컨슈머가 가져갈 수 있습니다.
public class Producer {
public static void main(String[] args) throws I0Exception {
Properties configs = new Properties( );
configs.put("bootstrap.servers", "localhost: 9092");
configs.put("key .serializer","org .apache.kafka.common.serialization.StringSerializer");
configs.put("value.serializer","org. apache.kafka.common.serialization.StringSerializer");
KafkaProducer < String, String > producer = new KafkaProducer < String, String > (configs) ;
ProducerRecord record = new ProducerRecord < String, String > ("click_ log", "Login");
producer. send (record);
producer. close();
}
}
위의 예제에서는 click_log라는 토픽에 login이라는 메세지만 선언을 해주었지만
사이에 파티션의 키를 설정하여 파티션 지정이 가능하게 됩니다.
이때 따로 설정을 하지 않고 파라미터의 개수에 따라서 자동으로 오버로딩되어 인스턴스를 생성하게 됩니다.
토픽에서 설명했듯이 파티션의 키값을 설정하지 않았다면 round robin방식으로 균일하게 파티션에 저장이되지만 따로 설정을 하였다면 카프카는 키를 특정한 hash값으로 변경시켜 파티션과 1:1 매칭을 시켜줍니다.
하지만 메세지를 보내는 도중 파티션의 수를 늘리게 된다면 매칭을 깨지게 되면서 키와 파티션의 연결은 보장되지 않습니다.(키-파티션의 일관성 보장 X)
그리고 토픽을 생성할때 partition과 replication의 수를 설정하게 됩니다.
즉, partition1, replication3이면 세개의 서버에 같은 파티션 하나가 생성되게 됩니다.
그리고 토픽을 만들때 하나의 브로커에 들어가서 만들게 되는데 그곳의 partition이 leader partition이 되고, 나머지 두개의 파티션은 follower partition이라고 합니다.
하지만 무작정많으면 좋지않습니다
⇒ 1 partition, 6 replication은 많아서 좋지만 브로커의 리소스 사용량도 늘어나게 됩니다.
만약 두개의 파티션이 존재하고 하나의 컨슈머가 있다면 하나의 컨슈머가 두개의 파티션을 할당하여 데이터를 가져올수 있습니다.
컨슈머가 두개라면 각각의 파티션 하나를 할당하여 데이터를 가져올수 있습니다.
하지만 파티션의 수보다 컨슈머 그룹에 컨슈머가 많다면 즉, 2개의 파티션에 3개의 컨슈머가 있다면 하나의 컨슈머는 동작하지않습니다.
컨슈머는 파티션의 수보다 같거나 적어야 합니다.
__consumer_offset토픽에는 컨슈머 그룹별로 토픽별로 offset을 나누어 저장하기 때문입니다.