Deduplication
Qué es
La deduplicación reconoce varias representaciones de la misma unidad lógica y suprime entregas, intentos o efectos repetidos en una frontera determinada. Es un mecanismo basado en identidad y memoria: debe decidir qué significa «ya visto» y cuánto tiempo conserva esa información.
Se diferencia de idempotencia. Una operación idempotente admite repetir sin multiplicar su efecto relevante; la deduplicación reconoce y evita una repetición. Pueden colaborar, pero ninguna definición depende de que exista la otra.
Qué problema resuelve
Los reintentos de publicación, las reentregas de at-least-once y el replay pueden presentar nuevamente trabajo ya aceptado. Suprimirlo evita cómputo innecesario o protege un efecto que no tolera ejecución repetida.
El mecanismo también tiene riesgos: suprimir dos operaciones distintas por error produce pérdida, y olvidar una operación previa permite un duplicado.
Cómo funciona
Identidad y alcance
Una clave podría ser (consumidor, tenant, id_de_operacion). Incluir el consumidor permite que dos aplicaciones procesen legítimamente el mismo evento; incluir el tenant evita mezclar identidades de clientes distintos.
Un ID de transporte puede identificar una publicación sin representar una intención de negocio. Si el productor crea otro ID al reintentar, el consumidor puede necesitar una identidad de dominio adicional. Un hash del payload tampoco distingue siempre dos acciones legítimas con los mismos parámetros.
Memoria, concurrencia y commit
«Consultar si existe; si no, ejecutar; luego guardar» tiene dos carreras: dos workers pueden observar ausencia, y un crash puede ocurrir entre efecto y registro.
Cuando ambos caben en una base de datos transaccional, un esquema lógico es:
BEGIN
reservar clave con restricción UNIQUE
si ya hay un resultado confirmado: no repetir el efecto
si este intento obtiene la reserva: aplicar efecto local
registrar resultado
COMMIT
confirmar al emisorLa reserva pertenece a la misma transacción; otro intento espera o resuelve el conflicto según el almacenamiento. Si se aborta, ni efecto ni registro quedan confirmados. El ejemplo presupone unicidad y aislamiento que hagan válida esa coordinación; no es un algoritmo para cualquier store.
Registrar «completado» antes del efecto puede perder trabajo. Registrarlo después, sin atomicidad, puede duplicarlo. Un efecto externo queda fuera de la transacción: aparece el Dual-Write Problem.
Retención
La memoria durable debe cubrir reintentos, retrasos y replays admitidos. Al expirar una clave, un duplicado tardío puede volver a ejecutarse. Una ventana finita protege durante esa ventana, no para siempre.
Azure Service Bus ilustra esa semántica: su detección compara identidades de publicaciones dentro de una ventana configurada. Esto no acredita procesamiento de aplicación ni protege por sí solo efectos externos. Azure Service Bus: duplicate detection.
Ejemplo
El evento credito-17 suma 10 a una proyección de saldo. El consumidor confirma, en una transacción, el incremento y (proyeccion-saldo, credito-17) como procesado. Cae antes del ack.
La reentrega encuentra el registro confirmado y no incrementa otra vez. Si cayó antes del commit, la transacción no dejó ninguno de los dos cambios y otro intento puede procesar. El incremento no se volvió naturalmente idempotente: el contrato que lo envuelve suprime repeticiones mediante identidad y atomicidad local.
Si el handler también envía un correo fuera de la transacción, el ejemplo no garantiza un solo correo.
Cuándo usarlo
Es útil cuando existe identidad estable y verificable, la repetición resulta costosa o el efecto natural no es idempotente. Puede ubicarse en productor, transporte o consumidor; cada posición protege un alcance distinto.
Algunas plataformas reconocen publicaciones repetidas mediante identidad de productor y número de publicación. Es una alternativa a almacenar cada ID individual con un contrato propio de secuencias. RabbitMQ Streams: message deduplication.
Cuándo NO usarlo
No usarlo para ocultar identidades ambiguas ni fusionar eventos distintos. No confiar en memoria volátil si la promesa debe sobrevivir al reinicio.
Un filtro probabilístico puede responder «ya visto» para una clave nueva. No debería ser la única autoridad si descartar trabajo válido es inaceptable: puede acelerar consultas contra memoria exacta. Aceptar esos falsos positivos como descartes es otra decisión.
Trade-offs y alternativas
Hay costos de escritura, almacenamiento, contención y limpieza. Más retención amplía la protección y aumenta el estado. Una política basada solo en la mayor secuencia recibida puede descartar trabajo legítimo fuera de orden si el contrato no garantiza esa secuencia.
Diseñar el efecto como idempotente puede reducir la dependencia de una lista de IDs, pero sigue necesitando identidad, concurrencia y efectos definidos. Deduplicar no garantiza orden, entrega eventual ni éxito; exactly-once-semantics requiere evaluar esas condiciones adicionales.
Relaciones
- idempotency explica la propiedad del efecto, independiente de la supresión.
- at-least-once presenta las fuentes comunes de repeticiones.
- delivery-guarantees delimita dónde se cuenta cada unidad.
- dual-write-problem muestra por qué memoria de procesamiento y efecto necesitan coordinación.
- exactly-once-semantics combina mecanismos dentro de un contrato completo.