Red de conocimiento informático - Conocimiento informático - Alguna comprensión de los sistemas de software

Alguna comprensión de los sistemas de software

Este artículo es para expresar algo de mi comprensión del software del sistema. El estilo es diferente al anterior y el estilo general es más "retirado". En realidad, no soy muy bueno para "retirarme", e incluso me repugna un poco. En comparación con leer artículos, prefiero leer código. Por supuesto, también leo artículos, pero relativamente menos. He estado trabajando en el campo de los motores de almacenamiento de bases de datos desde que me gradué. En los últimos cinco años, me he centrado principalmente en la investigación y el desarrollo del motor de almacenamiento LSM-Tree de desarrollo propio de Alibaba, X-Engine. Después de completar la actualización de la arquitectura nativa de la nube de X-Engine y comercializarlo, puede aceptar una cierta escala de clientes y operar de manera estable en la nube pública. También debería ser el primer motor de almacenamiento TP en la industria en lograr capacidades nativas de la nube basadas en. Arquitectura de árbol LSM. Pasé por completo el ciclo completo de planificación, diseño y desarrollo de la arquitectura, implementación y operación y mantenimiento estables de un motor de almacenamiento TP, y me beneficié del excelente trabajo de ingeniería del equipo de alto nivel, el líder tecnológico y los miembros de todo el equipo. Desde que ingresé al campo de las bases de datos, la capacidad y la visión técnica, junto con algunos de mis propios pensamientos durante el proceso, gradualmente formaron algunas de mis propias experiencias. Además, después de comunicarme con algunos arquitectos e ingenieros destacados en la industria, descubrí que hay muchas opiniones sobre la comprensión de la ingeniería de sistemas y, por supuesto, también hay muchas opiniones muy valiosas. Esta es también la razón principal que me impulsó a escribir este artículo. Espero expresar claramente algunos de mis propios conocimientos. Estas opiniones no son moda, y mucho menos innovación, sino más bien mi propio pensamiento y experiencia.

Punto de vista 1: La esencia del software es el consumo de recursos de hardware. La diferencia entre diferentes software radica en para qué problemas se consumen recursos de hardware y cómo se asigna el consumo de recursos de hardware. "Abstracción" y "compensación" se mencionan a menudo en el diseño de arquitectura de software. La abstracción significa esencialmente "qué problema resolver" y "compensación" en realidad significa "cómo asignar recursos de hardware". Por ejemplo, el motor de almacenamiento TP y el motor de almacenamiento AP pueden enumerar muchas diferencias en la implementación, como almacenamiento de filas VS almacenamiento de columnas, índice secundario VS índice ZoneMap, transacción fuerte VS transacción débil, etc. Estas diferencias son en realidad resultados. Las razones fundamentales para esto son:

1) Los dos escenarios de TP que resuelven diferentes problemas son principalmente servicios en línea en tiempo real. Las características de estos servicios son la escala general de datos. relativamente grande (datos que realmente necesitan procesarse en línea, puede haber muchos datos históricos), solicitudes cortas y rápidas, localidad de datos obvia, alta concurrencia y baja latencia, etc., mientras que la escala de datos general del AP. El escenario es grande, alta densidad informática, alto rendimiento, etc. (Qué problema se resuelve)

2) El soporte completo de transacciones del motor TP simplifica el control de concurrencia del negocio. De hecho, el motor TP hace lo que el sistema empresarial originalmente necesitaba hacer, lo cual, por supuesto. significa que el motor TP necesita consumir algunos recursos de hardware para esto. Para acelerar la entrada de datos en la base de datos, el motor AP tiene un soporte de transacciones relativamente débil. Esta parte del trabajo aún la completa el sistema empresarial (como ETL), por lo que no es necesario consumir recursos de hardware para esto. . (Cómo asignar recursos de hardware) Punto de vista 2: Los cambios importantes en el software del sistema están impulsados ​​básicamente por el desarrollo del hardware. Esto se hace eco del punto 1). Antes de entrar en el siglo XXI, la comunidad académica había realizado una investigación extensa y profunda sobre la teoría en el campo del software de sistemas. Desde la aparición de las computadoras al principio, hasta las mainframes y minicomputadoras, pasando por las PC domésticas y los servidores baratos de uso general, y ahora los servicios IAAS de computación en la nube, básicamente el desarrollo del software del sistema ha seguido esta tendencia. La renovada popularidad del software del sistema está impulsada esencialmente por el "nuevo hardware" de IAAS. La adquisición bajo demanda de todo el IAAS rompe con muchos diseños anteriores de software de sistema en el contexto de recursos físicos limitados. Por eso, el software de sistema nativo de la nube abrirá nuevas oportunidades. Punto de vista 3: Casi no existe una arquitectura de sistema que esté completamente por delante de otra arquitectura. Esto se hace eco de los puntos 1) y 2). Detrás de las diferentes opciones de arquitectura hay diferentes compensaciones. Como dice el refrán, debe haber ganancias y pérdidas. A menudo escucho algunos dichos. Si miras este documento y este artículo, su arquitectura no tiene ningún problema, pero nuestra arquitectura tiene este problema.

Mi primera reacción cuando escuché estos puntos de vista fue cuestionarlos. Hay tres razones principales para esto:

1) Los resultados experimentales de muchos artículos y artículos no se pueden reproducir, lo que significa que es muy posible que. su Hay un problema con la conclusión;

2) En muchos casos, solo se enfatiza la parte de "ganar", pero no se discute la parte de "renunciar".

3) El alcance del impacto de los problemas en nuestro sistema y si pueden resolverse requieren datos cuantitativos para determinarlo. Si se deja influenciar fácilmente por las conclusiones de varios trabajos y artículos, es probable que cree un sistema anodino. Al igual que un practicante de artes marciales que aprende artes marciales de varias sectas, al final es fácil obsesionarse. Punto de vista 4: Todos los caminos conducen a Roma La diferencia en el aspecto exterior final del sistema se debe más a la implementación de ingeniería que a razones arquitectónicas. La mayoría de los problemas que las diferentes arquitecturas de sistemas deben resolver son esencialmente los mismos y los componentes que componen un sistema son similares. Usted simplemente elige qué componentes construir el sistema de acuerdo con sus necesidades. Sólo sumergiéndose en la situación y afrontando, analizando y resolviendo verdaderamente los problemas se podrá comprender la esencia. De lo contrario, fácilmente se convertirá en una simple conversación sobre el papel. Por ejemplo: a menudo me preguntan sobre el problema de compactación que tiene un gran impacto en el rendimiento cuando se escriben datos continuamente en la arquitectura LSM-Tree. Así es como veo este problema. En primer lugar, una de las razones de la ventaja de la arquitectura LSM-Tree en cuanto a la absorción de escritura es que, en comparación con discos como innodb, el árbol B+ ordena directamente la escritura (la página está ordenada, la página está ordenada). Ordenado global), la arquitectura LSM-Tree elige transferir parte de la clasificación para ordenar en compactación y ordenar en lectura, lo que esencialmente transfiere el consumo de recursos de la clasificación durante la escritura a compactación o lectura. El vaciado sucio en realidad consta de dos acciones: generar páginas sucias y vaciar páginas sucias en el disco. Innodb es equivalente a generar páginas sucias al escribir, y al vaciar páginas sucias, es una operación IO simple. La compactación en realidad genera "páginas sucias" y "páginas sucias" al mismo tiempo para vaciar el disco. Si innodb continúa escribiendo, también habrá problemas que pueden afectar el rendimiento de la escritura si los datos no se vacían a tiempo. La razón por la que el lavado y la compactación de innodb se convierten en problemas se debe esencialmente a la diferencia en la velocidad de escritura de la memoria y el disco, lo que conduce a un desequilibrio en el modelo productor-consumidor. Por lo tanto, la limpieza de innodb y la compactación de LSM-Tree son esencialmente el mismo problema, pero utilizan diferentes métodos para minimizar el impacto de este proceso en el sistema.

El siguiente contenido trata principalmente sobre los principios que creo que son más importantes a la hora de realizar un diseño detallado. Los principios de estos principios son realmente muy fáciles de entender y el tema de la "ingeniería de software" se ha estudiado en profundidad, pero en realidad es bastante difícil de implementar en la práctica, puede deberse a un bagaje histórico o al entorno externo. Hacer diferentes concesiones basadas en las condiciones reales. Vale la pena señalar que las compensaciones que hagamos deben considerarse cuidadosamente y no apresurarse, de lo contrario es fácil "decidir". Además, el resultado de un sistema diseñado e implementado de acuerdo con estos principios y de un sistema diseñado e implementado sin cumplir plenamente con estos principios es en realidad "la diferencia entre lo bueno y lo mejor", pero la cantidad de "cuánto mejor" es en realidad difícil de medir antes de construir el sistema. Estos siete principios no existen de forma independiente, sino que se complementan entre sí. Orientado a escenarios: en primer lugar, debemos aclarar qué problema queremos resolver. Este es el punto de partida para construir todo el sistema. En el pasado no existía un sistema único para todos, y es posible que no exista en el futuro. La mejora del sistema debe completarse mediante iteración continua, por lo que cómo iterar es esencialmente qué problemas resolvemos en esas etapas. Un sistema puede tener objetivos ambiciosos para resolver muchos problemas, pero la hoja de ruta para todos los problemas debe ser relativamente clara en la planificación para que pueda satisfacer rápidamente las necesidades y al mismo tiempo conservar la base para la evolución y expansión futuras. Durante el proceso real de investigación y desarrollo, dos tipos de errores que pueden ocurrir son:

1) Quiere utilizar métodos de desarrollo ágiles para la gestión de ingeniería para satisfacer las necesidades de toda la iteración. En esencia, el desarrollo ágil primero define el conjunto mínimo de funciones, es decir, primero piensa claramente qué problema resolver y luego expande rápidamente las funciones de forma iterativa, lo que es un poco como caminar rápidamente en pequeños pasos.

En la práctica, es fácil convertir el desarrollo ágil en "rápido, duro y feroz", lo que se siente un poco como trabajar duro durante 30 días para alcanzar a Estados Unidos.

2) Si la definición del problema no es clara, es fácil que la configuración "invariante" del sistema se apresure. Cada sistema tiene algunas "invariantes" y, posteriormente, se desarrollan muchos diseños basados ​​en estas invariantes. Por ejemplo, una "invariante" común en el sistema LSM-Tree es que la versión actualizada de los datos está en un nivel inferior, si hay varias versiones. de la misma fila de datos existen en memtable, nivel0 y nivel1 al mismo tiempo, entonces la versión correspondiente en memtable debe ser la más reciente y la versión en el nivel0 también es más nueva que la del nivel1. Si se descubre durante el proceso de iteración que el "invariante" establecido previamente no es razonable, el costo de realizar cambios será muy alto. Orientado al desacoplamiento: ya sea que se diseñe un sistema de arriba hacia abajo o de abajo hacia arriba, una lógica de pensamiento muy importante es minimizar el acoplamiento entre módulos. Un sistema bien desacoplado a menudo significa:

1) La función de cada módulo se considera claramente y la integridad de la solución es relativamente alta

2 ) Es propicio para; centrarse en implementar un determinado módulo de manera más eficiente y evitar la influencia de otros módulos

3) Es propicio para iteraciones posteriores y el impacto es controlable

4) Los problemas son más fáciles; Los problemas con un solo módulo son más fáciles de solucionar. Los problemas realmente difíciles a menudo quedan expuestos después de que el problema se transmite entre los módulos. Por ejemplo, si ocurre un problema en el módulo A, pasa a través de los módulos B, C y D. finalmente en el módulo E se expone. Algunos puntos de vista escépticos dirán que diseñar para el desacoplamiento puede sacrificar el rendimiento general del sistema. De hecho, esto es lo mismo que no diseñar demasiado para el rendimiento desde el principio. Si algunos diseños de desacoplamiento realmente afectan el rendimiento, entonces se debe realizar el desacoplamiento. Acoplar dos módulos suele ser menos difícil que desmontar dos módulos acoplados. Orientado a la defensa: esta es la lógica de la programación defensiva. Se supone que las funciones llamadas pueden salir mal, por ejemplo, la asignación de memoria puede salir mal, la IO puede salir mal, las llamadas básicas a la biblioteca pueden salir mal, etc. Considere si algo sale mal. ¿Cuál es el comportamiento del sistema? Existe un principio muy simple de "detención por falla". Si no hay una defensa completa, incluso si falla, será difícil detenerse inmediatamente, lo que eventualmente causará algunos fenómenos muy extraños. Las dudas habituales son:

1) Puedes ver que la lógica de esta función definitivamente no fallará. Tal vez esta función no falle desde el punto de vista actual, pero es difícil garantizar que a medida que la lógica aumenta con la iteración, no habrá posibilidad de falla más adelante.

2) Con tantas defensas agregadas, hay más códigos de defensa que códigos lógicos reales, lo que afectará el rendimiento. En primer lugar, la capacidad actual de predicción de bifurcaciones de la CPU básicamente puede garantizar que el código de defensa no afecte el rendimiento en la mayoría de los casos. Además, al igual que las dudas sobre el acoplamiento, si algunos códigos de defensa se convierten en cuellos de botella en el rendimiento, se debe optimizar la optimización. Optimizar una defensa siempre es más barato que resolver un problema causado por la falta de defensa. Orientado a pruebas: el costo de solucionar problemas en la fase de prueba es mucho menor que el costo de solucionar problemas en el entorno de producción, por lo que es muy importante hacer que el sistema sea comprobable. El estándar comprobable del sistema es que puede realizar fácilmente pruebas unitarias y de integración, y cubrir la mayoría de las rutas de código. Con la iteración continua, un sistema comprobable acumulará cada vez más casos de prueba, fortaleciendo continuamente la base para la estabilidad. La orientación de prueba, la orientación de desacoplamiento y la orientación de defensa son complementarias entre sí. Solo si el acoplamiento entre módulos es lo suficientemente bajo, es posible realizar más pruebas. De lo contrario, probar un módulo requiere burlarse de muchas cosas complicadas. Estar orientado a la defensa hará que el comportamiento de la prueba sea más predecible. De lo contrario, si se ingresa un parámetro anormal y la falla específica es incierta, será difícil escribir el caso de prueba. Orientado a la operación y el mantenimiento: es probable que se produzcan errores en sistemas complejos, no importa cuánta preparación se realice en la etapa inicial, es difícil evitar problemas desconocidos en el entorno de producción. El objetivo principal de la operación y el mantenimiento es utilizar el método de menor costo para detener las pérdidas a tiempo cuando se encuentran problemas. Cuando se encuentran problemas en línea, es más barato resolverlos ajustando dinámicamente los parámetros que reiniciando, y es más barato resolverlos reiniciando que lanzando una versión.

Estar orientado a O&M no es tan simple como agregar algunos parámetros o interruptores, pero es necesario considerar "orientado a O&M" como una parte importante del plan de diseño para garantizar que existan medios de O&M si surgen problemas. él, será efectivo después de usarlo. Orientarse a la esencia del problema: Al resolver un problema, se debe pensar más en la causa esencial del problema. Los problemas simples se complican y los complejos se simplifican porque no se capta la esencia. Si puedes pensar claramente en las razones esenciales detrás de esto, evitarlo desde la fuente es una solución más completa, de lo contrario, es fácil caer en un estado de parcheo constante. Siempre he tenido un punto de vista: "Si fallas. "Si se capta la esencia del problema para resolverlo, el resultado muchas veces será crear problemas". Otra experiencia es que si un módulo tiene problemas varias veces seguidas, entonces hay que pensar si hay algo que deba mejorarse en el diseño inicial. Orientado a la visualización: El objetivo principal de la visualización es mostrar el estado operativo del sistema de una forma más intuitiva, lo cual es muy importante para el ajuste y diagnóstico del sistema. Cuando el sistema presenta una anomalía, la visualización puede ayudar a localizar rápidamente el problema en el sistema. Por otro lado, puede proporcionar una interfaz para que el sistema de seguimiento rastree el estado histórico. Por ejemplo, el monitoreo de diagnóstico de Oracle es un muy buen caso, y la gestión y monitoreo del estado interno de SnowFlake es casi una locura.

Dicho todo esto, el sistema se implementa en última instancia mediante líneas de código. Mantener el ingenio, el rigor y una verdadera actitud para construir el sistema es algo muy simple y correcto, pero también muy difícil de lograr. hazlo.* **¡Mian!

Enlace original: /m/1000349863/