1 puntos por GN⁺ 2024-11-14 | 1 comentarios | Compartir por WhatsApp

Actualización_2024-11-13

  • En el informe inicial se afirmaba que un consumidor con auto-commit habilitado podía provocar pérdida de datos al confirmar automáticamente el offset devuelto por el poll más reciente.
  • Sin embargo, varios lectores refutaron esto señalando que un consumidor con auto-commit en realidad confirma el offset del poll anterior, no del más reciente.
  • Los resultados de experimentos con el cliente Java de Kafka también respaldan esto, aunque el comportamiento puede variar según el cliente.
  • Se eliminó del informe la afirmación específica sobre auto-commit, y hace falta investigación adicional.

Antecedentes

  • Kafka es un sistema de streaming popular que ofrece replicación, sharding y logs append-only.
  • Bufstream es una solución alternativa a Kafka que prioriza la gobernanza de datos y la eficiencia de costos en entornos de nube.
  • Al igual que Kafka, Bufstream ofrece colecciones de logs parcialmente ordenados llamadas topics, y cada topic se divide en partitions.
  • Bufstream es compatible con clientes estándar de Kafka y está compuesto por agentes, un servicio sin estado que expone la API de Kafka, un object store que almacena los datos, y un servicio de coordinación.
  • Bufstream reduce costos escribiendo el almacenamiento de datos directamente en servicios de object storage, y puede operar sobre VM sin estado con autoescalado.

Seguridad del cliente

  • Bufstream está diseñado para distintas aplicaciones de streaming y establece varias opciones de configuración del cliente para un funcionamiento seguro.
  • Igual que Kafka, usa acks = all por defecto y establece enable.auto.commit = false para evitar pérdida de datos.
  • Usa auto.offset.reset = earliest para que los consumidores puedan observar el log completo.

Transacciones

  • Bufstream soporta el sistema de transacciones de Kafka y ofrece una forma débil de atomicidad mediante una configuración compleja.
  • Los consumidores pueden ejecutarse con niveles de aislamiento read_uncommitted o read_committed, y read_committed evita algunos fenómenos (G1a, G1c).
  • En Kafka, Redpanda y Bufstream ocurre el fenómeno G0, lo que no coincide con los niveles de aislamiento documentados.

Diseño de pruebas

  • Se probó desde Bufstream 0.1.0 hasta 0.1.3 usando la librería de pruebas de Jepsen y Java Kafka Client.
  • Las pruebas evalúan la seguridad de Bufstream inyectando distintos tipos de fallas.

Cola

  • Se diseñó una carga de trabajo de cola ajustada al modelo de datos de Kafka para usarla en Bufstream.
  • Cada proceso lógico ejecuta clientes de productor, consumidor y administrador, y envía registros para distintas claves.

Abortos

  • A partir de resultados inesperados, se diseñó una carga de trabajo que aborta transacciones y rastrea offsets.
  • Los offsets posteriores a transacciones abortadas se clasificaron en cuatro categorías: avance, rebobinado, más rebobinado, y otros.

Resultados de Bufstream

Consumidor detenido (#1)

  • Desde 0.1.0 hasta 0.1.3-rc.8 ocurrió un problema en el que las llamadas a consumer.poll() devolvían inmediatamente sin retornar registros.
  • Bufstream resolvió el problema en 0.1.3-rc.6 actualizando la caché.

Productor y consumidor detenidos (#2)

  • Incluso en 0.1.3-rc.6 ocurrieron problemas en los que fallaba la llamada InitProducerId o la llamada listOffsets.
  • Bufstream resolvió el problema agregando lógica adicional de polling.

Offset 0 incorrecto (#3)

  • Desde 0.1.0 hasta 0.1.3-rc.2 ocurrió un problema en el que se asignaba incorrectamente el offset 0.
  • Bufstream resolvió este problema en 0.1.3-rc.6.

Pérdida de escrituras transaccionales (#4)

  • En 0.1.2 ocurrió un problema en el que desaparecían registros de transacciones confirmadas.
  • Bufstream resolvió el problema en 0.1.3-rc2.

Pérdida de escrituras por filtrado del lado del servidor (#5)

  • En 0.1.3-rc.8 ocurrió pérdida de escrituras como respuesta a fallas menores.
  • Bufstream resolvió el problema en 0.1.3-rc.12.

Resultados de Kafka

Mensaje de error engañoso (KIP-588)

  • Existe un problema en el que ProducerFencedException también ocurre con timeouts transaccionales.
  • Se recomienda al equipo de Kafka cambiar el mensaje de error.

Posibilidad de espera infinita al cerrar el consumidor (KAFKA-17734)

  • Existe un problema en el que la llamada Consumer.close() puede quedarse esperando indefinidamente en network IO.
  • El problema se rastrea mediante KAFKA-17734.

Offsets de consumidor impredecibles tras un fallo de transacción (KAFKA-17582)

  • Falta documentación sobre el comportamiento esperado de los offsets del consumidor cuando falla una transacción.
  • Después de una transacción abortada, el consumidor puede rebobinar su offset o seguir avanzando.

1 comentarios

 
GN⁺ 2024-11-14
Comentarios en Hacker News
  • Mientras investigaban problemas en Kafka, se descubrieron escrituras invisibles. Esto plantea la posibilidad de que mensajes Produce retrasados queden incluidos en transacciones futuras y violen las garantías transaccionales. También existe la sospecha de que el cliente Java de Kafka podría reutilizar números de secuencia cuando una solicitud expira por timeout. Hacen falta más pruebas sobre Kafka

    • Parece que Jepsen debería volver a hacer una investigación profunda sobre Kafka. La última fue en 2013, y es probable que se encuentren muchos problemas en el propio Kafka. Problemas como "confirmar una escritura y luego descartarla en silencio" parecen muy graves
  • Al ver la página del producto de Bufstream, surge la duda de cómo pueden ser compatibles estas dos afirmaciones

    • Bufstream puede ejecutarse completamente dentro de un AWS o GCP VPC, lo que permite controlar por completo los datos, los metadatos y el tiempo de actividad. Bufstream nunca se comunica con el exterior
    • El precio de Bufstream es simple: $0.002 por GiB sin comprimir (aprox. $2 por TiB). No hay cobros por cores, agentes ni por llamada
    • No parece que vayan a operar todo el negocio basándose en un sistema de confianza
  • Sorprende la función de auto-commit de Kafka

    • Un consumidor de Kafka puede hacer commit automático de offsets independientemente de si realmente se procesaron o no. Eso significa que, si el consumidor hace poll de registros, hace commit y luego falla, los registros pueden perderse
    • Según la documentación, si auto-commit está activado, cada vez que se llama al método poll los offsets de los mensajes devueltos quedan listos para hacerse commit automáticamente. Si el procesamiento de mensajes no ha terminado, existe el riesgo de perder el avance de esos mensajes en caso de una falla
    • Ajustar el intervalo de auto-commit ayuda con el procesamiento duplicado, pero no con la pérdida de mensajes
  • El protocolo de transacciones de Kafka tiene problemas fundamentales y necesita corregirse

    • Excelente trabajo de investigación y redacción
  • Me pregunto si Kyle ha revisado NATS Jetstream

  • No pude encontrar el proyecto de bufstream en GitHub. Me pregunto si alguien tiene alguna pista

  • Después de leer las publicaciones de blog y la documentación relacionadas, Kafka define "exactly-once delivery" como una propiedad de la operación de "leer-procesar-escribir". Parece que sería mejor describirlo como una transacción

  • La frase "las transacciones pueden observarse parcialmente o por completo" parece que debería leerse como "los consumidores pueden observarlas parcial o completamente"

  • Me pregunto para qué se usa este software. ¿Instrumentación? ¿Caja negra?