[카프카] 5장_카프카 컨슈머

컨슈머란, 프로듀서가 메세지를 생산해서 카프카의 토픽으로 보내면 그 토픽의 메세지를 가져와 소비하는 애플리케이션, 서버이다.
주요 기능은, 특정 파티션을 관리하고 있는 파티션 리더에게 메세지를 가져오기 요청을 하는 것이다.

파티션과 메세지 순서

파티션 3 개로 구성한 토픽과 메세지 순서

프로듀서 다음 순서로 보낸다.

1
2
3
4
5
a
b
c
d
e

컨슈머에서 –from-beginning 옵션으로 받는다.
메세지의 순서가 프로듀서가 보낸 순서가 아니다.

1
2
3
4
5
a
d
b
e
c

다음으로, 프로듀서서가 숫자를 보낸다.

1
2
3
4
5
1
2
3
4
5

컨슈머에서 –from-beginning 옵션으로 받는다.

1
2
3
4
5
6
7
8
9
10
a
d
1
4
b
e
2
5
c
3

–partition 0, –partition 1, –partition 3 로 각각 옵션을 주어서 컨슈머를 각각 실행해보면,

1
2
3
4
b
e
2
5
1
2
3
4
a
d
1
4
1
2
c
3

위 현상은 정상이다.
프로듀서가 메세지를 a b c d e 순서로 보냈지만, 해당 메세지들은 하나의 파티션에만 순서대로 저장되는 것이 아니라 각각의 파티션별로 메세지가 저장되었다.
컨슈머의 출력 내용은 각 파티션의 오프셋 순서대로 메세지를 가져온 것이다. 즉,

  1. 카프카 컨슈머에서의 메세지 순서는 동일한 파티션 내에서는 프로듀서가 생성한 순서와 동일하게 처리하지만,
  2. 파티션과 파티션 사이에서는 순서를 보장하지 않는다.

그림으로 나타내면 아래와 같다.

파티션 1 개로 구성한 토픽과 메세지 순서

메세지 순서를 정확하게 보장받기 위해서는 토픽 파티션 수를 1 로 지정하면 된다.
단점은,

  1. 분산해서 처리할 수 없고
  2. 하나의 컨슈머에서만 처리할 수 있기 때문에 처리량이 낮다.

컨슈머 그룹

동일한 토픽에 대해 여러 컨슈머가 메세지를 가져갈 수 있도록 컨슈머 그룹이라는 기능을 제공한다.
이 방식은, 최근에 하나의 데이터를 다양한 용도로 사용하는 요구가 많아져서 유용하다.
즉, 하나의 토픽을 여러 consumer group 이 서로 다른 목적 달성을 위해 consume 하기 위해 사용되는 것이다.

아래 그림에서, 갑자기 프로듀서가 해당 토픽으로 많은 메세지를 전송한다고 가정해보자. 그러면,
프로듀서가 메세지를 보내는 속도가 컨슈머가 메세지를 가져가는 속도보다 빨라서, 컨슈머가 읽어가지 못하는 메세지들이 쌓인다.

그래서 다음과 같이 컨슈머를 확장한다.

하나의 파티션, 하나의 컨슈머

그런데, 이렇게 컨슈머를 추가했음에도 컨슈머가 가져가야하는 메세지가 쌓이면 어떻게 해야할까 ?

위와 같이 컨슈머 04 를 추가해보자. 그대로다.
왜냐하면, 토픽의 파티션에는 하나의 컨슈머만 연결할 수 있기 때문이다.
각각의 파티션에 대해서는 메세지 순서를 보장하는데 두 개의 컨슈머가 하나의 파티션을 공유하면 안정적으로 메세지 순서를 보장할 수 없다.
그래서 파티션 수도 같이 늘려줘야한다.

리벨런싱

컨슈머 그룹 안에서는 컨슈머들이 메세지를 가져오고 있는 토픽의 파티션에 대한 소유권을 공유한다.
partition 01 의 소유권이 consumer 01 에서 consumer 02 로, partition 02 의 소유권이 consumer 01 에서 consumer 03 으로 이동할 수 있다.
이렇게 소유권이 이동하는 것을 rebalancing 이라고 한다.
리밸런스의 단점은, 리밸런스 하는 동안 일시적으로 컨슈머는 메세지를 가져올 수 없다는 것이다.

위와 같이, 컨슈머 그룹에서 consumer 03 이 다운되는 경우를 살펴보자.
컨슈머가 컨슈머 그룹 안에서 멤버로 유지되고 할당된 파티션의 소유권을 유지하는 방법은, heart beat 를 보내는 것이다.
만약, 컨슈머가 오랫동안 하트비트를 보내지 않으면 세션은 타임아웃되고 해당 컨슈머가 다운되었다고 판단해서 리밸런스가 시작된다.
consumer 03 이 다운되면서 consumer 03 이 담당하던 partition 03 을 consumer 02 가 이어받는다.

커밋과 오프셋

컨슈머가 poll() 을 호출할 때마다 컨슈머 그룹은 카프카에 저장되어 있는 아직 읽지 않는 메세지를 가져온다.
이것이 가능한 이유는, 컨슈머 그룹이 어디까지 메세지를 가져갔는지 알 수 있기 때문이다.
컨슈머 그룹의 각각 컨슈머들은 각각의 파티션에 자신이 가져간 메세지의 위치 정보인 오프셋을 기록한다.
각 파티션에 대해 현재 위치를 업데이하는 것을 커밋 이라고 한다.

  1. 올드 카프카 컨슈머 (0.9 이전 버젼)
    오프셋 정보를 주키퍼에 저장

  2. 뉴 카프카 컨슈머
    내부에서 사용하는 토픽 (_consumer_offsets) 을 만들고 이 토픽에 오프셋 정보를 저장

자동 커밋

1
enable.auto.commit = true

컨슈머가 poll() 을 호출할 때마다 가장 마지막 오프셋을 커밋한다.

수동 커밋

메세지 처리가 완료될 때까지 메세지를 가져온 것으로 간주되어서는 안되는 경우에 사용한다.
ex) 메세지를 컨슈머가 가져오자마자 커밋하는 것이 아니라, 데이터베이스에 메세지를 저장한 후 커밋을 한다.


카프카, 데이터 플랫폼의 최강자 <고승범, 공용준>

Comments