메시지 중복 제거

메시지 중복 제거 (Message Deduplication)

메시지를 다시 보내야 하는 상황에서 중복이 쌓이면 순서 보장이 흔들리고 데이터가 중복 처리될 수 있어요. Pulsar의 메시지 중복 제거는 이런 중복 게시를 걸러내는 기능이에요. 이 글에서는 중복 제거가 어떻게 동작하는지, 브로커·네임스페이스·토픽 수준에서 어떻게 설정하는지, 그리고 클라이언트에서 어떤 준비가 필요한지 정리해 드릴게요.

출처: 문서

본문

메시지 중복 제거는 정보 스냅샷(informational snapshot) 동안 브로커의 성능에 영향을 줄 수 있어요.

Pulsar에서 메시지 중복 제거를 사용하려면 브로커, 네임스페이스 또는 토픽을 구성해야 해요. 클라이언트에서 구성을 변경하는 것이 좋은데, 예를 들어 send timeout을 무한대로 설정해요.

메시지 중복 제거 동작 방식

메시지 중복 제거는 브로커, 네임스페이스 또는 토픽 수준에서 활성화하거나 비활성화할 수 있어요. 기본적으로 모든 브로커, 네임스페이스, 토픽에서 비활성화되어 있어요. 다음 방식으로 활성화할 수 있어요:

  • 브로커 수준에서 모든 네임스페이스/토픽에 대해 중복 제거 활성화.
  • pulsar-admin namespaces 인터페이스로 특정 네임스페이스에 대해 중복 제거 활성화.
  • pulsar-admin topics 인터페이스로 특정 토픽에 대해 중복 제거 활성화.

메시지 중복 제거 구성

Pulsar에서 메시지 중복 제거는 broker.conf 구성 파일로 구성할 수 있어요. 사용 가능한 중복 제거 관련 파라미터는 다음과 같아요.

파라미터 설명 기본값
brokerDeduplicationEnabled Pulsar 브로커의 메시지 중복 제거 기본 동작을 설정해요. true로 설정하면 모든 네임스페이스/토픽에서 메시지 중복 제거가 활성화돼요. false로 설정하면 네임스페이스 수준이나 토픽 수준에서 중복 제거를 활성화하거나 비활성화해야 해요. false
brokerDeduplicationMaxNumberOfProducers 중복 제거 목적으로 정보가 저장되는 최대 프로듀서 수예요. 10000
brokerDeduplicationEntriesInterval 중복 제거 정보 스냅샷이 촬영되는 엔트리 수 간격이에요. 간격이 클수록 스냅샷이 더 적게 촬영되지만, 토픽 복구 시간(스냅샷 이후 게시된 엔트리를 재생하는 데 필요한 시간)이 길어져요. 1000
brokerDeduplicationSnapshotIntervalSeconds 중복 제거 정보 스냅샷이 촬영되는 시간 간격이에요. brokerDeduplicationEntriesInterval과 동시에 실행돼요. 120
brokerDeduplicationProducerInactivityTimeoutMinutes 브로커가 연결이 끊긴 프로듀서와 관련된 중복 제거 정보를 버리는 비활성 시간(분)이에요. 360 (6시간)

브로커 수준에서 기본값 설정

기본적으로 메시지 중복 제거는 모든 Pulsar 네임스페이스/토픽에서 비활성화되어 있어요. 모든 네임스페이스/토픽에서 활성화하려면 brokerDeduplicationEnabled 파라미터를 true로 설정하고 브로커를 재시작해요.

brokerDeduplicationEnabled 값을 설정해도, Pulsar admin CLI로 활성화/비활성화하면 브로커 수준의 기본 설정을 재정의해요.

네임스페이스 또는 토픽 수준에서 메시지 중복 제거 활성화

브로커 수준에서 메시지 중복 제거가 기본적으로 비활성화되어 있지만, pulsar-admin namespaces set-deduplication 또는 pulsar-admin topics set-deduplication 명령으로 특정 네임스페이스나 토픽에 대해 활성화할 수 있어요. --enable/-e 플래그를 사용하고 네임스페이스/토픽을 지정하면 돼요.

다음 예시는 네임스페이스 수준에서 메시지 중복 제거를 활성화하는 방법을 보여줘요.

bin/pulsar-admin namespaces set-deduplication \
public/default \
--enable # or just -e

네임스페이스 또는 토픽 수준에서 메시지 중복 제거 비활성화

브로커 수준에서 메시지 중복 제거를 활성화해도, pulsar-admin namespace set-deduplication 또는 pulsar-admin topics set-deduplication 명령으로 특정 네임스페이스나 토픽에 대해 비활성화할 수 있어요. --disable/-d 플래그를 사용하고 네임스페이스/토픽을 지정하면 돼요.

다음 예시는 네임스페이스 수준에서 메시지 중복 제거를 비활성화하는 방법을 보여줘요.

bin/pulsar-admin namespaces set-deduplication \
public/default \
--disable # or just -d

Pulsar 클라이언트

Pulsar 브로커, 네임스페이스 또는 토픽에서 메시지 중복 제거를 활성화하면, 클라이언트가 성공할 때까지 메시지를 무한히 재시도하도록 만드는 것이 권장돼요. 그렇지 않으면 일부 요청이 시간 초과될 수 있고, 애플리케이션이 요청이 토픽에 성공적으로 추가됐는지 여부를 알 수 없어 순서 보장이 깨질 수 있어요.

따라서 클라이언트 프로듀서에 대해 다음 작업을 완료해야 해요:

  1. 프로듀서에 이름을 지정해요 (필수예요. Pulsar는 프로듀서 이름으로 중복 메시지를 필터링해요).
  2. 메시지 timeout을 0으로 설정해요 (즉, timeout 없음).

Java, Python, C++ 클라이언트의 지침은 서로 달라요.

  • Java 클라이언트
  • Python 클라이언트
  • C++ 클라이언트

메시지 중복 제거가 활성화된 토픽에 보내는 Java 프로듀서에서 순서 보장을 유지하려면, producerName 세터로 프로듀서 이름을 설정하고 sendTimeout 세터로 timeout을 0으로 설정해요.

import org.apache.pulsar.client.api.Producer;
import org.apache.pulsar.client.api.PulsarClient;
import java.util.concurrent.TimeUnit;
PulsarClient pulsarClient = PulsarClient.builder()
        .serviceUrl("pulsar://localhost:6650")
        .build();
Producer producer = pulsarClient.newProducer()
        .producerName("producer-1")
        .topic("persistent://public/default/topic-1")
        .sendTimeout(0, TimeUnit.SECONDS)
        .create();

메시지 중복 제거가 활성화된 토픽에 보내는 Python 프로듀서에서 순서 보장을 깨지 않으려면, producer_name으로 프로듀서 이름을 설정하고 send_timeout_millis로 timeout을 0으로 설정해요.

import pulsar
client = pulsar.Client("pulsar://localhost:6650")
producer = client.create_producer(
    "persistent://public/default/topic-1",
    producer_name="producer-1",
    send_timeout_millis=0)

메시지 중복 제거가 활성화된 토픽에 보내는 C++ 프로듀서에서 순서 보장을 깨지 않으려면, producer_name으로 프로듀서 이름을 설정하고 send_timeout_millis로 timeout을 0으로 설정해요.

#include <pulsar/Client.h>
std::string serviceUrl = "pulsar://localhost:6650";
std::string topic = "persistent://some-tenant/ns1/topic-1";
std::string producerName = "producer-1";
Client client(serviceUrl);
ProducerConfiguration producerConfig;
producerConfig.setSendTimeout(0);
producerConfig.setProducerName(producerName);
Producer producer;
Result result = client.createProducer(topic, producerConfig, producer);

더 알아보기 (Learn more)