Planteamiento y contexto
Esta pregunta evalúa APIs de backend, almacenamiento de objetos y control de concurrencia. Las solicitudes condicionales de AWS agregan precondiciones a PutObject, CompleteMultipartUpload y CopyObject: la creación puede requerir que una clave no exista, mientras que una actualización puede requerir que el ETag no haya cambiado. El problema central es hacer que el almacenamiento evalúe la verificación junto con la escritura, en lugar de permitir que los clientes realicen un HEAD propenso a condiciones de carrera seguido de un PUT.
Qué está evaluando el entrevistador
Una respuesta sólida separa la creación de la actualización, elige If-None-Match: * o If-Match con el etag-value actual, y mapea una condición fallida a un comportamiento de reintento o fusión. También cubre la finalización multiparte, ETags débiles, resultados de red inciertos y señales de auditoría. Decir "agregar un bloqueo" no explica múltiples procesos ni la recuperación ante fallas.
Preguntas aclaratorias para hacer primero
Semántica de escritura
¿Se trata de un objeto inmutable de escritura única o de una actualización basada en una versión que se leyó? Lo primero utiliza una precondición de existencia; lo segundo necesita un ETag de versión.
Política de conflictos
¿Debería un conflicto devolver 412 para que el cliente vuelva a leer y fusione, o debería abandonarse el intento? Por lo general, un manifiesto o registro no debe sobrescribirse silenciosamente.
Ruta de carga
¿Los objetos pequeños usarán PutObject y los grandes multiparte? Coloque la condición en la solicitud de finalización definitiva y defina el comportamiento ante interrupciones, reintentos y limpieza.
Estructura de respuesta de 30 segundos
"Primero determino si se trata de una creación o de una actualización versionada. La creación utiliza If-None-Match: *, por lo que S3 rechaza atómicamente una clave existente. Una actualización lee el ETag actual y envía If-Match; si el ETag cambió, S3 devuelve 412 y el cliente vuelve a leer o fusiona. Las cargas multiparte aplican la condición en CompleteMultipartUpload. Un tiempo de espera no es prueba de fallo, por lo que consulto el objeto o uso un registro de idempotencia antes de reintentar, y monitoreo los 412, las partes huérfanas y los recuentos de reintentos."
Respuesta detallada paso a paso
Paso 1: Eliminar el patrón check-then-act
Un HEAD seguido de PUT genera condiciones de carrera: dos clientes pueden observar la ausencia y luego escribir. Coloque la precondición en la solicitud de escritura para que el servicio de almacenamiento la evalúe contra el estado actual del objeto.
Paso 2: Elegir la condición
Utilice If-None-Match: * para una creación inmutable; tiene éxito solo cuando no existe una representación actual. Utilice un If-Match fuerte para un objeto existente, permitiendo la escritura solo cuando el ETag es igual a la versión leída. Una discrepancia devuelve 412 y protege el contenido más reciente.
Paso 3: Definir el protocolo de conflictos
No reintente ciegamente un 412. Haga un GET del objeto actual y determine si el cambio del cliente puede fusionarse; de lo contrario, cree un registro de conflicto o una nueva clave. Agregue retroceso exponencial (backoff) y un límite de reintentos para que una clave de alto tráfico no genere una tormenta de reintentos.
Paso 4: Cubrir multiparte y copias
Otro cliente puede crear la misma clave mientras se cargan las partes, por lo que el CompleteMultipartUpload final también necesita la condición. Los flujos de trabajo de copia o reemplazo deben llevar la condición de ETag, mientras que las reglas de ciclo de vida limpian las cargas multiparte abandonadas.
Paso 5: Manejar tiempos de espera y observar
Un tiempo de espera no revela si la escritura se confirmó. Consulte el objeto y el ETag antes de reintentar, y registre un ID de comando del cliente para la intención de creación. Monitoree la tasa de 412, la tasa de reintentos exitosos, las partes huérfanas y la desviación de versiones para verificar que los conflictos se rechacen en lugar de sobrescribirse.
Respuesta de ejemplo de alta calidad
Separaría los archivos de datos inmutables de un registro actualizable. La creación de un archivo de datos utiliza If-None-Match: *, por lo que solo un escritor en la misma clave tiene éxito. El registro se lee con un ETag y se actualiza con If-Match; un 412 activa una relectura y fusión en lugar de sobrescribir otra versión. Una carga grande aplica la condición en CompleteMultipartUpload, y un trabajo de limpieza recupera las cargas fallidas. Tras un tiempo de espera de red, consulto el objeto y el ETag antes de reintentar. S3 proporciona la verificación atómica de conflictos; el cliente es dueño de la política de fusión y de los registros de idempotencia. Lo validaría con métricas de 412, reintentos y partes huérfanas.
Errores comunes
- Error: HEAD para verificar ausencia, luego PUT. → Por qué falla: Dos clientes pueden superar la verificación concurrentemente. → Solución: Utilizar
If-None-Match: *en PUT. - Error: Utilizar
If-None-Matchpara una actualización. → Por qué falla: Significa "no debe existir", no "debe ser igual a la versión que leí". → Solución: Leer un ETag fuerte y usarIf-Match. - Error: Reintentar la solicitud original incondicionalmente tras un 412. → Por qué falla: Puede sobrescribir repetidamente o crear una tormenta de reintentos. → Solución: Releer, fusionar o abandonar con backoff acotado.
- Error: Aplicar la condición únicamente a la primera solicitud multiparte. → Por qué falla: El estado del objeto puede cambiar antes de la finalización. → Solución: Aplicarla de nuevo en
CompleteMultipartUpload.
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Puede tratarse el ETag como un hash de contenido?
No universalmente. El requisito es un validador de versión; los escenarios de carga multiparte y cifrado pueden cambiar la semántica del ETag, por lo que se debe usar el checksum o validador documentado por el servicio para esa operación.
Pregunta de seguimiento 2: ¿En qué se diferencian 412 y 409?
Siga el contrato de la API: 412 significa que una precondición de la solicitud falló y generalmente pide al cliente que vuelva a leer; otro estado de conflicto puede describir el estado del recurso o de la operación. No infiera la semántica únicamente a partir del número.
Pregunta de seguimiento 3: ¿Qué pasa si el cliente no puede fusionar?
Conserve la versión actual y cree un registro de conflicto o una nueva clave para que el propietario del dominio lo resuelva. La sobrescritura silenciosa no es un criterio de éxito.
Pregunta de seguimiento 4: ¿Cómo se prueba la corrección de la concurrencia?
Ejecute creaciones y actualizaciones concurrentes sobre una misma clave, inyecte tiempos de espera, duplicados de finalización multiparte y fallas de limpieza, y luego verifique que a lo sumo una creación tenga éxito, que el contenido antiguo nunca sobrescriba al contenido más reciente y que los registros de auditoría coincidan con los resultados.