- Aunque el almacenamiento no volátil evolucionó de la cinta a HDD, SSD y almacenamiento en red en la nube, la ubicación y distribución de los datos siguen determinando la latencia de E/S
- El almacenamiento en cinta es fuerte en lecturas y escrituras secuenciales, pero puede tardar decenas de segundos en leer datos lejanos, por lo que no es adecuado para bases de datos transaccionales de alto tráfico
- Los HDD redujeron mucho la latencia frente a la cinta, pero por los platos giratorios y el movimiento del cabezal, las lecturas aleatorias suelen estar en el orden de 1~3 ms, y el rendimiento varía mucho según el orden de las solicitudes
- Los SSD funcionan con NAND flash sin piezas mecánicas, por lo que las lecturas aleatorias pueden llegar a ser tan rápidas como 16 μs, pero la distribución de datos sigue siendo importante por el aprovechamiento del paralelismo y el garbage collection
- En la nube, separar storage y compute facilita la escalabilidad y la respuesta ante fallas, pero agrega viajes de ida y vuelta por la red y límites de IOPS; PlanetScale Metal busca reducir ese costo con NVMe SSD conectados directamente y replicación
Elementos básicos que determinan la latencia del almacenamiento
- El almacenamiento no volátil conserva los datos aunque se apague la energía, y es la base para guardar datos como fotos, correos electrónicos, saldos bancarios y registros médicos
- El almacenamiento volátil, como los registros de CPU, la caché de CPU y la RAM, es más rápido, pero requiere energía constante
- El rendimiento del almacenamiento no depende solo de la capacidad, sino también de cómo se llega a los datos, la unidad de lectura y escritura, las colas, el paralelismo y si hay viajes de ida y vuelta por la red
- Con el lanzamiento de PlanetScale Metal, PlanetScale explicó que Metal ejecuta bases de datos en la nube sobre unidades NVMe locales en lugar de almacenamiento conectado por red
Almacenamiento en cinta: fuerte para acceso secuencial, débil para acceso aleatorio
- Desde la década de 1950, las computadoras usan unidades de cinta como almacenamiento digital no volátil
- Un cartucho de cinta está compuesto por varias pistas y muchas celdas, y el estado de polarización magnética de cada celda representa datos binarios
- Al insertar el cartucho en un lector y enrollarlo con un motor, el IO head lee los datos que pasan frente a él
- Si la posición de lectura o escritura está cerca del cabezal, es rápida; si está lejos, la latencia aumenta
- Incluso en sistemas de cinta modernos, para leer datos lejanos puede ser necesario enrollar cientos de metros
- En esos casos, una lectura puede tardar decenas de segundos
- Aun con la misma cantidad de lecturas y escrituras, si los datos están dispersos, lleva mucho más tiempo que con una disposición secuencial
- El ejemplo del texto muestra una situación en la que lecturas y escrituras dispersas tardan alrededor de 7 veces más para la misma carga de trabajo
- La cinta tiene mala latencia para lecturas y escrituras aleatorias, pero sigue siendo adecuada para lecturas y escrituras secuenciales largas
- Tiene menor costo por GB que SSD y HDD, y una vida útil de archivo más larga
- CERN administra más de 400 PB de datos en un data warehouse de almacenamiento en cinta
- AWS también ofrece un servicio de archivado en cinta
- La cinta no es adecuada para bases de datos transaccionales de alto tráfico
HDD: el equilibrio entre discos giratorios y cola de comandos
- Un HDD guarda datos en platos, que son discos metálicos circulares, en lugar de cinta
- Los platos giran rápidamente dentro de un enclosure; en el ejemplo se presenta 7200 RPM como una velocidad común
- Las pistas de un HDD son circulares, y un solo disco puede tener más de 100,000 pistas
- Cada pista contiene cientos de miles de páginas, y cada página almacena aproximadamente 4 KB de datos
- Un HDD alinea la posición de lectura y escritura mediante el movimiento del cabezal y la rotación del plato
- A diferencia de la cinta, los bits de toda la superficie siempre están accesibles
- No hace falta enrollar cinta hasta que aparezcan los datos deseados
- Una lectura aleatoria típica puede ejecutarse en 1~3 ms
- El orden de las solicitudes influye mucho en el rendimiento
- Las lecturas y escrituras con alta secuencialidad terminan rápido
- Aunque sean las mismas 6 lecturas y escrituras, si el orden está mezclado, aumenta el tiempo de espera hasta que el plato llegue a la posición correcta
- Los discos magnéticos admiten cola de comandos desde hace mucho tiempo
- SCSI ofrece funciones relacionadas desde la década de 1980, y SATA desde la década de 2000
- El SO puede enviar varios comandos para que se ejecuten en paralelo o en un orden distinto
- El controlador del disco puede usar la cola de trabajos para programar lecturas y escrituras según la estructura del disco
- Aunque los HDD mejoraron frente a la cinta, en especial en lecturas y escrituras aleatorias todavía pueden ser lentos
SSD: variables de rendimiento que permanecen aunque desaparezcan las piezas mecánicas
- Los SSD, o almacenamiento flash, se inventaron en la década de 1980, pero se volvieron masivos como almacenamiento de consumo en la década de 2000
- Los SSD no dependen de piezas mecánicas para leer datos
- Usan transistores no volátiles llamados NAND flash
- Los 1 y 0 se leen, escriben y borran mediante señales eléctricas, sin mover componentes físicos
- Un SSD está compuesto por uno o más target, cada target contiene varios blocks, y cada block contiene varias pages
- Los SSD leen y escriben por page
- Aunque solo se necesite parte de los datos, la unidad de solicitud del drive es la page
- En la configuración de ejemplo, si la page tiene 4096 bits, el block tiene 16K pages, el target tiene 16K blocks y el dispositivo tiene 8 targets, el total es
4k * 16k * 16k * 8 = 8,796,093,022,208bits, es decir 8 TB - Las lecturas aleatorias en SSD varían según el modelo, pero pueden ser tan rápidas como 16 μs
- Aunque no haya piezas mecánicas, la distribución de los datos sigue siendo importante
- Entre los factores de rendimiento de SSD están el paralelismo y el garbage collection
Paralelismo en SSD: la distribución entre targets cambia el throughput
- En general, cada target tiene una línea dedicada conectada a la unidad de control
- Cada línea procesa lecturas y escrituras, pero solo puede transferir una page a la vez
- La transferencia de una page es muy rápida, pero aun así toma una pequeña cantidad de tiempo
- Si 8 escrituras se distribuyen entre 4 targets, se pueden usar 4 líneas en paralelo y escribirlas en dos intervalos de tiempo
- Si las 8 escrituras se concentran en el mismo target, se usa una sola línea y las demás quedan ociosas
- El orden de lecturas y escrituras y la distribución de datos también afectan el rendimiento en SSD
- Al diseñar software como MySQL, hay que prestar atención a en qué estructura se guardan los datos y cómo se distribuyen en disco
Garbage collection en SSD: el costo de borrar antes de escribir
- Una page de SSD puede leerse muchas veces, pero una page escrita no puede sobrescribirse con datos nuevos hasta que los datos existentes se borren explícitamente
- No se pueden borrar pages individuales; hay que borrar el block completo
- Un SSD necesita algoritmos internos para administrar pages empty, in-use y dirty
- Una dirty page es una page que fue escrita, pero cuyos datos ya no se necesitan y está lista para borrarse
- En algunos casos se deben reubicar datos para aceptar una nueva write; el algoritmo que gestiona esto es el garbage collector
- Si hay suficientes pages unused, los datos nuevos pueden escribirse directamente
- Si faltan pages unused y hay muchas dirty pages, primero hay que ejecutar garbage collection
- En el ejemplo, para escribir 5 pages nuevas se mueven 2 pages non-dirty a otra ubicación
- Después, todas las pages de ese target se marcan como dirty para que puedan borrarse
- Estos pasos adicionales ralentizan mucho el rendimiento de write
- En un SSD ocupado con muchas lecturas, escrituras y borrados, el garbage collection puede hacer que otras operaciones se vuelvan más lentas
El cambio que agregó la nube: separar storage y compute
- El paso de cinta a HDD y SSD mejoró mucho el rendimiento de E/S durable
- La migración a la nube introdujo otro cambio en el rendimiento de E/S
- AWS se presenta como un servicio que, desde su lanzamiento en 2006, impulsó fuertemente la migración a la nube
- En entornos cloud, los usuarios alquilan servidores virtualizados sobre hardware arbitrario en grandes centros de datos
- Un servidor puede terminarse en cualquier momento por muchas razones, como fallas de hardware, reemplazos o desconexiones de red
- Al construir sistemas sobre infraestructura cloud alquilada, deben poder tolerar fallas más frecuentes
- Estas condiciones y la necesidad de volúmenes de almacenamiento escalables dinámicamente llevaron a la separación de storage y compute
Ventajas y costos del almacenamiento conectado por red
- Tradicionalmente, servidores, computadoras de escritorio, laptops y teléfonos conectan directamente el almacenamiento no volátil
- Se usan cables SATA, interfaces PCIe o integración dentro del mismo SoC
- El almacenamiento conectado directamente es rápido, pero tiene dos limitaciones
- Si el servidor se cae, los datos también dejan de estar disponibles
- El tamaño del almacenamiento es fijo
- Los servidores de aplicaciones suelen encajar bien en entornos temporales (ephemeral), y como muchas operaciones ocurren en memoria, este problema no suele ser grave
- Una base de datos no debe perder datos aunque el servidor se caiga, y el tamaño de los datos puede crecer rápidamente hasta alcanzar el límite de almacenamiento
- Muchos proveedores cloud permiten adjuntar a las instancias de compute almacenamiento conectado por red configurable por separado
- La configuración básica de EC2 normalmente adjunta un volumen de almacenamiento de red EBS
- Servicios de bases de datos como Amazon RDS, Amazon Aurora, Google Cloud SQL y PlanetScale también dependen de sistemas donde compute y storage están separados por red
- Este enfoque permite ajustar dinámicamente el volumen de almacenamiento según aumenten o disminuyan los datos
- Aunque el servidor se caiga, los datos quedan seguros y pueden adjuntarse de nuevo a otro servidor
- A cambio, aparece un costo de rendimiento por los viajes de ida y vuelta por la red y los límites de IOPS
Diferencia de latencia entre NVMe local y almacenamiento de red
- Un NVMe SSD conectado directamente es un SSD que usa la especificación de interfaz de controlador host para memoria no volátil, y ofrece altas velocidades de E/S y ancho de banda
- El viaje de ida y vuelta de la CPU a la RAM se presenta como aproximadamente 100 ns
- El viaje de ida y vuelta de la CPU a un NVMe SSD conectado localmente es de aproximadamente 50,000 ns, es decir 50 μs
- Un volumen de almacenamiento conectado por red requiere un viaje de ida y vuelta corto dentro del centro de datos
- El almacenamiento conectado por red como EBS se presenta con un tiempo de ida y vuelta de aproximadamente 250,000 ns, es decir 250 μs o 0.25 ms
- Aunque se usen los mismos SSD modernos, la conexión por red hace que el tiempo de procesamiento de cada solicitud de lectura y escritura sea mayor por un factor de un solo dígito
- En E/S secuencial masiva, el impacto negativo puede reducirse, pero no eliminarse
- El almacenamiento conectado por red genera latencia adicional cada vez que se accede al sistema de almacenamiento
Límites de IOPS y diferencia con el almacenamiento conectado directamente
- Muchos proveedores cloud, incluidos AWS y Google Cloud, limitan la cantidad de operaciones de E/S que pueden enviarse por el wire en el modelo de almacenamiento conectado por red
- Una instancia EBS GP3 de Amazon permite por defecto 3000 IOPS
- Puede configurarse más alto, pero tiene costo adicional
- Los volúmenes EBS GP2 anteriores funcionan acumulando un pool de IOPS para permitir bursts ocasionales
- Si el almacenamiento se conecta directamente a la instancia de compute, no hay límites artificiales de operaciones de E/S
- En una conexión directa, se puede leer y escribir tanto como lo permita el hardware
Cómo mantener durabilidad y escalabilidad
- En SSD conectados directamente, el problema 1, la durabilidad de los datos, puede resolverse con replicación
- Un enfoque común consiste en tener un servidor como primary que reciba todas las solicitudes de write, mientras 2 o más servidores adicionales replican los datos
- Si los datos están en tres lugares, la probabilidad de pérdida de datos disminuye
- Con las cifras del ejemplo, si se asume una probabilidad mensual de falla del servidor de 1%:
- En un solo servidor, la probabilidad mensual de pérdida de datos es 1%
- En tres servidores, baja a
1% × 1% × 1% = 0.0001%, es decir 1 en 1 millón
- PlanetScale detecta y reemplaza automáticamente los nodos fallidos, y hace respaldos frecuentes y confiables de los datos de la base de datos
- El problema 2, la escalabilidad del drive, requiere más intervención manual
- Se necesitan monitoreo y alertas cuando el disco se acerca a su límite de capacidad
- Se necesitan herramientas para aumentar la capacidad fácilmente cuando sea necesario
El enfoque de PlanetScale Metal
- Metal ofrece clústeres de bases de datos que usan NVMe SSD conectados directamente
- Cada instancia de base de datos se ejecuta con direct-attached NVMe SSD
- Un clúster Metal se compone por defecto de 1 primary y 2 replicas
- Los clústeres de bases de datos compatibles son Vitess o Postgres
- Al alcanzar el límite de almacenamiento, se puede redimensionar a un servidor con unidades más grandes con unos pocos clics
- Internamente, se levanta un nodo nuevo y se migran los datos de la instancia existente a la nueva; este proceso se maneja con zero downtime
- Las bases de datos Metal no tienen un cap artificial de IOPS
- Los usuarios pueden ejecutar operaciones de E/S con baja latencia y usar tanto como lo permita el hardware, sin pagar clases costosas de IOPS del proveedor cloud ni sufrir throttle
1 comentarios
Opiniones en Hacker News
Soy el autor del blog. Disfruté muchísimo el proceso de escribir este artículo y, por lejos, es el más complejo que he hecho hasta ahora.
Para crear las visualizaciones interactivas escribí, literalmente, miles de líneas de JavaScript, así que espero que todos lo disfruten.
Dicho eso, la expresión “1 en un millón” sobre la durabilidad me parece demasiado pesimista si se considera que el tiempo de falla antes de que entre un servidor nuevo y se replique de nuevo es corto.
Por ejemplo, si la recuperación toma 10 minutos, incluso si tres servidores fallaran sí o sí una vez al mes, la probabilidad de que se superpongan y fallen todos ya sería de alrededor de 1 en 2 millones; y si la probabilidad de falla mensual fuera del 1%, la posibilidad de que se superpongan tres fallas sería extremadamente baja.
Lo comento porque, si tienes un millón de clientes, 1 en un millón no es una cifra tan buena.
Sé que el tiempo tecleando y el tiempo dándole vueltas en la cabeza pueden ser bastante distintos.
Este tema me resulta muy familiar, así que no tengo nada que agregar sobre el contenido en sí, y al revisarlo por encima se ve bien. Pero estoy ideando animaciones para mi propio blog y varias librerías que probé últimamente no me convencieron.
Durante un tiempo estuve impulsando la combinación SQLite+NVMe. Personalmente la veo como un patrón nuevo que permite llegar mucho más lejos de lo habitual y, en algunos casos, aguantar hasta el final sin escalado horizontal.
En rendimiento, la latencia manda, sobre todo cuando los elementos deben procesarse en serie. Ejecutar SQLite sobre NVMe da una ventaja de latencia que otros proveedores no pueden ofrecer.
Tampoco creo que, en la mayoría de los casos de uso reales, ejecutar en memoria sea mucho mejor que el almacenamiento persistente en NVMe.
En un solo host puede ser un poco más rápido, pero en el momento en que pasas de 1 servidor web a 2 y ambos tienen que escribir en la base de datos, parece que te estás complicando la vida.
Decir que la latencia es importante también puede ser engañoso. Si no hay consistencia, el rendimiento no significa nada, y en cuanto tienes varios servidores web esa consistencia la tienes que resolver tú mismo.
Además, la latencia de la base de datos suele ser mucho menor que la latencia de ida y vuelta por Internet, y esa latencia de Internet también es pequeña comparada con la “latencia” de esperar a que carguen recursos de la página como imágenes o librerías de código.
Para empezar, hay que evitar al máximo las consultas seriales a la base de datos; usar joins cuando sea posible y, cuando no lo sea, lanzar las consultas de forma asíncrona y simultánea siempre que se pueda para que se ejecuten en paralelo.
Para evitar el problema de escrituras paralelas, además de configurar cierto modo de operación tosco, se puede usar el truco de tener un único hilo dedicado a escrituras en la aplicación.
Eso suele volver un poco más complejo un código paralelo que ya era complejo. Con un solo hilo de escritura, SQLite funciona realmente muy bien.
fsync()sobre un archivo en un sistema de archivos ext4 en una computadora de escritorio, incluso en un disco NVMe todavía se mide una latencia de 1 a 2 ms.En sistemas más recientes era de alrededor de 800 µs.
La cantidad de información era tan buena que leí todo olvidando por completo que era una promoción de producto. La visualización y la interacción son excelentes.
La animación de E/S de disco me hizo pensar en Melvin Kaye.
Mel no usaba bucles de retardo temporal ni siquiera cuando la lenta Flexowriter necesitaba una pausa entre caracteres de salida.
En cambio, ajustaba la posición de las instrucciones en el tambor para que, cada vez que se necesitara la siguiente instrucción, el cabezal de lectura acabara de pasar por ella, y el tambor tuviera que dar una vuelta más para encontrarla.
https://pages.cs.wisc.edu/~markhill/cs354/Fall2008/notes/The...
Metal se ve realmente genial, pero cuando en mi trabajo anterior usé los SSD locales de instancia de GCP, tuvimos problemas graves de confiabilidad, como bloques del dispositivo que perdían datos.
Me pregunto si la situación cambió y qué tipo de máquina usan.
En aquel entonces, la solución alternativa era esta: https://discord.com/blog/how-discord-supercharges-network-di...
Sin embargo, operamos un sistema redundante con replicación semisíncrona de MySQL para que todas las escrituras queden persistidas en dos máquinas de distintas zonas de disponibilidad antes de confirmarse al cliente.
El operador de Kubernetes y el proceso
vtorcde Vitess trabajan juntos para detectar y reemplazar activamente réplicas fallidas o sospechosas.En GCP vimos los mejores resultados con máquinas n2d-highmem, y en AWS usamos de forma bastante generalizada tipos de última generación con instance store.
Es un buen artículo. En general, también existe el problema de que el almacenamiento en la nube es particularmente lento.
Ya se ha tratado en otros lugares, pero este artículo resume bien el problema: http://databasearchitects.blogspot.com/2024/02/ssds-have-bec...
Hace poco se agregó soporte en https://github.com/feldera/feldera para guardar índices incrementales en S3/almacenamiento de objetos; NVMe ya era compatible desde mucho antes por las ventajas de rendimiento obvias mencionadas en el artículo anterior.
Ojalá alguien sacuda este espacio con una mejor forma de ofrecerlo.
Hay un aspecto del almacenamiento distribuido que este artículo no valora lo suficiente.
Primero, algunos sistemas no incluyen replicación de forma predeterminada. Un clúster de Cassandra o MySQL puede hacer replicación maestro-esclavo, pero muchos sistemas no.
Segundo, si usas almacenamiento NVMe en la nube, tienes que preocuparte por las ventanas de mantenimiento y los drains iniciados por el proveedor de nube, lo que vuelve la operación mucho más difícil.
Si no lo integras con esos sistemas para sacar los datos hacia otros nodos, los datos desaparecen.
Al separar almacenamiento y cómputo, el operador de la nube puede vaciar y mover el cómputo cuando lo necesite; los datos son independientes del cómputo, y como el operador de la nube también administra ese sistema de datos y los drains, puede ajustar la colocación de las cargas de trabajo sin intervención del cliente.
El almacenamiento conectado por red y replicado que parece una API de sistema de archivos “local” es una forma poderosa de dar durabilidad a sistemas que no tienen replicación integrada, como el nuestro.
De verdad es excelente, y PlanetScale Metal también se ve bastante sólido. Me gusta especialmente ver la gran caída de latencia en el lanzamiento: https://planetscale.com/blog/upgrading-query-insights-to-met...
Durante años no entendí por qué las bases de datos replicadas siempre se aferraban a EBS y aceptaban esa latencia. Si ya hay replicación, me preguntaba por qué no animarse a usar discos locales.
En una organización anterior, cuando operábamos Elasticsearch como almacenamiento temporal de logs/métricas, propuse hacerlo así, ya que los requisitos de confiabilidad no eran altos, pero no pude convencerlos y terminamos usando el peor AWS Elasticsearch.
Sé que la capacidad de los discos locales es finita, pero me parece que la proporción de cores/memoria/disco debería alcanzar para la mayoría de los casos de uso. También hay muchas instancias con discos locales en distintas proporciones, así que se puede encontrar un equilibrio adecuado.
Incluso se podría implementar almacenamiento hot/cold con instancias de discos duros locales de más de 20 TB.
Quiero felicitar mucho al equipo de PlanetScale porque por fin está haciendo algo que tiene sentido. Que ni siquiera AWS ejecute Elasticsearch sobre discos locales... basta con pensar que cosas como ClickHouse o Cassandra se ejecutan todas sobre discos locales.
El problema principal era que el disco se borra después de un evento de stop-start. Aunque el resto del clúster esté bien y haya réplicas disponibles, SQL Server no puede manejarlo automáticamente.
Como no recupera automáticamente el nodo reinicializado, el scripting y las pruebas para rodear esto son difíciles de asumir en producción, salvo para las organizaciones más audaces y capaces.
Operamos cientos de clústeres de ClickHouse con este modelo. Es mucho más común ajustar el tamaño para resolver problemas de rendimiento que por fallas.
Por ejemplo, si aparece un problema de rendimiento de un tenant un domingo por la mañana, hora de EE. UU., la solución más simple es subirlo a una VM más grande durante el fin de semana y dejar que el equipo principal vea la causa raíz el lunes por la mañana.
El costo adicional es pequeño y evita el burnout de empleados, que es mucho más caro.
Es un artículo realmente excelente, y la visualización de escrituras aleatorias está muy bien hecha.
Tengo algunas preguntas quizá tontas sobre los límites de IOPS del almacenamiento conectado por red.
Primero, me pregunto si el límite de “IOPS” es efectivamente un rate limit sobre un tipo específico de tráfico de red, es decir, el tráfico hacia y desde los volúmenes EBS. En última instancia, quiero preguntar si “IOPS” significa “tráfico de red de volúmenes EBS”.
Segundo, me pregunto si este enfoque también ahorra costos. Si es así, no sé si se debe a un arbitraje extraño de precios de AWS o a una ganancia de eficiencia por usar menos networking de EBS.
Parece claro que poner almacenamiento y cómputo en la misma máquina tiene la ventaja estructural de eliminar un salto en términos de latencia, pero quisiera saber si también hay una ganancia en throughput por dólar.
Yo suelo verlo con otro modelo: un volumen EBS no es una porción de una placa física conectada al bus PCIe, sino una participación en un gran sistema distribuido compuesto por muchísimas unidades físicas, más parecido a una SAN con capacidad de red dedicada hacia y desde el cómputo.
Puede ahorrar costos, pero al final es un conjunto de compromisos.