실시간 채팅 구현] kafka 적용기 -1 (kafka를 redis 대용으로 사용가능한가?)
이번에 팀 프로젝트로 실시간 채팅 서비스를 웹앱으로 구현하기로 하였는데 실시간 채팅 서비스 구현은 나도 처음인지라 어떠한 기술을 도입하는게 안정적인 서비스를 고민하던 차에 kafka와 redis를 이용하여 채팅 서비스를 구현하기로 하였는데 팀원들과 카프카 및 레디스에 대해서 논의하다가 다음과 같은 궁금증이 생겼다.
1. 애초에 내가 생각하던 카프카 및 레디스의 역할
1) 카프카
- 실시간 채팅 서비스를 구현할 때, 웹소켓을 이용해서 채팅을 한다면 채팅 내역들을 추후 백업 등을 할 때 필요하므로 영구적으로 DB에 저장해야한다고 판단하였다.
- 실시간 채팅 시 메세지를 DB에 저장을 할 때, 메세지 건마다 DB로 insert문을 날려야 하니 DB 입장에서는 병목현상이 발생할 수도 있고, 만약 DB가 중간에 뻗는다면 데이터가 유실되니 곧바로 DB로 저장하는거는 위험하고 비효율적이라고 생각해서 메세지 브로커를 생각하게 되었다.
- DB병목현상 및 데이터 유실을 막기 위해 kafka 라는 이벤트 분산 스트리밍을 생각하게 되었고 kafka가 적절하다고 판단하였다.
- kafka를 사용한다면, 웹소켓에서 받아온 메세지를 producer로 제공하여 토픽에 넣어주고, 컨슈머가 해당 메세지를 소비하면서 DB로 넣어주는 구조로 생각하였다.
2) redis
- 레디스는 인메모리 기반으로 최근 메세지들을 캐싱해서 빠른 대화내용 저장 및 select를 위해 사용하려고 함.
- 또한, 읽음 수 처리, 메시지 수신 시 즉시 알림 구현을 위해 사용하려고 함.
3) DB(postgresql)
- 백업용도 및 전체 대화내역 저장을 위해 kafka에서 DB로 저장하려고 사용.
2. 팀원들과 토론하면서 생긴 궁금점
1) kafka는 메세지를 받으면 토픽에 메세지들을 저장하는데 해당 메세지들은 디스크에 저장되어 영구보존이 가능하다고 함. 그렇다면 굳이 redis를 사용할 이유가 있을까? redis는 메세지 소비시 데이터가 휘발되는데 kafka는 데이터 영구보존이 되니까 kafka를 db처럼 사용해서 redis는 필요없는건 아닐까?
2) redis 는 pub/sub으로 구독과 발행을 해서 메세지가 들어오면 구독하고 있던 서비스가 바로 메세지를 받는데, kafka는 polling으로 자동으로 메세지를 받는게 아니라 메세지가 있는지 계속해서 확인해야하는 것으로 알고 있다. 그러면 polling 하기 전까지는 topic에 메세지들이 들어있는데 polling 전까지의 메세지들을 db의 select처럼 관리해서 볼 수 있는 거 아닐까?
이 두가지 궁금점이 내가 생각하던 kafka의 역할과는 사뭇 다른데, 따지고 보면 맞는말 같기도 해서 kafka의 정확한 기능과 redis 및 db의 차이점에 대해 조사를 하기로 하였다.
그러면 먼저, kafka란 무엇인지 알아보도록 하자.
1. kafka란?
Kafka는 분산 스트리밍 플랫폼이다. 간단히 말해, 대량의 이벤트 데이터를 빠르게 전송하고 안전하게 보관하며, 필요한 시스템들이 비동기적으로 처리할 수 있도록 해주는 메시지 브로커다.
즉, 실시간 데이터 스트리밍, 비동기 메세지 처리, 이벤트 중심 아키텍처를 구현하는데 특화된 시스템으로서, 대규모 데이터를 빠르고 안정적으로 한 시스템에서 다른 시스템으로 흐르게 만드는 파이프라인을 말한다.
2. Kafka의 주요 특징
항목 | 설명 |
고성능 | 초당 수백만 개의 메세지를 처리할 수 있음 |
내구성 | 메세지를 디스크에 저장해 장애 시에도 유실 없음 |
확장성 | 수평 확장이 용이함(브로커, 파티션 단위 확장) |
재처리 가능성 | offset 기반 처리로 메세지를 다시 소비할 수 있음 |
분산 시스템 | cluster 형태로 구성되어 고가용성 제공 |
kafka에서는 기본 구성요소로 Producer, Consumer, Topic, Broker에 대한 개념이 있는데 개념적으로는 다음과 같다.
구성요소 | 설명 |
Producer | - kafka에 메세지를 발생하는 주체를 뜻함. - 실시간 채팅에서는 웹 서버에서 채팅 메세지를 kafka로 전송하는것을 producer가 처리함. |
Consumer | - kafka에서 메세지를 가져가서 처리하는 주체 - 예를들어, 메세지를 읽고 DB에 저장하거나, 알림 시스템으로 전달하는 역할. - consumer는 consumer group에 속할 수 있으며, 같은 그룹 내의 consumer들은 서로 메세지를 나누어서 처리함. |
Topic | - 메세지를 구분하기 위한 카테고리 단위의 큐를 뜻함. - 모든 메세지는 특정 토픽에 속함 - 내부적으로 하나 이상의 partition으로 나뉘어서 병렬처리됨. |
Broker | - kafka 서버 인스턴스 - 메세지를 받아 디스크에 저장하고 Consumer에게 제공함. - 여러 Broker로 cluster 구성이 가능함. |
3. kafka의 주요 개념 및 기능
1) Partition
- Topic을 병렬로 처리하기 위한 최소한의 단위를 뜻함.
- 여러 consumer가 동시에 메세지를 처리할 수 있게 해줌
- 메세지는 partition에 순차적으로 저장됨
2) Offset
- kafka 메세지의 고유 위치를 뜻함. 이는 메세지의 순번을 뜻하는 것임
- 각 consumer group은 "어디까지 데이터를 읽었는지"를 offset으로 관리함
- offset을 조작 시, 이미 소비한 메세지에 대해서도 재처리가 가능함
3) Retention
- kafka는 메세지를 일정 기간 또는 용량만큼 디스크에 보존함
- ex) log.retention.ms=604800000 -> 7일동안 디스크에 메세지를 유지함.
4) Exactly-once / At-least-once 처리
- kafka는 적절한 설정을 통해 중복 없는 메세지 처리(exactly-once)도 가능함.
- 기본적으로는 at-least-once (최소 한번 전달) 인데, 이는 중복 가능성이 있음
이번 포스팅에서는 kafka의 기본 개념에 대해서만 알아보도록 하고 다음 포스팅에서는 redis와 kafka의 차이점에 대해 비교하도록 하려고 한다. 그 다음에는 팀원들과 논의했던 2가지 의문점에 대해 포스팅 하겠다.