¿Patrones para mantener la consistencia en un sistema distribuido de origen de eventos?

13

Últimamente he estado leyendo sobre fuentes de eventos y realmente me gustan las ideas detrás de esto, pero estoy atascado con el siguiente problema .

Supongamos que tiene N procesos concurrentes que reciben comandos (por ejemplo, servidores web), generan eventos como resultado y los almacenan en un almacén centralizado. Supongamos también que todo el estado de la aplicación transitoria se mantiene en la memoria de los procesos individuales mediante la aplicación secuencial de eventos de la tienda.

Ahora, supongamos que tenemos la siguiente regla de negocios: cada usuario distinto debe tener un nombre de usuario único.

Si dos procesos reciben un comando de registro de usuario para el mismo nombre de usuario X, ambos comprueban que X no está en su lista de nombres de usuario, la regla se valida para ambos procesos y ambos almacenan un evento de "nuevo usuario con nombre de usuario X" en la tienda.

Hemos ingresado en un estado global inconsistente porque se viola la regla de negocios (hay dos usuarios distintos con el mismo nombre de usuario).

En un servidor tradicional de N < - > En un sistema de estilo RDBMS, la base de datos se utiliza como un punto central de sincronización que ayuda a evitar tales inconsistencias.

Mi pregunta es: ¿cómo suelen los sistemas de origen de eventos abordar este problema? ¿Simplemente procesan cada comando secuencialmente (por ejemplo, limitan la cantidad de proceso que puede escribir en la tienda a 1)?

    
pregunta Olivier Lalonde 19.05.2016 - 20:35

2 respuestas

6
  

En un servidor tradicional de N < - > En un sistema de estilo RDBMS, la base de datos se utiliza como un punto central de sincronización que ayuda a evitar tales inconsistencias.

En los sistemas de origen de eventos, el "almacén de eventos" cumple la misma función. Para un objeto de origen de evento, su escritura es un anexo de sus nuevos eventos a una versión particular del flujo de eventos. Entonces, al igual que con la programación concurrente, puede obtener un bloqueo en ese historial al procesar el comando. Es más común que los sistemas de origen de eventos adopten un enfoque más optimista: cargar el historial anterior, calcular el nuevo historial y luego comparar e intercambiar. Si algún otro comando también ha escrito en esa secuencia, entonces su comparación e intercambio fallarán. A partir de ahí, puede volver a ejecutar su comando o abandonar su comando, o quizás incluso fusionar sus resultados en el historial.

La contención se convierte en un problema importante si todos los servidores N con sus comandos M intentan escribir en una sola secuencia. La respuesta habitual aquí es asignar un historial a cada entidad de origen de eventos en su modelo. Así que el Usuario (Bob) tendría un historial distinto del Usuario (Alicia), y las escrituras en una no bloquearán las escrituras en la otra.

  

Mi pregunta es: ¿cómo suelen los sistemas de origen de eventos abordar este problema? ¿Simplemente procesan cada comando secuencialmente?

Greg Young en Validación de conjunto

¿Existe una manera elegante de verificar las restricciones de los atributos de los objetos del dominio sin mover la lógica empresarial a la capa de servicio?

La respuesta breve, en muchos casos, al investigar ese requisito más a fondo revela que (a) es un proxy poco comprendido para algún otro requisito, o (b) que las violaciones de la "regla" son aceptables si se pueden detectar ( informe de excepción), mitigado dentro de una ventana de tiempo, o son de baja frecuencia (por ejemplo: los clientes pueden verificar si un nombre está disponible antes de enviar un comando para usarlo).

En algunos casos, donde su almacén de eventos es bueno para la validación de conjuntos (es decir, una base de datos relacional), entonces implementa el requisito escribiendo en una tabla de "nombres únicos" en la misma transacción que persiste los eventos.

En algunos casos, solo puede hacer cumplir el requisito al tener todos los nombres de usuarios publicados en la misma secuencia (lo que le permite evaluar el conjunto de nombres en la memoria, como parte de su modelo de dominio). - En este caso, dos procesos actualizarán el intento de actualizar "el" historial de flujos, pero una de las operaciones de comparación e intercambio fallará, y el reintento de ese comando podrá detectar el conflicto.

    
respondido por el VoiceOfUnreason 19.05.2016 - 21:11
2

Parece que podría implementar un proceso de negocio ( saga en el contexto de Domain Driven Design ) para el registro de usuarios donde el usuario es tratado como un CRDT .

Recursos

  1. enlace enlace

  2. "CRDT con datos distribuidos Akka" enlace para obtener más información acerca de

    • CmRDT s - CRDT basadas en operaciones
    • CvRDT s - CRTD basadas en estado
  3. Ejemplos de código en Scala enlace . Tal vez el "carrito de la compra" sea el más adecuado.

  4. Tour de Akka Cluster - Akka Distributed Data enlace
respondido por el SemanticBeeng 03.02.2018 - 16:16

Lea otras preguntas en las etiquetas