Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Fotograma de la película “Nuestro universo secreto: la vida oculta de la célula”

El negocio de inversión es una de las áreas más complejas del mundo bancario, porque no sólo hay préstamos, empréstitos y depósitos, sino también valores, divisas, materias primas, derivados y todo tipo de complejidades en forma de productos estructurados.

Recientemente, hemos visto un aumento en la educación financiera de la población. Cada vez más personas se involucran en el comercio en los mercados de valores. Las cuentas de inversión individuales aparecieron no hace mucho. Le permiten operar en los mercados de valores y recibir deducciones fiscales o evitar el pago de impuestos. Y todos los clientes que acuden a nosotros quieren gestionar su cartera y ver informes en tiempo real. Además, la mayoría de las veces esta cartera es multiproducto, es decir, las personas son clientes de diversas líneas de negocio.

Además, aumentan las necesidades de los reguladores, tanto rusos como extranjeros.

Para satisfacer las necesidades actuales y sentar las bases para futuras actualizaciones, hemos desarrollado un núcleo de negocio de inversión basado en Tarantool.

Algunas estadísticas. El negocio de inversión de Alfa-Bank ofrece servicios de corretaje para personas físicas y jurídicas para brindarles la oportunidad de negociar en diversos mercados de valores, servicios de depósito para el almacenamiento de valores, servicios de gestión de fideicomisos para personas físicas con capital privado y grande, servicios de emisión de valores para otras empresas. . El negocio de inversión de Alfa-Bank incluye más de 3 mil cotizaciones por segundo, que se descargan desde varias plataformas comerciales. Durante la jornada laboral se realizan más de 300 mil transacciones en los mercados por cuenta del banco o de sus clientes. Se producen hasta 5 mil ejecuciones de órdenes por segundo en plataformas externas e internas. Al mismo tiempo, todos los clientes, tanto internos como externos, quieren ver sus posiciones en tiempo real.

Prehistoria

Desde principios de la década de 2000, nuestras áreas de negocio de inversión se desarrollaron de forma independiente: operaciones de cambio, servicios de corretaje, operaciones de divisas, operaciones extrabursátiles de valores y diversos derivados. Como resultado, hemos caído en la trampa de los pozos funcionales. ¿Lo que es? Cada línea de negocio tiene sus propios sistemas que duplican las funciones de cada uno. Cada sistema tiene su propio modelo de datos, aunque operan con los mismos conceptos: transacciones, instrumentos, contrapartes, cotizaciones, etc. Y a medida que cada sistema evolucionó de forma independiente, surgió un zoológico diverso de tecnologías.

Además, el código base de los sistemas ya está bastante desactualizado, porque algunos productos se originaron a mediados de los años 1990. Y en algunas áreas esto ralentizó el proceso de desarrollo y hubo problemas de rendimiento.

Requisitos para una nueva solución

Las empresas se han dado cuenta de que la transformación tecnológica es vital para un mayor desarrollo. Nos dieron tareas:

  1. Recopile todos los datos comerciales en un almacenamiento único y rápido y en un único modelo de datos.
  2. No debemos perder ni cambiar esta información.
  3. Es necesario versionar los datos, porque en cualquier momento el regulador puede solicitar estadísticas de años anteriores.
  4. No debemos simplemente traer algunos DBMS nuevos y de moda, sino crear una plataforma para resolver problemas comerciales.

Además, nuestros arquitectos establecen sus propias condiciones:

  1. La nueva solución debe ser de clase empresarial, es decir, ya debe estar probada en algunas grandes empresas.
  2. El modo operativo de la solución debería ser de misión crítica. Esto significa que debemos estar presentes en varios centros de datos simultáneamente y sobrevivir tranquilamente a la interrupción de un centro de datos.
  3. El sistema debe ser escalable horizontalmente. El hecho es que todos nuestros sistemas actuales sólo son escalables verticalmente y ya estamos tocando el techo debido al bajo crecimiento de la potencia del hardware. Por tanto, ha llegado el momento en el que necesitamos tener un sistema escalable horizontalmente para sobrevivir.
  4. Entre otras cosas, nos dijeron que la solución tenía que ser barata.

Seguimos el camino estándar: formulamos los requisitos y contactamos con el departamento de compras. De allí recibimos una lista de empresas que, en general, están dispuestas a hacer esto por nosotros. Les contamos a todos sobre el problema y recibimos una evaluación de las soluciones de seis de ellos.

En el banco no confiamos en la palabra de nadie, nos gusta comprobarlo todo nosotros mismos. Por lo tanto, una condición obligatoria para nuestra licitación era pasar las pruebas de carga. Formulamos tareas de prueba de carga y tres de cada seis empresas ya acordaron implementar una solución prototipo basada en tecnologías en memoria por su propia cuenta para probarla.

No les diré cómo probamos todo y cuánto tiempo tomó, solo resumiré: el mejor rendimiento en las pruebas de carga lo mostró una solución prototipo basada en Tarantool del equipo de desarrollo de Mail.ru Group. Firmamos un acuerdo y comenzamos el desarrollo. Había cuatro personas del Grupo Mail.ru y de Alfa-Bank tres desarrolladores, tres analistas de sistemas, un arquitecto de soluciones, un propietario de producto y un Scrum Master.

A continuación les contaré cómo creció nuestro sistema, cómo evolucionó, qué hicimos y por qué exactamente esto.

Desarrollo

La primera pregunta que nos hicimos fue cómo obtener datos de nuestros sistemas actuales. Decidimos que HTTP era bastante adecuado para nosotros, porque todos los sistemas actuales se comunican entre sí enviando XML o JSON a través de HTTP.

Usamos el servidor HTTP integrado en Tarantool porque no necesitamos finalizar las sesiones SSL y su rendimiento es suficiente para nosotros.

Como ya dije, todos nuestros sistemas viven en diferentes modelos de datos, y en la entrada necesitamos llevar el objeto al modelo que nosotros mismos describimos. Se necesitaba un lenguaje que permitiera transformar los datos. Elegimos el imperativo Lua. Ejecutamos todo el código de conversión de datos en una zona de pruebas; este es un lugar seguro más allá del cual el código en ejecución no llega. Para hacer esto, simplemente cargamos el código requerido, creando un entorno con funciones que no pueden bloquear ni soltar nada.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Después de la conversión, se debe verificar que los datos cumplan con el modelo que estamos creando. Discutimos durante mucho tiempo cuál debería ser el modelo y qué lenguaje utilizar para describirlo. Elegimos Apache Avro porque el lenguaje es simple y cuenta con soporte de Tarantool. Las nuevas versiones del modelo y del código personalizado se pueden poner en funcionamiento varias veces al día, incluso bajo carga o sin ella, en cualquier momento del día, y adaptarse a los cambios muy rápidamente.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Después de la verificación, los datos deben guardarse. Hacemos esto usando vshard (tenemos réplicas de fragmentos geodispersas).

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Además, la especificidad es tal que a la mayoría de los sistemas que nos envían datos no les importa si los recibimos o no. Por eso implementamos una cola de reparación desde el principio. ¿Lo que es? Si por alguna razón un objeto no se somete a transformación o verificación de datos, aun así confirmamos la recepción, pero al mismo tiempo guardamos el objeto en la cola de reparación. Es consistente y está ubicado en el almacén de datos principal del negocio. Inmediatamente escribimos una interfaz de administrador, varias métricas y alertas. Como resultado, no perdemos datos. Incluso si algo ha cambiado en la fuente, si el modelo de datos ha cambiado, lo detectaremos inmediatamente y podremos adaptarnos.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Ahora necesitas aprender cómo recuperar datos guardados. Analizamos cuidadosamente nuestros sistemas y vimos que la pila clásica de Java y Oracle necesariamente contiene algún tipo de ORM que convierte datos de relacionales a objetos. Entonces, ¿por qué no dar inmediatamente objetos a los sistemas en forma de gráfico? Así que adoptamos felizmente GraphQL, que satisfizo todas nuestras necesidades. Le permite recibir datos en forma de gráficos y extraer solo lo que necesita en este momento. Incluso puedes versionar la API con bastante flexibilidad.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Casi de inmediato nos dimos cuenta de que los datos que estábamos extrayendo no eran suficientes. Creamos funciones que se pueden vincular a objetos en el modelo; esencialmente, campos calculados. Es decir, adjuntamos una determinada función al campo que, por ejemplo, calcula el precio medio de cotización. Y el consumidor externo que solicita los datos ni siquiera sabe que se trata de un campo calculado.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Implementé un sistema de autenticación.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Luego notamos que en nuestra decisión cristalizaron varios roles. Un rol es una especie de agregador de funciones. Normalmente, los roles tienen diferentes perfiles de uso de equipos:

  • T-Connect: maneja conexiones entrantes, CPU limitada, bajo consumo de memoria, sin estado.
  • IB-Core: transforma los datos que recibe mediante el protocolo Tarantool, es decir, opera con tablas. Tampoco almacena estado y es escalable.
  • Almacenamiento: solo almacena datos, no utiliza ninguna lógica. Este rol implementa las interfaces más simples. Escalable gracias a vshard.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Es decir, utilizando roles, desacoplamos diferentes partes del clúster entre sí, que se pueden escalar de forma independiente entre sí.

Entonces, hemos creado un registro de flujo de datos transaccionales asincrónicos y una cola de reparación con una interfaz de administración. La grabación es asíncrona desde un punto de vista empresarial: si tenemos la garantía de escribirnos datos a nosotros mismos, sin importar dónde, lo confirmaremos. Si no se confirma, entonces algo salió mal y es necesario enviar los datos. Esta es la grabación asincrónica.

pruebas

Desde el principio del proyecto, decidimos que intentaríamos implementar un desarrollo basado en pruebas. Escribimos pruebas unitarias en Lua usando el marco tarantool/tap y pruebas de integración en Python usando el marco pytest. Al mismo tiempo, involucramos tanto a desarrolladores como a analistas en la redacción de pruebas de integración.

¿Cómo utilizamos el desarrollo impulsado por pruebas?

Si queremos alguna característica nueva, primero intentamos escribir una prueba para ella. Cuando descubrimos un error, nos aseguramos de escribir una prueba primero y solo luego solucionarlo. Al principio es difícil trabajar así, hay malentendidos por parte de los empleados, incluso sabotajes: "Vamos a arreglarlo rápidamente ahora, hacer algo nuevo y luego cubrirlo con pruebas". Sólo que este “más tarde” casi nunca llega.

Por lo tanto, primero debe obligarse a escribir pruebas y pedir a otros que lo hagan. Créame, el desarrollo basado en pruebas aporta beneficios incluso a corto plazo. Sentirás que tu vida se ha vuelto más fácil. Creemos que el 99% del código ya está cubierto por pruebas. Esto parece mucho, pero no tenemos ningún problema: se ejecutan pruebas en cada confirmación.

Sin embargo, lo que más nos gusta son las pruebas de carga, las consideramos las más importantes y las realizamos periódicamente.

Les contaré una pequeña historia de cómo realizamos la primera etapa de pruebas de carga de una de las primeras versiones. Instalamos el sistema en la computadora portátil del desarrollador, encendimos la carga y obtuvimos 4 mil transacciones por segundo. Buen resultado para un portátil. Lo instalamos en un banco de carga virtual de cuatro servidores, más débil que en producción. Implementado al mínimo. Lo ejecutamos y obtenemos un resultado peor que en una computadora portátil en un hilo. Contenido de choque.

Estábamos muy tristes. Observamos la carga del servidor, pero resulta que están inactivos.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Llamamos a los desarrolladores, y nos explican, gente que venimos del mundo de Java, que Tarantool es monohilo. Sólo puede ser utilizado eficazmente por un núcleo de procesador bajo carga. Luego implementamos la cantidad máxima posible de instancias de Tarantool en cada servidor, activamos la carga y ya recibimos 14,5 mil transacciones por segundo.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Déjame explicarte de nuevo. Debido a la división en roles que usan los recursos de manera diferente, nuestros roles responsables de procesar las conexiones y la transformación de datos cargan solo el procesador y son estrictamente proporcionales a la carga.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
En este caso, la memoria se utilizó sólo para procesar conexiones entrantes y objetos temporales.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Por el contrario, en los servidores de almacenamiento la carga del procesador aumentó, pero mucho más lenta que en los servidores que procesan conexiones.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Y el consumo de memoria creció en proporción directa a la cantidad de datos cargados.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool

Servicios

Para desarrollar nuestro nuevo producto específicamente como plataforma de aplicaciones, creamos un componente para implementar servicios y bibliotecas en él.

Los servicios no son sólo pequeños fragmentos de código que operan en algunos campos. Pueden ser estructuras bastante grandes y complejas que forman parte de un clúster, verifican datos de referencia, ejecutan lógica de negocios y devuelven respuestas. También exportamos el esquema de servicio a GraphQL y el consumidor recibe un punto de acceso universal a los datos, con introspección en todo el modelo. Es muy cómodo.

Dado que los servicios contienen muchas más funciones, decidimos que debería haber bibliotecas en las que moveremos el código de uso frecuente. Los agregamos al entorno seguro, habiendo comprobado previamente que no nos rompe nada. Y ahora podemos asignar entornos adicionales a funciones en forma de bibliotecas.

Queríamos tener una plataforma no sólo para almacenamiento, sino también para informática. Y como ya teníamos un montón de réplicas y fragmentos, implementamos una especie de computación distribuida y lo llamamos reducción de mapa, porque resultó similar a la reducción de mapa original.

Sistemas antiguos

No todos nuestros sistemas heredados pueden llamarnos a través de HTTP y usar GraphQL, aunque admiten el protocolo. Por lo tanto, creamos un mecanismo que permite replicar datos en estos sistemas.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Si algo cambia para nosotros, se activan activadores únicos en la función de Almacenamiento y el mensaje con los cambios termina en la cola de procesamiento. Se envía a un sistema externo utilizando una función de replicador independiente. Esta función no almacena el estado.

Nuevas mejoras

Como recordarás, desde un punto de vista empresarial, hicimos grabación asincrónica. Pero luego se dieron cuenta de que esto no sería suficiente, porque hay una clase de sistemas que necesitan recibir inmediatamente una respuesta sobre el estado de la operación. Entonces ampliamos nuestro GraphQL y agregamos mutaciones. Encajan orgánicamente en el paradigma existente de trabajar con datos. Para nosotros, este es un punto único de lectura y escritura para otra clase de sistemas.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
También nos dimos cuenta de que los servicios por sí solos no serían suficientes para nosotros, porque hay informes bastante pesados ​​que deben crearse una vez al día, una semana o un mes. Esto puede llevar mucho tiempo y los informes pueden incluso bloquear el bucle de eventos de Tarantool. Por lo tanto, creamos roles separados: programador y ejecutor. Los corredores no almacenan el estado. Realizan tareas pesadas que no podemos calcular sobre la marcha. Y la función del programador monitorea el cronograma de inicio de estas tareas, que se describe en la configuración. Las tareas en sí se almacenan en el mismo lugar que los datos comerciales. Cuando llega el momento adecuado, el programador toma la tarea, se la entrega a algún corredor, quien la cuenta y guarda el resultado.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
No es necesario ejecutar todas las tareas según un cronograma. Algunos informes deben leerse a pedido. Tan pronto como llega este requisito, se crea una tarea en el sandbox y se envía al corredor para su ejecución. Después de un tiempo, el usuario recibe una respuesta asincrónica de que todo se ha calculado y el informe está listo.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
Inicialmente, nos adherimos al paradigma de almacenar todos los datos, versionarlos y no eliminarlos. Pero en la vida, de vez en cuando todavía hay que borrar algo, sobre todo información sin procesar o intermedia. Según los datos caducados, creamos un mecanismo para limpiar el almacenamiento de datos obsoletos.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool
También entendemos que tarde o temprano llegará una situación en la que no habrá suficiente espacio para almacenar datos en la memoria, pero aun así los datos deben almacenarse. Para estos fines, pronto crearemos almacenamiento en disco.

Cómo hicimos el núcleo del negocio de inversión de Alfa-Bank basado en Tarantool

Conclusión

Comenzamos con la tarea de cargar datos en un solo modelo y dedicamos tres meses a desarrollarlo. Teníamos seis sistemas de suministro de datos. El código completo de transformación en un solo modelo tiene aproximadamente 30 mil líneas en Lua. Y la mayor parte del trabajo aún está por delante. A veces falta motivación por parte de los equipos vecinos y son muchas las circunstancias que complican el trabajo. Si alguna vez se enfrenta a una tarea similar, multiplique el tiempo que le parece normal para su implementación por tres, o incluso cuatro.

Recuerde también que los problemas existentes en los procesos de negocio no se pueden resolver utilizando un nuevo DBMS, ni siquiera uno muy productivo. ¿Lo que quiero decir? Al comienzo de nuestro proyecto, creamos entre los clientes la impresión de que ahora traeremos una nueva base de datos rápida y ¡viviremos! Los procesos serán más rápidos, todo irá bien. De hecho, la tecnología no resuelve los problemas que tienen los procesos de negocio, porque los procesos de negocio son personas. Y es necesario trabajar con personas, no con tecnología.

El desarrollo basado en pruebas puede resultar doloroso y llevar mucho tiempo en las primeras etapas. Pero su efecto positivo se notará incluso a corto plazo, cuando no sea necesario hacer nada para realizar pruebas de regresión.

Es extremadamente importante realizar pruebas de carga en todas las etapas de desarrollo. Cuanto antes notes algún defecto en la arquitectura, más fácil será solucionarlo, lo que te permitirá ahorrar mucho tiempo en el futuro.

A Lua no le pasa nada. Cualquiera puede aprender a escribir en él: desarrollador de Java, desarrollador de JavaScript, desarrollador de Python, front-end o back-end. Incluso nuestros analistas escriben sobre ello.

Cuando hablamos del hecho de que no tenemos SQL, la gente aterroriza. “¿Cómo se obtienen datos sin SQL? ¿Es eso posible? Ciertamente. En un sistema de clases OLTP, no se necesita SQL. Existe una alternativa en forma de algún tipo de lenguaje que le devuelve inmediatamente a una vista orientada a documentos. Por ejemplo, GraphQL. Y existe una alternativa en forma de computación distribuida.

Si comprende que necesitará escalar, diseñe su solución en Tarantool de tal manera que pueda ejecutarse en paralelo en docenas de instancias de Tarantool. Si no hace esto, será difícil y doloroso más adelante, ya que Tarantool sólo puede utilizar eficazmente un núcleo de procesador.

Fuente: habr.com

Añadir un comentario