Colección de citas famosas - Consulta de diccionarios - ¿No es solo un sitio web de reserva de entradas? ¿Cuál es la complejidad de la idea de diseño del modelo central de 12306?

¿No es solo un sitio web de reserva de entradas? ¿Cuál es la complejidad de la idea de diseño del modelo central de 12306?

El objetivo de este artículo no es cómo resolver el problema de la alta concurrencia, sino cómo analizar cuál debería ser el modelo ideal de 12306 desde una perspectiva empresarial. Los artículos que actualmente hablan de 12306 en Internet parecen ser los mismos. Solo hablan de tecnología y no de análisis empresarial ni de cómo modelar. Por eso quiero escribir sobre mi diseño y compartirlo con todos.

1. Resumen de requisitos

12306 El principal problema que debe resolver este sistema es la venta de entradas online. Hay dos roles involucrados en el uso del sistema: el usuario y el Ministerio de Ferrocarriles. El principal atractivo de los usuarios es comprobar los billetes restantes y comprarlos; el principal atractivo del Ministerio de Ferrocarriles es vender billetes. La compra y venta de billetes son en realidad un escenario. Para los usuarios, es la compra de billetes, y para el Ministerio de Ferrocarriles, es la venta de billetes. Por lo tanto, necesitamos diseñar un sistema de sitio web en línea para resolver las tres demandas principales de los usuarios: consultar los boletos restantes, comprar boletos y vender boletos del Ministerio de Ferrocarriles. Parece que estas 3 escenas giran en torno a los billetes de tren.

Consultar billetes restantes: El usuario introduce las tres condiciones de origen, destino y fecha de salida para consultar posibles trenes. El usuario puede ver el nombre de la estación por la que pasa cada tren y los billetes restantes para cada asiento. . cantidad.

Compra de boletos: la compra de boletos se divide en dos etapas: reserva de boletos y pago. Este artículo se centra en analizar el diseño del modelo y las ideas de implementación de la reserva de boletos.

De hecho, existen muchas otras necesidades, como establecer cuotas de venta de asientos para diferentes trenes y establecer diferentes límites para diferentes secciones. Pero en comparación con las dos necesidades anteriores, creo que esta necesidad es relativamente menor.

2. Análisis de la demanda

De hecho, 12306 también es un sistema de comercio electrónico y parece que los productos son boletos. Porque si un boleto se considera una mercancía, entonces comprar un boleto es similar a comprar una mercancía. Entonces cada boleto tiene inventario y la mercancía también tiene el concepto de inventario. Pero si lo pensamos detenidamente, encontraremos que 12306 es mucho más complicado, porque no podemos determinar todos los votos de antemano. Si debemos determinarlo, solo podemos usar el método exhaustivo.

Tomemos como ejemplo el tren de alta velocidad G71 desde Beijing Oeste hasta Shenzhen Norte (aquí solo se considera la dirección sur, no Shenzhen Norte hasta Beijing Oeste, que es otro tren llamado G72). 17 Hay 3 estaciones (Beijing Oeste es la Estación 01, Shenzhen Norte es la Estación 17), 3 tipos de asientos (Business, Primera Clase, Segunda Clase). A primera vista, ¿no son estos sólo 3 productos? Asiento Business G71, Asiento de Primera Clase G71, Asiento de Segunda Clase G71. La mayoría del personal técnico que rocía fácilmente 12306 (incluidos los expertos y directores de tecnología de algunas empresas medianas) tropezó aquí por primera vez. De hecho, G71 tiene 136*3=408 productos (408 SKU). De la siguiente manera:

Si vendes un tren que sale de Beijing Oeste, hay 16 formas de venderlo (porque hay 16 estaciones detrás), Beijing Oeste a: Baoding, Shijiazhuang, Zhengzhou, Wuhan, Changsha. , Cantón, Humen, Shenzhen. . . . Todos son un producto independiente. Del mismo modo, si subes al autobús en Shijiazhuang, hay 15 formas posibles de bajar. Por analogía, contando las estaciones en las que te bajas, hay 136 tipos de billetes: 16+15+14. .... +2+1=136. Cada tipo de billete tiene 3 tipos de asientos y hay 408 productos por billete.

Para facilitar la discusión posterior, primero aclaremos ¿qué es un ticket?

La información principal de un billete incluye: hora de salida, lugar de salida, destino, número de tren y número de asiento. La persona que posee el billete tiene un bono, lo que significa que puede tomar un determinado número de asiento en un determinado tren de un determinado lugar a un determinado lugar. Por tanto, un billete es un bono para el usuario y una promesa para el Ministerio de Ferrocarriles; ¿qué significa para el sistema? no tengo idea. Por eso es necesario analizar el modelado de negocio y dominio, sigamos pensando.

Después de comprender la información básica del billete, veamos cuántos billetes se pueden vender para el tren de alta velocidad G71.

Permítanme explicarles antes de comentar que el número físico de asientos en un tren (los billetes de pie también pueden considerarse como un tipo de asiento, porque los billetes de pie también tienen cuotas de cantidad) no es igual a la coordinación máxima disponible. . No es posible que todos los asientos físicos se vendan a través del sitio web 12306, sino solo una parte, como el 40%. El resto se seguirá vendiendo sin conexión.

No sólo eso, puede que haya más gente subiendo al autobús en unas estaciones y menos gente en otras, por lo que también configuraremos diferentes límites para distintos tramos.

Por ejemplo, D31 tiene 765 boletos desde Beijing Sur a Shanghai***, 260 boletos desde Beijing Sur, 80 boletos desde Yangliuqing y 76 boletos desde Tai'an. Si los 80 boletos en Yangliuqing están agotados, se mostrará que no hay boletos. Incluso si hay boletos en otras estaciones, se mostrará que no hay boletos. Definitivamente, cada tren tendrá varias cuotas de asientos y configuraciones de límites. No puedo predecir esta configuración en este momento, pero he encapsulado estas reglas en la raíz agregada del tren. Todas las estrategias de configuración se basan en el tipo de asiento, configurado por sitio e intervalo. En cuanto a la configuración abstracta de tickets, creo que hay tres tipos principales:

El número máximo de tickets permitidos en una determinada sección;

El número mínimo de tickets permitidos en una determinada sección ;

p>

¿Cuál es el número máximo de billetes que se pueden abordar en una determinada estación?

Cuando el usuario solicita un boleto, la sección especificada por el usuario se compara con estas tres condiciones de configuración. Si se cumplen las tres condiciones, se puede emitir el boleto. Si no está satisfecho, se considerará que no tiene votos. He aquí un ejemplo:

ABCDEFG, estos son todos los sitios. La cuota total de asientos es 100. Suponiendo que hay menos personas subiendo al autobús en la estación B y bajando en la estación E, entonces podemos establecer que solo se puedan emitir 10 boletos como máximo en la sección BE. Por tanto, siempre que la reserva de billetes del usuario se realice dentro de este apartado, se emitirán un máximo de 10 billetes. Para otro ejemplo, un tren tiene una cuota total de asientos de ***100 y esperamos que haya al menos 80 billetes de viaje completo. Entonces solo necesitamos configurar al menos 80 billetes para el tramo AG. Entonces cualquier solicitud de reserva de billetes, si es para un subrango, no puede exceder de 100-80, es decir, 20 billetes. Estas dos condiciones deben cumplirse al mismo tiempo antes de que se permita la emisión de billetes.

Sin embargo, no importa cómo se establezcan las cuotas y los límites, siempre los configuramos para un determinado tren. Estas configuraciones son solo algunas condiciones de juicio adicionales (reglas comerciales) para la emisión de boletos interna del tren y no afectan el precio. Núcleo del modelo de tren: estado y funciones de exposición externa. Por lo tanto, en aras de la claridad en la discusión de este artículo, mis discusiones posteriores no involucrarán la cuestión de cuotas y límites, sino más bien que cualquier sección puede disfrutar del número físico máximo de asientos en el tren.

Y, para facilitar la discusión de temas, hemos reducido el número de sitios de discusión. Supongamos que cierto tren tiene cuatro estaciones A, B, C y D. Cuando la persona 001 compra la sección A y B, el sistema le asignará un asiento a 001. Cuando se inicia el sitio, el sistema puede considerar que el asiento x está disponible. Por lo tanto, concluimos que el mismo asiento puede vender dos boletos, AB y BC, al mismo tiempo. A través de este sencillo análisis, sabemos que un tren sólo tiene un número limitado de asientos, como 1.000 asientos. Pero hay muchas más de 1.000 entradas que se pueden vender.

Tomemos las cuatro estaciones A, B, C y D como ejemplo. Si el tren tiene un total de 1000 asientos, entonces AB puede vender 1000 asientos y BC también puede vender 1000 asientos. , CD También puedes vender 1.000 copias. Esto significa que, en teoría, se pueden vender un máximo de 3.000 entradas. Pero si cambiamos el método de venta y todos compran boletos ABCD, lo que significa que todos los boletos pasan por todas las estaciones, entonces solo se podrán vender 1000 boletos como máximo. En el escenario real, debe estar entre 1000 y 3000. Y el tren G71 actual tiene 17 estaciones. Entonces, ¿cuántos billetes se pueden vender? Probablemente lo olvides. En teoría, el tramo de línea formado entre dos de estas 17 estaciones se puede vender como billete. No soy bueno en matemáticas, así que no puedo resolverlo muy bien. Por favor, que alguien bueno en matemáticas me ayude a hacer los cálculos, jaja.

A través del análisis anterior, sabemos que la esencia de un billete es un determinado intervalo (un segmento de línea) de un determinado tren, y este intervalo contiene varias estaciones. Luego también descubrimos que mientras los intervalos no se superpongan, no habrá competencia por los asientos y se podrán reciclar, es decir, se podrán vender por adelantado al mismo tiempo.

Además, después de un análisis más profundo, también encontramos que existen 4 relaciones entre intervalos:

Sin superposición

Superposición parcial

; p>

Superposición completa;

Superposición.

Ya hemos comentado el caso de la no superposición, y la cobertura también es un tipo de superposición. Así que descubrimos que si hay superposición, por ejemplo, dos intervalos se superponen, los intervalos superpuestos (que pueden presumir de tener uno o más sitios) están compitiendo por los asientos. Porque suponiendo que un tren tiene 100 asientos, cada intervalo atómico (la línea que conecta dos estaciones adyacentes) puede superponerse hasta 99 veces.

Entonces, después del análisis anterior, ¿sabemos cuáles son las reglas comerciales básicas para vender un billete para un viaje en tren? Es decir: el número de superposiciones de cada intervalo atómico incluido en este billete más 1 no puede exceder el número total de asientos del tren. De hecho, el número de superposiciones + 1 también puede entenderse como el grosor del segmento de línea.

3. Diseño del modelo

Analicé la esencia de los tickets anteriores. A continuación, echemos un vistazo a cómo diseñar un modelo para realizar rápidamente la demanda de compra de boletos. La atención se centra en cómo diseñar la lógica de agregación de productos y reducción de inventario.

La idea del comercio electrónico tradicional

Si sigue la idea del comercio electrónico ordinario, diseñe los tickets (intervalo de sitio) como productos básicos (raíz agregada ) y luego diseñar la cantidad de inventario para los tickets. Personalmente creo que es muy malo. Porque, por un lado, hay muchas raíces agregadas (el G71 anterior tiene 408, por otro lado, incluso si se enumeran, la compra de un boleto definitivamente afectará la cantidad de inventario de muchas otras raíces agregadas (siempre que así sea); se ve afectado parcial o completamente los intervalos superpuestos). Es difícil evaluar la complejidad de procesar una orden de este tipo. Además, es necesario realizar tantas actualizaciones de raíz agregadas en una sola transacción. ¿No es esto vergonzoso para la base de datos? Además, este diseño inevitablemente provocará una gran cantidad de conflictos de transacciones concurrentes, lo que puede provocar un punto muerto en la base de datos.

En resumen, creo que este es un error de diseño típico en el modelo de dominio, que conduce a conflictos de alta concurrencia y dificultades para implementar la persistencia de datos. O si desea resolver el problema de concurrencia, solo puede hacer cola para el procesamiento de un solo subproceso, pero aún no puede resolver la vergonzosa situación de modificar una gran cantidad de raíces agregadas en una transacción.

Escuché que 12306 usa una base de datos en memoria de alta gama como Pivotal Gemfire. No sé mucho sobre esto. No puedo imaginar cómo pueden lograr una fuerte coherencia de datos entre los boletos dentro de un tren sin usar una base de datos en memoria (es decir, garantizar que todos los boletos vendidos cumplan con las reglas comerciales discutidas anteriormente). Por lo tanto, personalmente creo que este diseño se basa en una mentalidad fija y trata los billetes de tren como productos de comercio electrónico ordinarios. Por lo tanto, a veces tenemos que confiar en la experiencia al diseñar y no debemos limitarnos a la experiencia pasada. Realmente no es fácil. La clave es realizar un análisis en profundidad basado en escenarios comerciales específicos e intentar abstraer la esencia. problema, para que podamos prescribir el medicamento adecuado. ¿Hay otras ideas de diseño?

Mi opinión

1. Diseño de agregación

A través del análisis anterior, sabemos que, de hecho, creo que cualquier compra de boletos es para un tren determinado. El número es la raíz agregada responsable de procesar las reservas de billetes. ¿Veamos qué información contiene un viaje en tren? Un tren incluye:

Nombre del tren, como G71;

Número de asientos El número real de asientos se dividirá en tipos, como 20 asientos ejecutivos y 200 de primera clase. asientos y asientos de segunda clase 500; para simplificar el problema aquí, podemos ignorar temporalmente el tipo. Creo que este tipo no afecta las decisiones de diseño del modelo central. Cabe señalar que el número de escaños aquí no debe interpretarse como el número real de escaños físicos. Es probable que sea menor que el número real de escaños. Porque nos es imposible vender todos los asientos de un tren en línea a través de 12306, pero solo una parte. El número específico a vender debe ser designado manualmente por el personal.

Información de la estación pasada (incluido el ID de la estación, el nombre de la estación, etc.), nota: el número de tren también registrará la relación secuencial entre estas estaciones;

Hora de salida lea GRASP Nueve; Los estudiantes del patrón Especialista en Información en el Gran Patrón deben saber que asignar responsabilidades a clases que poseen la información necesaria para desempeñar esa responsabilidad.

En nuestro escenario, el tren tiene toda la información para la emisión de un billete, por lo que debemos darle la responsabilidad de la emisión del billete al tren.

Además, los estudiantes que han estudiado DDD deben saber que existe un principio en el diseño de agregaciones, que es: fuerte coherencia dentro de la agregación y coherencia final entre agregaciones. Después del análisis anterior, sabemos que generar un boleto en realidad afecta el número disponible de muchos otros boletos que se cruzan con el segmento de línea correspondiente a este boleto. Debido a que toda la información del sitio está dentro de la agregación de trenes, todos los intervalos atómicos se pueden mantener dentro de la agregación de trenes, así como la cantidad de boletos disponibles para cada intervalo atómico (equivalente al número de inventario). Cuando el número de billetes disponibles para un intervalo atómico es 0, significa que los billetes de tren para ese intervalo se han agotado. Por lo tanto, podemos utilizar completamente el número de tren como raíz agregada para garantizar una fuerte coherencia al actualizar el número de votos disponibles en todos los intervalos atómicos al emitir boletos. Para la raíz agregada del viaje, esto es muy simple, porque son solo unas pocas operaciones de memoria simples y el consumo de tiempo se puede ignorar. Si un tren tiene cuatro estaciones ABCD, entonces existen tres intervalos atómicos. Para el G71, es 16.

2. ¿Cómo juzgar si se puede emitir un billete?

Según el diseño de agregación anterior, la lógica de deducir el inventario al emitir boletos es:

De acuerdo con la información del pedido, obtenga el lugar de salida y el destino, y luego obtenga todos los artículos. en este rango intervalo atómico. Luego intente reducir en 1 el número de boletos disponibles en cada intervalo atómico. Si todos los intervalos atómicos se reducen lo suficiente, la compra del boleto se realiza correctamente; de ​​lo contrario, la compra del boleto falla y se le indica al usuario que el boleto se ha agotado; ¿No es muy sencillo? Conociendo la lógica de emisión de boletos, la lógica del reembolso de boletos es muy simple: suma 1 al número de votos disponibles en todos los rangos atómicos de este boleto y listo. Si lo pensamos desde la perspectiva del grosor del segmento de línea, cuando se emite el boleto, el grosor de cada intervalo atómico es +1, y cuando se reembolsa el boleto, es menos uno. Es la operación contraria, pero la esencia es la misma.

Entonces, a través de esta idea, controlamos el procesamiento de una reserva de boletos en una raíz agregada y utilizamos la característica de coherencia sólida en la raíz agregada para garantizar la coherencia sólida del procesamiento de boletos. y elimina la posibilidad de conflictos de concurrencia. El diseño tradicional de comercio electrónico que utiliza tickets como raíz central de agregación para productos similares me pareció inapropiado a primera vista. Porque esto viola el principio de que DDD enfatiza que las raíces agregadas deben garantizar una fuerte consistencia, y Saga garantiza la consistencia final entre las raíces agregadas.

Hay otro concepto muy importante sobre el que me gustaría compartir mi opinión, que es la relación entre escaños y secciones. Porque unos amigos me dijeron que al considerar el número de asiento, aunque se puede reducir en 1, el número de asiento debe ser el mismo. Creo que los asientos se comparten globalmente y no tienen nada que ver con la sección (tal vez lo entendí completamente mal, corríjanme). El asiento es un concepto físico después de que un usuario compra con éxito un boleto, habrá un asiento menos. Un boleto solo corresponde a un asiento, pero un asiento puede corresponder a varios boletos, mientras que el intervalo es un concepto lógico. : 1) indicar la salida y el destino del billete; 2) registrar el importe disponible del billete. Si el intervalo se puede conectar (es decir, la cantidad disponible de cada intervalo atómico en el intervalo es mayor que 0), significa que se permite un asiento. Por tanto, creo que los asientos y los billetes (rango) son conceptos bidimensionales.

3. ¿Cómo asignar asientos a los billetes?

Creo que la raíz de agregación de trenes debería mantener todos los boletos vendidos para el tren. La esencia de los boletos vendidos es la relación correspondiente entre la sección y el asiento. Cuando el sistema procesa la reserva de boletos, el usuario envía un rango. Por lo tanto, el sistema debe hacer dos cosas:

Primero determinar si hay asientos disponibles según la sección;

Si hay asientos disponibles, luego usar el algoritmo para seleccionar un asiento disponible. ;

Cuando obtienes un asiento disponible, puedes generar un boleto y luego guardarlo en la raíz agregada del tren. Aquí tienes un ejemplo:

Supongamos que la situación actual es que hay 3 asientos y 4 estaciones:

Asientos: 1,2,3

Sitio: abcd

Método de venta de entradas 1:

Entrada 1: ab, 1

Entrada 2: bc, 2

Entrada 3: cd,3

Ticket 4: ac,3

Ticket 5: bd,1

Este método de selección de asientos debería ser más eficiente, porque siempre se da prioridad Obtener asientos del grupo de asientos y reciclar los billetes reutilizables únicamente como último recurso.

Los dos votos 4 y 5 anteriores son el resultado de considerar el reciclaje.

Método de venta de entradas 2:

Entrada 1: ab, 1

Entrada 2: bc, 1

Entrada 3: cd, 1

Ticket 4: ac, 2

Ticket 5: bd, 3

Este método de selección de asientos debería ser relativamente ineficaz, porque siempre se da prioridad. escaneará para ver si hay asientos reciclables, pero siempre es más costoso escanear y obtener boletos directamente del grupo de asientos.

Los dos votos 2 y 3 anteriores son el resultado de considerar el reciclaje.

Sin embargo, el algoritmo de dar prioridad a la obtención de boletos del grupo de asientos es defectuoso, es decir, aunque en el primer paso se juzga que hay un asiento disponible, es posible que el asiento no sea el mismo. durante todo el recorrido. Ejemplo:

Supongamos que la situación actual es que hay 3 asientos y 4 estaciones:

Asientos: 1,2,3

Sitio: abcd

p>

Método de venta de entradas 3:

Entrada 1: ab, 1

Entrada 2: bc, 2

Entrada 3: cd, 3

Ahora si alguien quiere comprar una entrada para publicidad, los asientos disponibles son 2 o 3. Pero ya sean 2 o 3, el pasajero deberá cambiar de asiento a mitad del camino. Por ejemplo, si le vende el asiento 2, se sentará en el asiento 2 cuando ab, pero se sentará en el asiento 1 cuando vaya bc. De lo contrario, cuando la persona con el billete 2 suba al autobús, se encontrará con que el asiento 2 ya está ocupado. Sin embargo, mediante el algoritmo que prioriza el reciclaje, no existe tal problema.

Entonces, a partir del análisis anterior, también sabemos cómo escribir el algoritmo de selección de asientos, que consiste en utilizar un algoritmo que prioriza el reciclaje de asientos. Creo que no importa cómo diseñemos el algoritmo aquí, no afectará la situación general, porque todo esto sucede solo dentro de la raíz agregada del tren. Esta es la ventaja de diseñar la raíz agregada con anticipación y aclarar a qué objeto pertenece la responsabilidad de emitir el boleto. a.

4. Resumen del análisis del modelo

Creo que el ticket no es la raíz agregada central. El ticket es solo el resultado de la emisión de un ticket, solo un cupón.

12306 La raíz agregada central real debe ser el número de tren. El número de tren tiene la responsabilidad de emitir boletos. Las cosas específicas que se deben hacer al emitir un boleto son:

Determinar si el. se puede emitir el boleto;

Seleccionar asientos disponibles;

Actualizar el número de boletos disponibles en todos los intervalos atómicos cuando se emite un boleto, que se utiliza para determinar si los boletos se pueden emitir a continuación. tiempo;

Mantener todas las entradas vendidas. Las entradas se utilizan como base para seleccionar los asientos disponibles.

A través del diseño de este modelo, podemos garantizar que un proceso de emisión de boletos solo se realizará dentro de una raíz agregada de tren. La ventaja de esto es:

Se puede lograr una fuerte consistencia de las modificaciones de datos sin depender de las transacciones de la base de datos, porque todas las modificaciones solo ocurren dentro de una raíz agregada;

A la vez que se garantiza una fuerte consistencia de los datos. es altamente eficiente y puede proporcionar altas capacidades de procesamiento concurrente. Consulte el diseño de arquitectura a continuación para conocer el diseño específico.

4. Diseño de arquitectura

Creo que escenarios comerciales como 12306 son muy adecuados para usar la arquitectura CQRS porque, en primer lugar, es un sistema que requiere más verificación y menos escritura; pero la lógica empresarial es un sistema muy complejo. Por tanto, es muy adecuado para la separación de lectura y escritura a nivel arquitectónico, es decir, utilizando la arquitectura CQRS. Y se debería utilizar CQRS donde el almacenamiento de datos también está separado. De esta manera, ambos extremos de CQ no necesitan tener en cuenta los problemas de la otra parte en absoluto y cada uno puede optimizar sus propios problemas. Podemos utilizar la idea del modelo de dominio DDD en el lado C para implementar reglas comerciales complejas y lógica comercial con un modelo de dominio bien diseñado. El lado Q utiliza una solución de almacenamiento en caché distribuido para lograr capacidades de consulta escalables.

1. Ideas de implementación para la reserva de entradas

Al mismo tiempo, con la ayuda de marcos como ENode, podemos implementar la arquitectura en memoria + Event Sourcing.

La tecnología de Event Sourcing puede unificar la persistencia de todas las modificaciones de estado en el modelo de dominio. Originalmente, ORM se usaba para guardar el último estado de la raíz agregada. Ahora solo es necesario guardar un evento de manera simple y general (solo una reserva de boleto). implica La modificación de una raíz agregada de viaje en tren solo genera un evento y solo necesita persistir un evento (una cadena JSON), lo que garantiza un alto rendimiento sin depender de transacciones, y los problemas de concurrencia se pueden resolver a través de ENode).

Siempre que guardemos el evento de cada cambio de la raíz agregada (cómo diseñar la estructura del evento, este artículo no lo presentará en detalle, puedes pensar en ello), es equivalente para guardar el último estado de la raíz agregada. Es precisamente gracias a la introducción de la tecnología de Event Sourcing que nuestro modelo siempre puede sobrevivir en la memoria, es decir, se puede utilizar la tecnología en memoria. No subestimes la tecnología en memoria. La tecnología en memoria es muy útil para mejorar el rendimiento del procesamiento de comandos en algunos aspectos.

Por ejemplo, utilizamos nuestra raíz agregada de viajes en tren para procesar la lógica de emisión de boletos. Supongamos que para un determinado viaje en tren se envía una gran cantidad de comandos a la cola de mensajes distribuidos y luego una máquina se suscribe. los mensajes de esta cola, y luego esta máquina Al procesar el comando de reserva de boletos para este tren, dado que la raíz agregada de este tren siempre está en la memoria, se ahorra el paso de ir a la base de datos para recuperar la raíz agregada cada vez, lo que equivale a una IO de base de datos menos.

La ventaja de esto es que el número de billetes que realmente se pueden vender para un tren es limitado porque solo hay unos pocos asientos, por ejemplo, 1.000 asientos. Se estima que en circunstancias normales, sólo. Se emitirán alrededor de 2000 boletos (el número específico de boletos que se pueden emitir depende del grado de intersección de los intervalos, como se analizó anteriormente). En otras palabras, esta raíz agregada solo generará 2000 eventos, lo que significa que solo el procesamiento de 2000 comandos de reserva de boletos generará eventos y los persistirá, mientras que la gran cantidad restante de comandos se encontrará después de que los números de tren se calculen en la memoria; no quedan boletos, no se realizarán modificaciones y no se generarán eventos de dominio, por lo que el siguiente comando de reserva de boletos se puede procesar directamente. Esto puede mejorar enormemente el rendimiento del procesamiento de comandos de reserva de billetes.

Creo que es necesario mencionar otra pregunta, porque después de que el usuario reserva con éxito el boleto, aún debe pagar. Sin embargo, los usuarios pueden no pagar o no completar el pago dentro del tiempo especificado. En este caso, el sistema liberará automáticamente las entradas previamente solicitadas por el usuario. Por lo tanto, en función de esta demanda, debemos apoyar el 2pc a nivel empresarial en los negocios. Es decir, el inventario se retiene primero, es decir, el boleto se retiene durante un cierto período de tiempo (por ejemplo, 15 minutos), y luego se le entrega el boleto después de que el pago se haya realizado correctamente, y el sistema lo hace realidad. modificaciones de inventario.

A través de dicho procesamiento de retención, se puede garantizar que no se produzcan condiciones de sobreventa. Esta idea es en realidad similar a los sistemas de comercio electrónico tradicionales como Taobao, por lo que no entraré en más detalles. El caso de la conferencia que escribí antes también tiene esta idea. Si está interesado, puede ver el video que grabé antes.

2. La idea de implementación de consultar los votos restantes

Creo que la implementación de consultar los votos restantes es relativamente simple. Aunque para 12306, las solicitudes de consulta representan el 80% y las solicitudes de envío de pedidos solo representan el 20%. Pero como la consulta no modifica los datos, podemos usar completamente el caché distribuido para implementarlo. Solo necesitamos diseñar cuidadosamente la clave almacenada en caché; la cantidad de claves almacenadas en caché depende del costo. Si todas las consultas posibles tienen claves correspondientes, la complejidad del tiempo será 1 y, naturalmente, el rendimiento de la consulta también será alto; , porque la clave es mucho más. Si desea tener menos claves, la complejidad de la consulta aumentará naturalmente. Entonces el diseño de caché no es más que la idea de intercambiar espacio por tiempo. Luego, existen tres tipos de actualizaciones de caché: invalidación automática, actualizaciones programadas y notificaciones activas. A través de la arquitectura CQRS, dado que ambos extremos de CQ están controlados por eventos, cuando hay algún cambio de estado en el extremo C, se generarán los eventos correspondientes para notificar al extremo Q, por lo que podemos lograr actualizaciones casi en tiempo real en el extremo Q. .

Al mismo tiempo, debido al desacoplamiento completo de ambos extremos de CQ, podemos diseñar una variedad de almacenamiento en el lado Q, como bases de datos y cachés (Redis, etc.); se utiliza para mantener datos relacionales fuera de línea y almacenar en caché las consultas de los usuarios en tiempo real. Las velocidades de actualización de la base de datos y la caché no se ven afectadas entre sí porque son paralelas.

Para el mismo evento, 10 máquinas pueden ser responsables de actualizar el caché y 100 máquinas pueden ser responsables de actualizar la base de datos. Incluso si la actualización de la base de datos es lenta, no afectará el progreso de la actualización de la caché. Este es el beneficio de la arquitectura CQRS. La arquitectura de CQ es completamente diferente y podemos reconstruir un nuevo almacenamiento del lado Q en cualquier momento. Me pregunto si todos han experimentado esto.

En cuanto al diseño de la clave de caché, creo que se considera principalmente a partir de la información pasada al consultar los tickets restantes. La consulta clave para 12306 es: lugar de salida, destino y fecha de salida. Creo que hay dos ideas de diseño clave:

Diseñar directamente la clave para la condición de consulta y luego obtener rápidamente la información del tren y devolverla directamente. Este método requiere que nuestro sistema haya enumerado todos los trenes Las claves de caché; De todos los tickets (intervalos) posibles, creo que debes saber que existen muchas claves de este tipo.

En lugar de enumerar todos los intervalos, se utiliza como clave el número de votos disponibles para cada intervalo atómico (la línea recta que conecta dos estaciones adyacentes) de cada viaje en tren. De esta manera, hay muy pocas claves, porque si hay 10,000 trenes y cada tren tiene un promedio de 15 intervalos, entonces solo hay 15W claves. Cuando queremos realizar una consulta, solo necesitamos averiguar el número de votos disponibles en todos los intervalos atómicos entre la entrada de origen y destino del usuario, y luego comparar el intervalo atómico con el número más pequeño de votos disponibles. Entonces, la cantidad de votos disponibles en este intervalo atómico es la cantidad de votos disponibles en el intervalo ingresado por el usuario. Por supuesto, en este punto mencioné considerar la fecha de salida. Creo que la fecha de salida se utiliza para determinar qué tren es la raíz agregada. El mismo número de tren y diferentes fechas tienen diferentes instancias raíz agregadas. Incluso en el mismo día, puede haber varias instancias raíz agregadas porque algunos trenes tienen varios trenes al día, como uno que sale a las 9 a. m. y otro por la tarde. a las 3 en punto. Por lo tanto, sólo necesitamos usar la fecha como parte de la clave de caché.

Resumen

Este artículo se basa enteramente en algunos resultados de diseño basados ​​en mi pensamiento simple sobre el negocio principal del sitio web 12306. El modelado de dominio DDD real requiere una comunicación profunda con el personal comercial de primera línea y los expertos en el dominio, para que podamos tener una comprensión más profunda del conocimiento comercial en el campo y diseñar arquitecturas y modelos de dominio más confiables.

Me avergüenza mucho no haber comprado nunca un billete de tren en 12306. Mi casa está relativamente cerca, así que incluso si quisiera comprar uno, mi familia me lo compraría :) Por lo tanto, el contenido Lo compartido en este artículo se basa inevitablemente en conversaciones sobre papel. Pero creo que el negocio del sistema 12306 es de hecho más complejo que el sistema de comercio electrónico tradicional y la concurrencia es muy alta. Por lo tanto, creo que este sistema realmente merece la atención de todos en el diseño del modelo, en lugar de centrarse solo en la implementación técnica.