Pub/Sub으로 보낸 알림이 조용히 사라진 이유
문제 발생
백그라운드 작업 완료 알림을 Pub/Sub으로 보냈습니다.
PUBLISH job:done "{\"id\":123}"대부분 잘 동작했는데, 배포로 컨슈머가 재시작되는 몇 초 동안 발행된 메시지가 통째로 사라졌습니다. 재시도도, 큐에 남는 것도 없었습니다.
원인 분석
설계된 동작입니다. Redis 문서가 전달 의미론을 분명히 적습니다 — Redis의 Pub/Sub은 at-most-once(최대 1회) 메시지 전달 의미론을 가집니다. 이름 그대로 메시지는 전달된다면 한 번 전달된다는 뜻입니다. Redis 서버가 메시지를 보낸 뒤에는 다시 보낼 가능성이 없습니다. 그리고 결정적으로 — 구독자가 (오류나 네트워크 연결 끊김 등으로) 메시지를 처리할 수 없으면 그 메시지는 영원히 사라집니다.
메시지가 어디에도 저장되지 않기 때문입니다. Pub/Sub은 키 공간과 무관하고(문서에 따르면 데이터베이스 번호와도 무관해서 db 10에 발행한 것을 db 1의 구독자가 받습니다), 발행 시점에 연결된 구독자에게만 밀어 넣습니다.
더 강한 보장이 필요할 때의 대안도 문서가 지목합니다 — 애플리케이션에 더 강한 전달 보장이 필요하다면 Redis Streams를 살펴보십시오. 스트림의 메시지는 영속되며 at-most-once와 at-least-once 전달 의미론을 모두 지원합니다.
해결 방안
-
유실돼도 되는 것에만 씁니다. 실시간 시세 표시, 타이핑 중 표시, 캐시 무효화 신호처럼 다음 메시지가 곧 오는 용도가 Pub/Sub의 자리입니다.
-
유실되면 안 되는 것은 Streams로 옮깁니다. 소비자 그룹으로 처리 상태를 추적하면 재시작 중 발행된 메시지도 이어서 받습니다.
-
작업 큐가 필요하면 큐를 씁니다. "완료 알림"이 아니라 "완료 처리"라면 애초에 큐(Streams, 또는 전용 브로커)가 맞습니다.
-
캐시 무효화에도 안전망을 둡니다. 무효화 신호를 놓치면 낡은 데이터가 남습니다 — TTL을 함께 걸어 최악의 경우에도 스스로 만료되게 합니다.
-
패턴 구독의 중복을 인지합니다. 문서 설명대로 채널과 패턴을 동시에 구독하면 같은 메시지를 여러 번 받을 수 있습니다 — 핸들러를 멱등하게 만듭니다.
-
클러스터에서는 sharded Pub/Sub을 검토합니다. 일반 Pub/Sub은 모든 노드로 전파되어 클러스터 버스를 크게 씁니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.