메시지 보존과 만료

메시지 보존과 만료 (Message Retention and Expiry)

Pulsar를 오래 쓰다 보면 메시지를 어디까지 쌓아 두고 언제 버릴지 정하는 게 중요해져요. 기본 설정은 모든 미확인 메시지를 백로그에 계속 저장하지만, 보존 정책과 TTL을 네임스페이스 단위로 설정해 이 동작을 바꿀 수 있어요. 이 글에서는 보존 정책(retention), 백로그 할당량, TTL을 각각 설정하고 확인하는 방법을 정리해 드릴게요.

출처: 문서

본문

Pulsar 브로커는 Pulsar를 통과하는 메시지를 처리하는 역할을 담당해요. 여기에는 메시지의 영구 저장도 포함돼요. 기본적으로 각 토픽에 대해 브로커는 적어도 하나의 백로그에 있는 메시지만 보존해요. 백로그(backlog)는 특정 구독에 대한 미확인 메시지 집합이에요. 토픽은 여러 구독을 가질 수 있으므로 여러 백로그를 가질 수 있어요.

그 결과, (기본적으로) 구독이 생성되지 않은 토픽에는 어떤 메시지도 보존되지 않아요.

(더 이상 저장되지 않는 메시지가 반드시 즉시 삭제되는 것은 아니며, 다음 ledger 롤오버까지는 접근할 수 있을 수도 있어요. 클라이언트는 롤오버가 언제 일어날지 예측할 수 없으므로, 롤오버가 불편한 시점에 발생하지 않을 것이라고 기대하는 것은 현명하지 않아요.)

Pulsar에서는 이 동작을 네임스페이스 단위로 두 가지 방식으로 수정할 수 있어요:

  • 보존 정책(retention policy)을 설정해 백로그에 없는 메시지(모든 기존 구독이 확인했거나 구독이 없어서)를 영구 저장할 수 있어요.
  • TTL(Time to Live)을 지정해 지정된 시간 안에 확인되지 않은 메시지를 자동으로 확인(acknowledged) 상태로 만들 수 있어요.

Pulsar의 관리 인터페이스를 사용하면 보존 정책과 TTL을 네임스페이스 단위로 관리할 수 있어요 (따라서 특정 테넌트 안에서, 특정 클러스터 또는 global 클러스터에서).

보존과 TTL은 서로 다른 두 문제를 해결해요 - 메시지 보존: 데이터를 최소 X시간 동안 유지 (확인됐더라도) - TTL: 일정 시간 후 데이터를 버림 (자동 확인으로) 대부분의 애플리케이션은 이 중 하나만 사용하길 원할 거예요.

보존 정책

기본적으로 Pulsar 메시지가 브로커에 도착하면, 모든 구독에서 확인될 때까지 저장되고, 그 시점에 삭제 대상으로 표시돼요. 주어진 네임스페이스의 모든 토픽에 대해 보존 정책을 설정하면 이 동작을 재정의하고 모든 구독에서 이미 확인된 메시지도 보존할 수 있어요. 보존은 크기 제한시간 제한을 모두 기반으로 해요.

아래 다이어그램은 메시지 보존의 개념을 보여줘요.

보존 정책은 Reader 인터페이스를 사용할 때 유용해요. Reader 인터페이스는 확인(acknowledgment)을 사용하지 않으며 메시지가 백로그 안에 존재하지 않아요. Reader 전용 사용 사례에는 보존을 구성하는 것이 필요해요.

네임스페이스의 토픽에 보존 정책을 설정할 때는 크기 제한(defaultRetentionSizeInMB로)과 시간 제한(defaultRetentionTimeInMinutes로)을 둘 다 설정해야 해요. pulsar-admin과 Java에서 보존 정책을 설정하려면 다음 표를 참조하세요.

시간 제한 크기 제한 메시지 보존
-1 -1 무한 보존
-1 >0 크기 제한 기반
>0 -1 시간 제한 기반
0 0 메시지 보존 비활성화 (기본적으로 메시지가 보존되지 않음을 의미)
0 >0 잘못된 조합
>0 0 잘못된 조합
>0 >0 시간이나 크기가 한계에 도달하면 확인된 메시지 또는 활성 구독이 없는 메시지는 보존되지 않아요.

보존 설정은 구독이 없는 토픽의 모든 메시지 또는 모든 구독이 확인한 메시지에 적용돼요. 보존 정책 설정은 구독이 있는 토픽의 미확인 메시지에는 영향을 주지 않아요. 미확인 메시지는 백로그 할당량이 제어해요.

토픽의 보존 한계를 초과하면, 보존된 메시지 집합이 지정된 한계 안으로 다시 들어올 때까지 가장 오래된 메시지가 삭제 대상으로 표시돼요.

기본값

인스턴스 수준에서 defaultRetentionTimeInMinutesdefaultRetentionSizeInMB라는 두 파라미터로 메시지 보존을 설정할 수 있어요. 기본적으로 두 파라미터 모두 0으로 설정되어 있어, 메시지 보존이 비활성화된 상태예요.

두 파라미터에 대한 자세한 내용은 broker.conf 구성 파일을 참조하세요.

보존 정책 설정

pulsar-admin, REST API, Java에서 네임스페이스, 크기 제한, 시간 제한을 지정해 네임스페이스의 보존 정책을 설정할 수 있어요. 그리고 토픽 수준 정책으로 특정 토픽의 데이터 보존 정책을 재정의하지 않는 한, 모든 비파티션 토픽과 토픽 파티션이 네임스페이스에 지정된 데이터 보존 정책을 적용해요.

set-retention 하위 명령을 사용하고, -s/--size 플래그로 크기 제한을, -t/--time 플래그로 시간 제한을 지정해요.

다음 예시에서는 my-tenant/my-ns 네임스페이스의 각 토픽에 대해 크기 제한을 10GB, 시간 제한을 3시간으로 설정해요.

  • 3시간 안에 토픽의 메시지 크기가 10GB에 도달하면 확인된 메시지는 보존되지 않아요.
  • 3시간이 지나면 메시지 크기가 10GB 미만이더라도 확인된 메시지는 보존되지 않아요.
pulsar-admin namespaces set-retention my-tenant/my-ns \
--size 10G \
--time 3h

다음 예시에서는 시간을 제한하지 않고 크기 제한을 1TB로 설정해요. 크기 제한이 보존을 결정해요.

pulsar-admin namespaces set-retention my-tenant/my-ns \
--size 1T \
--time -1

다음 예시에서는 크기를 제한하지 않고 시간 제한을 3시간으로 설정해요. 시간 제한이 보존을 결정해요.

pulsar-admin namespaces set-retention my-tenant/my-ns \
--size -1 \
--time 3h

무한 보존을 하려면 두 값을 모두 -1로 설정해요.

pulsar-admin namespaces set-retention my-tenant/my-ns \
--size -1 \
--time -1

보존 정책을 비활성화하려면 두 값을 모두 0으로 설정해요.

pulsar-admin namespaces set-retention my-tenant/my-ns \
--size 0 \
--time 0

POST /admin/v2/namespaces/{tenant}/{namespace}/retention

참고 보존 정책을 비활성화하려면 크기와 시간 제한을 모두 0으로 설정해야 해요. 크기나 시간 제한 중 하나만 0으로 설정하는 것은 잘못된 조합이에요.

int retentionTime = 10; // 10 minutes
int retentionSize = 500; // 500 megabytes

RetentionPolicies policies = new RetentionPolicies(retentionTime, retentionSize);
admin.namespaces().setRetention(namespace, policies);

보존 정책 가져오기

네임스페이스를 지정해 보존 정책을 가져올 수 있어요. 출력은 retentionTimeInMinutesretentionSizeInMB라는 두 키를 가진 JSON 객체예요.

get-retention 하위 명령을 사용하고 네임스페이스를 지정해요.

예시
pulsar-admin namespaces get-retention my-tenant/my-ns
{
  "retentionTimeInMinutes": 10,
  "retentionSizeInMB": 500
}

GET /admin/v2/namespaces/{tenant}/{namespace}/retention

admin.namespaces().getRetention(namespace);

백로그 할당량

백로그는 bookies가 저장한 토픽의 미확인 메시지 집합이에요. Pulsar는 처리되고 확인될 때까지 모든 미확인 메시지를 백로그에 저장해요.

네임스페이스 수준에서 백로그 할당량을 사용해 백로그의 허용 가능한 크기 및/또는 시간을 제어할 수 있어요. Pulsar는 할당량을 사용해 토픽의 백로그 논리적 크기에 대해 하드 한계를 적용해요. 할당량 한계에 도달하면 백로그 할당량이 경고 정책(예: 프로듀서 예외)을 트리거해요.

아래 다이어그램은 백로그 할당량의 개념을 보여줘요.

백로그 할당량을 설정하는 것은 다음을 설정하는 것을 의미해요:

  • 네임스페이스의 각 토픽에 대한 허용 가능한 크기 및/또는 시간 임계값
  • 임계값을 초과하면 브로커가 어떤 조치를 취할지 결정하는 보존 정책

다음 보존 정책을 사용할 수 있어요:

정책 동작
producer_request_hold 프로듀서가 메시지를 보유하고 클라이언트 구성 sendTimeoutMs가 초과될 때까지 재시도해요.
producer_exception 프로듀서가 메시지를 보내려 할 때 예외를 던져요.
consumer_backlog_eviction 브로커가 백로그 메시지를 버리기 시작해요.

참고 보존의 범위에는 백로그가 포함되므로 보존은 백로그 할당량보다 커야 해요. 그렇지 않으면 둘 다 설정했을 때 Pulsar가 오류를 던질 거예요.

백로그 할당량은 네임스페이스 수준에서 처리돼요. 다음으로 관리할 수 있어요:

크기/시간 임계값과 백로그 보존 정책 설정

네임스페이스, 크기 제한 및/또는 초 단위 시간 제한, 이름 기준 정책을 지정하고 네임스페이스의 모든 토픽에 대한 크기 및/또는 시간 임계값과 백로그 보존 정책을 설정할 수 있어요.

set-backlog-quota 하위 명령을 사용하고 네임스페이스, 백로그를 제한하는 -l/--limit, -lt/--limitTime 플래그의 크기 제한, -p/--policy 플래그의 보존 정책, -t/--type(기본값은 destination_storage)의 정책 유형을 지정해요.

예시
pulsar-admin namespaces set-backlog-quota my-tenant/my-ns \
--limit 2G \
--policy producer_request_hold
pulsar-admin namespaces set-backlog-quota my-tenant/my-ns/my-topic \
--limitTime 3600 \
--policy producer_request_hold \
--type message_age

GET /admin/v2/namespaces/{tenant}/{namespace}/backlogQuotaMap

admin.namespaces().setBacklogQuota(namespace, BacklogQuota.builder()
        .retentionPolicy(RetentionPolicy.producer_request_hold)
        .limitSize(2147483648L)
        .limitTime(60 * 60)
        .build());

백로그 임계값과 백로그 보존 정책 가져오기

네임스페이스에 적용된 크기 임계값과 백로그 보존 정책을 볼 수 있어요.

get-backlog-quotas 하위 명령을 사용하고 네임스페이스를 지정해요. 예시:

pulsar-admin namespaces get-backlog-quotas my-tenant/my-ns
{
  "destination_storage": {
    "limit" : 2147483648,
    "policy" : "producer_request_hold"
  }
}

GET /admin/v2/namespaces/{tenant}/{namespace}/backlogQuotaMap

Map<BacklogQuota.BacklogQuotaType,BacklogQuota> quotas =
  admin.namespaces().getBacklogQuotas(namespace);

백로그 할당량 사용량 모니터링

백로그 할당량 한계와 사용량은 지표토픽 stats를 통해 모두 노출돼요. 이를 통해 예를 들어 백로그 할당량이 한계에 도달하려 할 때 미리 알리는 경고를 정의할 수 있어요.

백로그 할당량 제거

remove-backlog-quota 하위 명령을 사용하고 네임스페이스를 지정하며, t/--type으로 제거할 백로그 유형을 지정해요 (기본값은 destination_storage). 예시:

pulsar-admin namespaces remove-backlog-quota my-tenant/my-ns

DELETE /admin/v2/namespaces/{tenant}/{namespace}/backlogQuota

admin.namespaces().removeBacklogQuota(namespace);

백로그 비우기

pulsar-admin

clear-backlog 하위 명령을 사용해요.

예시
pulsar-admin namespaces clear-backlog my-tenant/my-ns

기본적으로 네임스페이스의 백로그를 비우겠다는 확인 메시지가 표시돼요. -f/--force 플래그로 프롬프트를 무시할 수 있어요.

TTL (Time to Live)

기본적으로 Pulsar는 모든 미확인 메시지를 영원히 저장해요. 많은 메시지가 미확인 상태로 남는 경우 디스크 공간을 크게 사용할 수 있어요. 디스크 공간이 걱정된다면 미확인 메시지가 얼마나 오래 보존될지 결정하는 TTL을 설정할 수 있어요.

TTL 파라미터는 각 메시지에 붙은 스톱워치 같아서, 메시지가 미확인 상태로 남아 있을 수 있는 시간을 정의해요. TTL이 만료되면 Pulsar가 메시지를 자동으로 확인 상태로 이동시켜요 (그래서 삭제 준비가 되는 거예요).

아래 다이어그램은 TTL의 개념을 보여줘요.

네임스페이스의 TTL 설정

set-message-ttl 하위 명령을 사용하고, 네임스페이스와 -ttl/--messageTTL 플래그로 TTL(초)을 지정해요.

예시
pulsar-admin namespaces set-message-ttl my-tenant/my-ns \
--messageTTL 120 # TTL of 2 minutes

POST /admin/v2/namespaces/{tenant}/{namespace}/messageTTL

admin.namespaces().setNamespaceMessageTTL(namespace, ttlInSeconds);

네임스페이스의 TTL 구성 가져오기

get-message-ttl 하위 명령을 사용하고 네임스페이스를 지정해요.

예시
pulsar-admin namespaces get-message-ttl my-tenant/my-ns
60

GET /admin/v2/namespaces/{tenant}/{namespace}/messageTTL

admin.namespaces().getNamespaceMessageTTL(namespace)

네임스페이스의 TTL 구성 제거

remove-message-ttl 하위 명령을 사용하고 네임스페이스를 지정해요.

예시
pulsar-admin namespaces remove-message-ttl my-tenant/my-ns

DELETE /admin/v2/namespaces/{tenant}/{namespace}/messageTTL

admin.namespaces().removeNamespaceMessageTTL(namespace)

네임스페이스에서 메시지 삭제하기

물리적 저장 크기 측면에서 메시지 만료와 보존은 같은 동전의 양면과 같아요.

  • 백로그 할당량과 TTL 파라미터는 Pulsar의 기본 동작이 미확인 메시지를 영구 저장하는 것이므로 디스크 크기가 무한정 커지는 것을 막아요.
  • 보존 정책은 Pulsar가 기본적으로 삭제하려는 메시지를 수용할 저장 공간을 할당해요.

결론적으로 물리적 저장 크기는 백로그 할당량과 보존 크기의 합을 수용할 수 있어야 해요.

메시지 삭제 속도(디스크 공간 해제 속도)는 여러 요인에 의해 결정될 수 있어요.

  • 세그먼트 롤오버 주기: 기본적으로 세그먼트 롤오버 주기는 새 세그먼트가 생성되는 주기예요. 새 세그먼트가 생성되면 이전 세그먼트가 삭제돼요. 기본적으로는 50,000개 엔트리(메시지)를 쓰거나 240분이 지나면 일어나요. 브로커에서 조정할 수 있어요.
  • 엔트리 로그 롤오버 주기: BookKeeper의 여러 ledger는 엔트리 로그에 인터리브(interleave)돼요. 삭제된 ledger를 위해 엔트리 로그가 모두 롤오버되어야 해요. 엔트리 로그 롤오버 주기는 구성 가능하지만 순전히 엔트리 로그 크기에 기반해요. 자세한 내용은 여기를 보세요. 엔트리 로그가 롤오버되면 엔트리 로그를 가비지 컬렉션할 수 있어요.
  • 가비지 컬렉션 간격: 엔트리 로그에는 인터리브된 ledger가 있으므로 공간을 확보하려면 엔트리 로그를 다시 써야 해요. 가비지 컬렉션 간격은 BookKeeper가 가비지 컬렉션을 수행하는 주기예요. 엔트리 로그의 마이너 컴팩션과 메이저 컴팩션과 관련돼요. 자세한 내용은 여기를 보세요.

아래 다이어그램은 소비된 저장 크기가 백로그와 보존에 주어진 한계보다 큰 경우 중 하나를 보여줘요. 보존 한계를 초과하는 메시지도 같은 세그먼트의 다른 메시지가 아직 보존 기간 안에 있으므로 유지돼요.

보존 기간이 없고 백로그가 많지 않다면, 확인된 보존 메시지의 상한은 Pulsar 세그먼트 롤오버 주기 + 엔트리 로그 롤오버 주기 + (가비지 컬렉션 간격 * 가비지 컬렉션 비율)과 같아요.

더 알아보기 (Learn more)