Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

1. Antecedentes

Con el rápido crecimiento de los niveles de usuario, la arquitectura monolítica de vivo official mall v1.0 ha expuesto gradualmente sus inconvenientes: los módulos se están volviendo más hinchados, la eficiencia del desarrollo es baja, aparecen cuellos de botella en el rendimiento y el mantenimiento del sistema es difícil.

La actualización de la arquitectura v2.0 comenzó en 2017, y la división física del sistema vertical basada en módulos comerciales, las líneas comerciales divididas realizan cada una sus funciones, brindan capacidades orientadas al servicio y respaldan conjuntamente el negocio del sitio principal.

El módulo de pedidos es el núcleo del sistema de comercio electrónico. Los datos acumulados están a punto de alcanzar el cuello de botella de almacenamiento de un solo metro. El sistema no puede soportar el flujo de lanzamientos de nuevos productos y promociones importantes. La transformación del servicio es imperativa.

Este artículo presentará los problemas y las soluciones encontrados durante la construcción del sistema de pedidos del centro comercial vivo y compartirá la experiencia de diseño de arquitectura.

Dos, arquitectura del sistema

Separe el módulo de pedidos del centro comercial y conviértase en un sistema de pedidos de forma independiente, utilizando una base de datos independiente para proporcionar servicios estandarizados como pedidos, pagos, logística y servicios posventa para sistemas relacionados en el centro comercial.

La arquitectura del sistema se muestra en la siguiente figura:

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

3. Desafíos técnicos

3.1 Problemas de volumen de datos y alta concurrencia

El primer desafío es el sistema de almacenamiento:

  • Problema de volumen de datos

    Con la acumulación de pedidos históricos, la cantidad de datos en la tabla de pedidos en MySQL ha alcanzado decenas de millones.

    Sabemos que la estructura de almacenamiento del motor de almacenamiento InnoDB es un árbol B + y la complejidad del tiempo de búsqueda es O (log n). Por lo tanto, cuando la cantidad total de datos n aumenta, la velocidad de recuperación inevitablemente se ralentizará. No importa cómo agregar índice u optimizarlo, no se puede resolver. Solo puedo pensar en formas de reducir la cantidad de datos en una sola tabla.

    Las soluciones para grandes cantidades de datos incluyen: archivo de datos, subtabla

  • Problema de alta concurrencia

    El negocio de los centros comerciales se encuentra en un período de rápido desarrollo, el número de pedidos ha alcanzado repetidamente nuevas alturas, la complejidad del negocio también está aumentando y el número de visitas a MySQL por aplicaciones está aumentando.

    La capacidad de procesamiento de un MySQL independiente es limitada.Cuando la presión es demasiado grande, la velocidad de acceso de todas las solicitudes disminuirá y la base de datos puede incluso estar inactiva.

    Las soluciones con alta concurrencia son: usar caché, separación de lectura y escritura y subbase de datos

A continuación, se ofrece una breve descripción de estas soluciones:

  • Archivo de datos

    Los datos de los pedidos tienen atributos de tiempo y hay un efecto de cola caliente. En la mayoría de los casos, se recuperan los pedidos más recientes, mientras que una gran cantidad de datos antiguos que se utilizan con menos frecuencia se almacena en la tabla de pedidos.

    Luego, puede almacenar los datos nuevos y antiguos por separado, mover los pedidos históricos a otra tabla y realizar algunos cambios correspondientes en el módulo de consulta en el código, lo que puede resolver eficazmente el problema del gran volumen de datos.

  • Usar caché

    El uso de Redis como pre-caché de MySQL puede bloquear la mayoría de las solicitudes de consulta y reducir el retraso de respuesta.

    La caché es particularmente eficaz para los sistemas que tienen poco que ver con los usuarios, como los sistemas básicos, pero para los sistemas de pedidos, los datos de las órdenes de cada usuario son diferentes, la tasa de aciertos de la caché no es alta y el efecto no es muy bueno.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

  • Separación de lectura y escritura

    La biblioteca maestra es responsable de ejecutar las solicitudes de actualización de datos y luego sincronizar los cambios de datos en todas las bibliotecas esclavas en tiempo real y usar varias bibliotecas esclavas para compartir solicitudes de consulta.

    Sin embargo, hay muchas operaciones de actualización de datos de pedidos y la presión de la biblioteca principal durante el pedido pico aún no se resuelve. Y hay un retraso de sincronización maestro-esclavo. Normalmente, el retraso es muy pequeño, no más de 1 ms, pero también puede causar datos inconsistentes maestro-esclavo en un momento determinado.

    Luego, es necesario manejar todos los escenarios comerciales afectados compatibles, y se pueden hacer algunos compromisos. Por ejemplo, después de que el pedido se haya realizado correctamente, primero saltará a una página de pedido exitoso y el usuario puede hacer clic manualmente para ver el pedido y ver el pedido.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

  • Sub-biblioteca

    La sub-biblioteca incluye una sub-biblioteca vertical y una sub-biblioteca horizontal.

    ① Subbase de datos horizontal: divida los datos de la misma tabla en diferentes bases de datos de acuerdo con ciertas reglas, y cada base de datos se puede colocar en un servidor diferente.

    ② Subbase de datos vertical: Las tablas se clasifican según el negocio y se distribuyen a diferentes bases de datos, cada base de datos se puede colocar en un servidor diferente, su concepto central está dedicado a bases de datos especiales.

  • Submesa

    Las sub-tablas incluyen sub-tablas verticales y sub-tablas horizontales.

    ** ①Subtabla horizontal  : ** En la misma base de datos, los datos de una tabla se dividen en varias tablas de acuerdo con ciertas reglas.

    ** ②Subtabla vertical  : ** Divida una tabla en varias tablas según los campos, y cada tabla almacena algunos de los campos.

Consideramos exhaustivamente el costo, el efecto y el impacto de la transformación en el negocio existente y decidimos usar directamente el último truco: subbase de datos y subtabla.

3.2 Selección de tecnología de sub-biblioteca y sub-metro

La selección técnica de sub-biblioteca y sub-tabla se considera principalmente desde estas direcciones:

  1. Solución de código abierto Client SDK

  2. Solución de código abierto de proxy de middleware

  3. Marco de autoinvestigación proporcionado por el equipo de middleware de la empresa

  4. Construye tus propias ruedas

Después de referirse a la experiencia anterior en proyectos y comunicarse con el equipo de middleware de la empresa, se adoptó la solución de código abierto Sharding-JDBC . Ahora ha sido renombrado Sharding-Sphere.

  • Github:https://github.com/sharding-sphere/

  • Documentos: los documentos oficiales son aproximados, pero los materiales en línea, el análisis del código fuente y las demostraciones son relativamente ricos.

  • Comunidad: activa

  • Características: proporcionado en el paquete jar, pertenece a la fragmentación del lado del cliente, admite transacciones xa

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos  

3.2.1 Estrategia de la subtabla de la subbase de datos

Combinando las características comerciales, seleccione el ID de usuario como clave de fragmentación y obtenga el número de tabla de la base de datos de los datos del pedido del usuario calculando el valor hash del ID de usuario y luego tomando el módulo.
Suponga que hay n bibliotecas en total y cada biblioteca tiene m tablas.

El método de cálculo del número de tabla de la biblioteca es:

-Número de serie de la biblioteca: Hash (userId) / m% n

-Número de serie de la tabla: Hash (userId)% m

El proceso de enrutamiento se muestra en la siguiente figura:

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

3.2.2 Limitaciones de sub-bases de datos y sub-tablas y soluciones

La subtabla de la subbase de datos resuelve el problema del volumen de datos y la simultaneidad, pero limitará en gran medida la capacidad de consulta de la base de datos. Es posible que algunas consultas relacionadas anteriormente simples no se realicen después de la subbase de datos y la subtabla de la tabla, por lo que debe verificar por separado Estos SQL que no son compatibles con Sharding-JDBC se reescriben.

Además, se encontraron estos desafíos:

(1) Diseño de identificación único a nivel mundial

Después de fragmentar la base de datos y las tablas, la clave principal de incremento automático de la base de datos ya no es globalmente única y no se puede usar como un número de orden. Sin embargo, muchas interfaces de interacción entre sistemas internos solo tienen un número de orden. No hay identificación de usuario para esta clave de fragmentación. Cómo encontrar el número de orden correspondiente ¿Y la mesa de la biblioteca?

Resultó que cuando generamos el número de pedido, incluimos implícitamente el número de tabla de la biblioteca. De esta manera, el número de tabla de la biblioteca se puede obtener del número de pedido sin la identificación del usuario.

(2) El número de orden histórico no tiene información de tabla de biblioteca implícita

Se utiliza una única tabla para almacenar la relación de mapeo entre los números de orden históricos y los ID de usuario. A medida que pasa el tiempo, estas órdenes dejan de usarse gradualmente en la interacción entre sistemas.

(3) El fondo de gestión necesita consultar todos los pedidos que cumplen las condiciones por página de acuerdo con varias condiciones de filtrado

Los datos del pedido se almacenan de forma redundante en el motor de búsqueda Elasticsearch, que solo se utiliza para consultas en segundo plano.

3.3 Cómo sincronizar datos de MySQL a ES

Como se mencionó anteriormente, para facilitar la gestión de consultas de back-end, almacenamos datos de pedidos de forma redundante en Elasticsearch. Entonces, ¿cómo sincronizar los datos de pedidos en MySQL con ES después de que se modifiquen?

Lo que hay que tener en cuenta aquí es la puntualidad y la coherencia de la sincronización de datos, la pequeña intrusión en el código empresarial y la ausencia de impacto en el rendimiento del servicio en sí.

  • Esquema MQ

    Servicio de actualización de ES como consumidor, actualice ES después de recibir el mensaje MQ de cambio de pedido

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

  • Solución Binlog

    El servicio de actualización de ES utiliza proyectos de código abierto como canal para pretender ser un nodo esclavo de MySQL, recibe Binlog y lo analiza para obtener información de cambio de datos en tiempo real, y luego actualiza ES en base a esta información de cambio.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

Entre ellos, la solución BinLog es más general, pero también más complicada de implementar, finalmente elegimos la solución MQ.

Dado que los datos de ES solo se utilizan en segundo plano de gestión, los requisitos de fiabilidad de los datos y sincronización en tiempo real no son especialmente elevados.

Teniendo en cuenta situaciones extremas como el tiempo de inactividad y la pérdida de mensajes, la función de sincronizar manualmente los datos ES bajo ciertas condiciones se agrega en segundo plano para compensar.

3.4 Cómo reemplazar la base de datos de forma segura

Cómo migrar datos de la base de datos de instancia única original al nuevo clúster de base de datos también es un desafío técnico importante

No solo para garantizar la exactitud de los datos, sino también para garantizar que después de cada paso, una vez que ocurra un problema, pueda volver rápidamente al paso anterior.

Consideramos dos soluciones para la migración con tiempo de inactividad y la migración sin tiempo de inactividad:

(1) Plan de migración ininterrumpida:

  • Copie los datos de la biblioteca anterior a la nueva biblioteca, inicie un programa de sincronización y utilice Binlog y otras soluciones para sincronizar los datos de la biblioteca anterior con la nueva biblioteca en tiempo real.

  • Se lanza el servicio de biblioteca nuevo y antiguo para órdenes de escritura doble, y solo se lee y escribe la biblioteca antigua.

  • Active la escritura doble, detenga el programa de sincronización al mismo tiempo e inicie el programa de compensación de comparación para asegurarse de que los datos de la nueva biblioteca sean coherentes con la biblioteca anterior.

  • Cambie gradualmente las solicitudes de lectura a la nueva biblioteca.

  • Tanto la lectura como la escritura se cambian a la nueva biblioteca, y el programa de compensación se compara para garantizar que los datos de la biblioteca anterior sean coherentes con la nueva biblioteca.

  • Bibliotecas antiguas fuera de línea, funciones de doble escritura para pedidos fuera de línea, procedimientos de sincronización fuera de línea y procedimientos de compensación de comparación.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

(2) Cierre del plan de migración:

  • Se lanzó el nuevo sistema de pedidos, se ejecutó el programa de migración para sincronizar los pedidos hace dos meses a la nueva base de datos y se auditó la información.

  • Cierre la aplicación mall V1 para asegurarse de que los datos de la base de datos anterior no cambien.

  • Realice el proceso de migración, sincronice los pedidos que no fueron migrados en el primer paso a la nueva biblioteca y realice auditorías.

  • Inicie la aplicación mall V2, inicie la prueba y la verificación, si falla, vuelva a la aplicación mall V1 (el nuevo sistema de pedidos tiene un interruptor para escribir dos veces la biblioteca anterior).

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

Teniendo en cuenta el alto costo de transformación de la solución ininterrumpida y la pérdida comercial de la solución de apagado nocturno no es grande, la elección final es la solución de migración de apagado.

3.5 Problema de transacciones distribuidas

En el proceso de transacción del comercio electrónico, las transacciones distribuidas son un problema clásico, como por ejemplo:

  • Una vez que el usuario ha pagado con éxito, debe notificar al sistema de entrega para entregar la mercancía al usuario.

  • Una vez que el usuario confirma el recibo, debe notificar al sistema de puntos para que emita puntos para recompensas de compras al usuario.

¿Cómo garantizamos la coherencia de los datos en la arquitectura de microservicios?

Los diferentes escenarios comerciales tienen diferentes requisitos para la coherencia de los datos. Entre las soluciones principales de la industria, hay envío en dos fases (2PC) y envío en tres fases (3PC) para resolver una coherencia sólida, y TCC, mensaje local, Mensajes de transacciones y notificaciones de mejor esfuerzo, etc.

Aquí no hay una descripción detallada del esquema anterior, pero presentamos el esquema de la tabla de mensajes local que estamos usando: la operación asincrónica que se ejecutará en la transacción local se registra en la tabla de mensajes. Si la ejecución falla, se puede compensar con tareas de tiempo.

La siguiente figura muestra un ejemplo de cómo notificar al sistema de puntos que dé puntos después de completar el pedido.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

3.6 Seguridad y estabilidad del sistema

  • Aislamiento de red

    Solo se puede acceder a un número muy pequeño de interfaces de terceros a través de la red externa, y todas verifican la firma.El sistema interno interactúa con el nombre de dominio de la red interna y la interfaz RPC.

  • Bloqueo concurrente

    Antes de cualquier operación de actualización de pedidos, estará restringida por el bloqueo de nivel de fila de la base de datos para evitar actualizaciones simultáneas.

  • Idempotencia

    Todas las interfaces son idempotentes, por lo que no hay necesidad de preocuparse por el impacto del reintento del tiempo de espera de la red de la otra parte.

  • Fusible

    Utilice componentes de Hystrix para agregar protección de fusibles a las llamadas en tiempo real a sistemas externos para evitar que el impacto de una falla del sistema se propague a todo el sistema distribuido.

  • Monitoreo y alerta

    Al configurar la alarma de registro de errores de la plataforma de registro, la alarma de análisis de servicio de la cadena de llamadas y las funciones de monitoreo y alarma del middleware y componentes básicos de la empresa, podemos encontrar anomalías del sistema por primera vez.

3.7 Foso escalonado

Usando el consumo de MQ para sincronizar los datos relacionados con el pedido de la base de datos con el ES, los datos escritos encontrados no son los últimos datos del pedido.

El lado izquierdo de la siguiente figura es el plan original:

Al consumir el MQ de la sincronización de datos del pedido, si el hilo A se ejecuta primero y encuentra los datos, los datos del pedido se actualizan en este momento y el hilo B comienza a realizar la operación de sincronización. Después de encontrar los datos del pedido, se escribe en ES antes del hilo A. Cuando el hilo A realiza la escritura, sobrescribirá los datos escritos por el hilo B, lo que hará que los datos de la orden en ES no sean los más recientes.

La solución es agregar un bloqueo de fila al consultar los datos de la orden, todo el negocio se ejecuta en una transacción y el siguiente hilo se ejecuta después de que se completa la ejecución.

Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos Vivo Global Mall: Diseño y práctica de la arquitectura del centro de pedidos

sharding-jdbc Después de agrupar, ordenar y paginar, consultar todos los problemas de datos

示例 : seleccione a del grupo temporal por a, orden b por un límite desc 1,10。

La implementación es que los campos agrupar y ordenar por en Sharding-jdbc son inconsistentes con el orden, y 10 se establece en Integer.MAX_VALUE, lo que hace que la consulta de paginación falle.


io.shardingsphere.core.routing.router.sharding.ParsingSQLRouter#processLimit

private void processLimit(final List<Object> parameters, final SelectStatement selectStatement, final boolean isSingleRouting) {
     boolean isNeedFetchAll = (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) && !selectStatement.isSameGroupByAndOrderByItems();
    selectStatement.getLimit().processParameters(parameters, isNeedFetchAll, databaseType, isSingleRouting);
}

io.shardingsphere.core.parsing.parser.context.limit.Limit#processParameters

/**
* Fill parameters for rewrite limit.
*
* @param parameters parameters
* @param isFetchAll is fetch all data or not
* @param databaseType database type
* @param isSingleRouting is single routing or not
*/
public void processParameters(final List<Object> parameters, final boolean isFetchAll, final DatabaseType databaseType, final boolean isSingleRouting) {
    fill(parameters);
    rewrite(parameters, isFetchAll, databaseType, isSingleRouting);
}

private void rewrite(final List<Object> parameters, final boolean isFetchAll, final DatabaseType databaseType, final boolean isSingleRouting) {
    int rewriteOffset = 0;
    int rewriteRowCount;
    if (isFetchAll) {
        rewriteRowCount = Integer.MAX_VALUE;
    } else if (isNeedRewriteRowCount(databaseType) && !isSingleRouting) {
         rewriteRowCount = null == rowCount ? -1 : getOffsetValue() + rowCount.getValue();
    } else {
       rewriteRowCount = rowCount.getValue();
    }
    if (null != offset && offset.getIndex() > -1 && !isSingleRouting) {
       parameters.set(offset.getIndex(), rewriteOffset);
     }
     if (null != rowCount && rowCount.getIndex() > -1) {
        parameters.set(rowCount.getIndex(), rewriteRowCount);
      }
}

La redacción correcta debe seleccionarse a del grupo temporal por un desc, b límite 1,10; la versión utilizada es 3.1.1 de sharing-jdbc.

Si hay valores duplicados en el campo de clasificación de la consulta de paginación ES, es mejor agregar un campo único como la segunda condición de clasificación para evitar la pérdida de datos y la detección de datos duplicados durante la consulta de paginación. Por ejemplo, la hora de creación del pedido se utiliza como la única condición de clasificación. Si hay una gran cantidad de datos a lo largo del tiempo, se producirá la omisión o duplicación de los pedidos consultados. Es necesario agregar un valor único como segunda condición de clasificación o utilizar directamente el valor único como condición de clasificación.

4. Resultados

  • Éxito online único, funcionamiento estable durante más de un año

  • El rendimiento del servicio principal mejoró en más de diez veces

  • El desacoplamiento del sistema, la eficiencia iterativa se mejora enormemente

  • Puede apoyar el rápido desarrollo del centro comercial durante al menos cinco años.

Cinco, conclusión

No buscamos ciegamente tecnologías e ideas de vanguardia al diseñar el sistema, ni adoptamos directamente soluciones de comercio electrónico convencionales cuando enfrentamos problemas, sino para seleccionar el método más apropiado de acuerdo con las condiciones comerciales reales.

Personalmente, siento que un buen sistema no está diseñado por Daniel al principio, sino que debe iterarse gradualmente con el desarrollo y la evolución del negocio, seguir prediciendo la dirección del desarrollo del negocio y formular un plan de evolución de la arquitectura por adelantado. Es decir: ¡vaya al frente del negocio!

Autor: equipo de desarrollo del centro comercial del sitio web oficial de vivo

Supongo que te gusta

Origin blog.51cto.com/14291117/2575533
Recomendado
Clasificación