이벤트 중복 제거
1) 중복 제거 이유
복수, 네트워크 타임 아웃, 장애 및 과거 데이터의 재생으로 인해 복수가 나타납니다. 그들이 통제되지 않은 경우:- 불변량이 위반됩니다 (이중 직불 결제, 반복 된 이메일/SMS, "두 번 생성 된" 순서).
- 비용 증가 (재 작성/재처리)
- 왜곡 된 분석.
중복 제거의 목표는 종종 demempotency와 함께 허용 가능한 운송 반복으로 일회성 관찰 효과를 제공하는 것입니다.
2) 중복 제거 위치 (계층)
1. Edge/API 게이트웨이-' Idempotency-Keu '/body + 서명으로 명시 적 중복을 차단합니다.
2. 중개인/스트림-키/시퀀스에 의한 논리적 중복 제거, 누락시 통합 (비용으로 인해 덜 자주).
3. 이벤트 수신기 (소비자) -기본 위치: 받은 편지함/키 테이블/캐시.
4. 싱크 (DB/캐시) - 고유 키/UPSERT/버전/압축.
5. ETL/분석-시간별 마감일 및 열 침대의 키.
규칙: 가능한 한 빨리, 그러나 오 탐지의 비용과 재생의 필요성을 고려합니다.
3) 중복 키
3. 1 천연 (선호)
'payment _ id', 'order _ id', 'saga _ id # step', 'colligate _ id # seq'.
안정성과 의미를 보장합니다.
3. 2 복합
'(테넌트 _ id, 유형, 외부 _ id, 버전)' и독특하다 '(user _ id, 이벤트 _ ts _ crount, 페이로드 _ hash)'.
3. 지문 3 개
필드의 결정 론적 부분 집합 (정규화 순서/레지스터), 선택적으로 'HMAC (비밀, 페이로드)' 의 해시.
3. 4 시퀀스/버전
단조로운 'seq' per 골재 (낙관적 차단/버전).
패턴 방지: 사업체와 연결되지 않은 "랜덤 UUI" 는 불가능합니다.
4) 시간 창 및 주문
중복 제거 창-이벤트가 다시 올 수있는 기간 (보통 24-72 시간); 금융-더 긴).
순서가 맞지 않음: 늦게하자. 스트리밍 프레임 워크-이벤트 시간 + 워터 마크.
슬라이딩/수정 창 데드 업: "마지막 N 분 동안 키를 보셨습니까? ».
순서를 인식하는 경우: 마지막으로 처리 된 경우 이중/반복.
5) 데이터 구조 및 구현
5. 1 정확한 회계
Redis SET/STRING + TTL: 'SETNX key 1 EX 86400' → "처음으로-우리는 처리하고 있습니다. 그렇지 않으면 SKIP".
LRU/LFU 캐시 (in-proc): 빠르지 만 휘발성 → 첫 번째 장벽으로 만 더 좋습니다.
SQL 고유 인덱스 + UPSERT: "삽입 또는 업데이트" (demotent effect).
5. 2 대략적인 구조 (확률 론적)
Bloom/Cuckoo 필터: 저렴한 메모리, 오 탐지가 가능합니다. 재무/주문이 아닌 명백한 "잡음" 드롭 (예: 원격 측정) 에 적합합니다.
카운트 민 스케치: "핫" 테이크로부터 보호하기위한 주파수 추정.
5. 3 스트리밍 상태
Kafka Streams/Flink: TTL이있는 키드 스테이트 스토어, 창의 키로 디업; 검문소/복원.
Watermark + 허용 지연 시간: 늦은 이벤트 창을 관리합니다.
6) 거래 패턴
6. 받은 편지함 1 개 (들어오는 테이블)
'메시지 _ id '/키를 저장하고 부작용을 초래합니다:pseudo
BEGIN;
ins = INSERT INTO inbox(id, received_at) ON CONFLICT DO NOTHING;
IF ins_not_inserted THEN RETURN cached_result;
result = handle(event);
UPSERT sink with result; -- idempotent sync
UPDATE inbox SET status='done', result_hash=... WHERE id=...;
COMMIT;
재생은 녹음을보고 효과를 반복하지 않습니다.
6. 보내기
한 번의 거래 기록 및 이벤트 → 게시자가 브로커에게 보냅니다. 소비자로부터 이중을 제거하지는 않지만 "구멍" 은 제외합니다.
6. 3 고유 인덱스/UPSERT
sql
INSERT INTO payments(id, status, amount)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING; -- "create once"
또는 제어 버전 업그레이드:
sql
UPDATE orders
SET status = $new, version = version + 1
WHERE id=$id AND version = $expected; -- optimistic blocking
6. 4 골재 버전 지정
이벤트는 '이벤트 인 경우 적용 가능합니다. 버전 = 집계. 버전 + 1 '. 그렇지 않으면-이중/반복/충돌.
7) 데드 업 및 중개인/스트림
7. 1 카프카
Idempotent Producer는 엔트리 복식을 줄입니다.
거래를 통해 원자 적으로 오프셋 + 출력 레코드를 커밋 할 수 있습니다.
계산: 키당 마지막 값을 저장합니다-사후 결제/통합 (지불이 아님).
소비자 측: 창 키를위한 주 상점/Redis/DB.
7. 2 NATS/제트 스트림
Ack/reducation → 적어도 한 번은. 소비자의 데드 업 (받은 편지함/Redis).
JetStream 시퀀스/소비자 작업을 통해 반복을보다 쉽게 식별 할 수 있습니다.
7. 3 대기열 (토끼/SQS)
가시성 타임 아웃 + 반복 배송 → 키 + 데드 스토어가 필요합니다.
'MessageGroupID '/' DeduplicationID' 가있는 SQS FIFO가 도움이되지만 TTL 창은 공급자가 제한되어 있습니다. 비즈니스에 필요한 경우 키를 더 오래 유지하십시오.
8) 저장 및 분석기
8. 클릭 하우스/빅 쿼리 1 개
창으로 정리: 조건에 따라 'ORDER Ły, ts' 및 'argMax '/' anyLast'.
클릭 하우스:sql
SELECT key,
anyLast(value) AS v
FROM t
WHERE ts >= now() - INTERVAL 1 DAY
GROUP BY key;
또는 "고유 한" 이벤트의 구체화 된 계층 (키/버전별로 병합).
8. 로그 2 개/원격 측정
가장 많이 사용되는 → 네트워크/디스크에서 대략적인 덤프 (Bloom) 를 말합시다.
9) 재 처리, 재생 및 백필
Dedup 키는 재생에서 살아남 아야합니다 (TTL 확장 재생 창).
백필의 경우 온라인 창을 방해하지 않도록 버전 ('key # source = batch2025') 또는 별도의 "leaks" 와 함께 키 공간을 사용하십시오.
결과 아티팩트 저장 (해시/버전) -재생시 "빠른 건너 뛰기" 속도를 높입니다.
10) 측정 및 관찰 가능
'dedup _ hit _ total '/' dedup _ hit _ rate' -잡힌 중복의 비율.
확률 필터에 대한 'dedup _ fp _ rate'.
'창 _ 크기 _ 초' 실제 (원격 측정 늦은 도착).
(PHP 3 = 3.0.6, PHP 4)
(PHP 3 = 3.0.6, PHP 4)
테넌트/키/유형별 프로필: 가장 많이 사용되는 위치와 이유.
확인: '메시지 _ id', 'demempotency _ key', 'seq', 'wing _ id', '동작 = 프로세스' 건너 뛰기 '.
11) 보안 및 개인 정보 보호
PII를 키에 넣지 마십시오. 해시/별명을 사용하십시오.
충돌/위조를 피하기 위해 지문-HMAC (비밀, 표준 _ 페이로드) 에 서명합니다.
키의 저장 시간을 준수 (GDPR 보존) 로 조정합니다.
12) 성능 및 비용
작업 당 대기 시간/비용으로 LRU 내 Redis SQL을 사용합니다.
Redis: 저렴하고 빠르지 만 키와 TTL의 양을 고려하십시오. '테넌트/해시' 로 선명합니다.
SQL: p99에 의해 비싸지 만 강력한 보증과 청중을 제공합니다.
확률 필터: 매우 저렴하지만 FP가 가능합니다. "추가 SKIP" 가 중요하지 않은 경우 사용하십시오.
13) 반 패턴
"우리는 Kafka를 정확히 한 번만 가지고 있습니다. 키가 필요하지 않습니다 "필요-타박상/비즈니스 계층에서.
키에 대해 너무 짧은 TTL → 재생/지연은 두 배를 제공합니다.
글로벌 싱글 디드 업 → 핫스팟 및 SPOF; 세입자/키로 날카롭지 않습니다.
메모리에서만 결제-프로세스 손실 = 테이크 웨이브.
돈/주문에 대한 블룸-허위 긍정은 합법적 인 운영을 박탈 할 것입니다.
일관되지 않은 페이로드 캐논 화-의미가 동일한 메시지에 대한 다른 해시.
순서가 맞지 않는 이벤트를 무시하면 늦은 이벤트에 중복이 잘못 표시됩니다.
14) 구현 점검표
- 자연 키 (또는 복합/지문) 를 정의하십시오.
- dedup 창과 'lateness' 정책을 설정하십시오.
- 선택 수준: 가장자리, 소비자, 싱크; 날카로움을 제공합니다.
- 구현받은 편지함/UPSERT; 흐름의 경우-키 상태 + TTL.
- 대략적인 장벽이 필요한 경우-Bloom/Cuckoo (중요하지 않은 도메인에만 해당).
- 재생 호환성 설정 (TTL 계산/백필 창).
- Metrics 'dedup _ hit _ rate', 충돌 및 창 지연; 임차인 당 대시 보드.
- 게임 데이: 타임 아웃/배상, 재생, 주문 외, 캐시 드롭.
- 문서 페이로드 정식 및 키 버전.
- 핫 키와 긴 창에서로드 테스트를 수행하십시오.
15) 샘플 구성/코드
15. 1 Redis SETNX + TTL (배리어)
lua
-- KEYS[1] = "dedup:{tenant}:{key}"
-- ARGV[1] = ttl_seconds local ok = redis. call("SET", KEYS[1], "1", "NX", "EX", ARGV[1])
if ok then return "PROCESS"
else return "SKIP"
end
15. 2 PostgreSQL 받은 편지함
sql
CREATE TABLE inbox (
id text PRIMARY KEY,
received_at timestamptz default now(),
status text default 'received',
result_hash text
);
-- In the handler: INSERT... ON CONFLICT DO NOTHING -> check, then UPSERT in blue.
15. 3 카프카 스트림
java var deduped = input
.selectKey((k,v) -> v.idempotencyKey())
.groupByKey()
.windowedBy(TimeWindows. ofSizeWithNoGrace(Duration. ofHours(24)))
.reduce((oldV,newV) -> oldV) // first wins
.toStream()
.map((wKey,val) -> KeyValue. pair(wKey. key(), val));
15. 4 플링크 (키 상태 + TTL, 의사)
java
ValueState<Boolean> seen;
env. enableCheckpointing(10000);
onEvent(e):
if (!seen.value()) { process(e); seen. update(true); }
15. 5 NGINX/API 게이트웨이 (가장자리의 Idempotency-Key)
nginx map $http_idempotency_key $idkey { default ""; }
Proxy the key to the backend; backend solves deadup (Inbox/Redis).
16) FAQ
Q: 무엇을 선택해야합니까: 데드 업 또는 순수한 dempotence?
A: 일반적으로 둘 다: 데드 업은 빠른 "필터" (저장) 이고 demempotence는 올바른 효과를 보장합니다.
Q: 어떤 TTL을 넣을까요?
A: 가능한 최대 재전송 시간 + 재고. 일반적으로 24-72 시간; 재무 및 연기 작업-일/주.
Q: 늦은 이벤트를 어떻게 처리합니까?
A: '허용 된 지연 시간' 및 알람 'late _ 이벤트' 설정; 이후 지점-별도의 지점을 통해 (재 컴파일/건너 뛰기).
Q: 전체 원격 측정 스트림을 중복 해제 할 수 있습니까?
A: 예, 대략적인 필터 (Bloom) 는 가장자리에 있지만 FP를 고려하고 중요한 비즈니스 효과에는 적용되지 않습니다.
Q: 백필을 방해하는 데드 업?
A: 백필 기간 동안 키 공간 ('key # batch2025') 을 분리하거나 장벽을 비활성화하십시오. TTL 키는 온라인 창만 커버해야합니다.
17) 총계
중복은 올바른 키, 창 및 상태 구조 + 트랜잭션 패턴 (받은 편지함/전송/UPSERT) 과 순서 및 늦은 이벤트의 신중한 처리입니다. 가장 저렴한 곳에 배치하고, 타박상을 입히고, 'dedup _ hit _ rate' 를 측정하고, 재생/실패를 테스트하십시오.