En las dos lecciones anteriores hemos contado el coste de un fallo de página en milisegundos y hemos visto un servidor caer en hiperpaginación por culpa del disco. Ahora toca mirar de frente ese componente que hemos estado tratando como una caja negra lenta. Porque no es una caja negra: un disco mecánico y un SSD NVMe tienen físicas completamente distintas, y las decisiones que el sistema operativo toma para uno son contraproducentes para el otro.
Un aviso sobre el alcance: esta lección trata el almacenamiento como recurso gestionado, no como sistema de archivos. Aquí verás la física del dispositivo, cuánto cuesta un acceso, cómo se ordenan las peticiones y cómo se combinan varios discos en un volumen fiable. Todo lo que tiene que ver con ficheros, directorios, inodos, particiones y montaje corresponde al módulo 4. La frontera es clara: aquí gestionamos bloques numerados; allí se les da significado.
Contenido
- La jerarquía de almacenamiento completa
- El disco duro mecánico por dentro
- Cálculo del tiempo de un acceso a disco
- SSD y memoria NAND: otra física, otras reglas
- Amplificación de escritura, recolección de basura y TRIM
- NVMe y por qué cambia las reglas
- LBA y la abstracción del dispositivo de bloques
- Planificación de peticiones de disco
- Los planificadores reales de Linux
- RAID: combinar discos para capacidad, velocidad o fiabilidad
- La decisión de Meteora para
/var/lib/meteora - Medición con
lsblkeiostat -x
La jerarquía de almacenamiento completa
En 01-01 vimos la jerarquía de memoria hasta la RAM. Ahora la completamos hacia abajo, que es donde las diferencias se vuelven brutales:
| Nivel | Latencia típica | Ancho de banda | Capacidad | Coste por GB | Volátil |
|---|---|---|---|---|---|
| Registros | 0,3 ns | — | ~1 KB | — | Sí |
| Caché L1 | 1 ns | 1 TB/s | 64 KB | — | Sí |
| Caché L2 | 4 ns | 500 GB/s | 1 MB | — | Sí |
| Caché L3 | 15 ns | 200 GB/s | 32 MB | — | Sí |
| RAM (DDR4) | 80-100 ns | 20 GB/s | 8 GB | 4 € | Sí |
| SSD NVMe | 20-100 µs | 3.500 MB/s | 1 TB | 0,08 € | No |
| SSD SATA | 100-200 µs | 550 MB/s | 1 TB | 0,06 € | No |
| Disco duro | 5-15 ms | 150 MB/s | 8 TB | 0,02 € | No |
| Cinta LTO-9 | decenas de segundos | 400 MB/s | 18 TB | 0,008 € | No |
Los saltos entre niveles adyacentes son de 2 a 5 veces, salvo uno:
El abismo está entre la RAM y el almacenamiento persistente, y ese abismo es la razón de existir de la caché de páginas, del buffering que calculamos en 01-06 y de la paginación por demanda de la lección anterior. Todo el diseño de un sistema operativo en la parte de E/S consiste en evitar cruzarlo.
Una analogía en escala humana, escalando 1 ns a 1 segundo:
| Operación | Tiempo real | En escala humana |
|---|---|---|
| Acceso a caché L1 | 1 ns | 1 segundo |
| Acceso a RAM | 100 ns | 1 minuto y medio |
| Acceso a SSD NVMe | 50 µs | 14 horas |
| Acceso a disco duro | 8 ms | 3 meses |
| Reinicio del servidor | 60 s | 1.900 años |
Cuando el agregador provoca un fallo mayor, desde el punto de vista de la CPU es como esperar tres meses por un dato.
El disco duro mecánico por dentro
Un HDD es el único componente con partes móviles en un servidor moderno, y su física gobierna todo su comportamiento.
Vista lateral: Vista superior de un plato:
┌─────────────────┐ ╭─────────────╮
═══╪═══ plato 0 ═════╡ ← cabezal │ ╭─────────╮ │ ← pista 0 (externa)
│ │ │ │ ╭─────╮ │ │ ← pista 1
═══╪═══ plato 1 ═════╡ ← cabezal │ │ │ · │ │ │ ← eje
│ │ │ │ ╰─────╯ │ │
═══╪═══ plato 2 ═════╡ ← cabezal │ ╰─────────╯ │
└────────┬────────┘ ╰─────────────╯
brazo actuador sector = arco de pistaEl vocabulario, que hay que tener claro para los cálculos:
| Término | Qué es |
|---|---|
| Plato | Disco magnético giratorio. Un HDD tiene entre 1 y 9 |
| Cara | Cada lado de un plato; cada una tiene su cabezal |
| Pista | Circunferencia concéntrica en una cara |
| Cilindro | Conjunto de pistas del mismo radio en todos los platos |
| Sector | Unidad mínima de lectura/escritura: 512 bytes o 4 KB |
| Cabezal | Lee y escribe; todos se mueven juntos en el brazo |
El cilindro es un concepto clave: como todos los cabezales se mueven solidariamente, acceder a datos del mismo cilindro no requiere mover el brazo, aunque estén en platos distintos. Es prácticamente gratis.
Un acceso tiene tres componentes de tiempo:
| Componente | Qué ocurre | Orden de magnitud | ¿Depende de? |
|---|---|---|---|
| Tiempo de búsqueda (seek) | Mover el brazo al cilindro correcto | 3-12 ms | La distancia recorrida |
| Latencia rotacional | Esperar a que el sector pase bajo el cabezal | 2-8 ms | Las RPM del disco |
| Tiempo de transferencia | Leer los datos mientras giran | 0,01-0,1 ms | El tamaño del bloque |
La latencia rotacional media es exactamente media vuelta, porque en promedio el sector estará a mitad de camino:
| RPM | Vuelta completa | Latencia rotacional media |
|---|---|---|
| 5.400 | 11,1 ms | 5,56 ms |
| 7.200 | 8,33 ms | 4,17 ms |
| 10.000 | 6,0 ms | 3,00 ms |
| 15.000 | 4,0 ms | 2,00 ms |
Cálculo del tiempo de un acceso a disco
Vamos a calcularlo con los datos del disco de meteo-01:
Disco: 7.200 RPM Tiempo de búsqueda medio: 8,5 ms Tasa de transferencia sostenida: 150 MB/s Sector: 4 KB
Caso 1: leer un bloque de 4 KB en una posición aleatoria.
Búsqueda: 8,50 ms
Latencia rotacional: 4,17 ms (60.000 ms/min ÷ 7.200 RPM ÷ 2)
Transferencia: 4 KB / 150 MB/s = 0,027 ms
──────────
Total: 12,70 msObserva la proporción, que es lo verdaderamente importante:
El 99,8 % del tiempo se dedica a posicionarse, no a leer. Esta única cifra explica todo el diseño de los sistemas de almacenamiento sobre disco mecánico.
Caso 2: leer 1 MB contiguo.
Búsqueda: 8,50 ms
Latencia rotacional: 4,17 ms
Transferencia: 1 MB / 150 MB/s = 6,67 ms
──────────
Total: 19,34 msLeer 256 veces más datos solo cuesta un 52 % más de tiempo.
Caso 3: leer ese mismo 1 MB en 256 bloques de 4 KB dispersos.
Comparación directa:
| Patrón | Tiempo | MB/s efectivos |
|---|---|---|
| 1 MB secuencial | 19,3 ms | 51,8 MB/s |
| 1 MB en 256 bloques aleatorios | 3.251 ms | 0,31 MB/s |
| Factor de diferencia | 168× |
Un disco mecánico es 168 veces más lento con acceso aleatorio que secuencial. De ahí salen tres consecuencias que dominan el diseño de sistemas:
- Leer más de lo pedido casi sale gratis (lectura anticipada, readahead): ya que has pagado la búsqueda, aprovecha.
- Agrupar escrituras dispersas en una secuencial compensa enormemente, aunque implique escribir más bytes. Es el fundamento de los sistemas de archivos estructurados en registro y del journaling (04-05).
- Reordenar las peticiones para minimizar el movimiento del brazo tiene un impacto gigantesco. Es el tema del apartado 8.
Aplicado a Meteora, con los 17 MB diarios de /var/lib/meteora/lecturas/:
Lectura secuencial del día: 17 MB / 150 MB/s + 12,7 ms ≈ 126 ms Lectura en 4.250 bloques de 4 KB: 4.250 × 12,7 ms ≈ 54 segundos
El mismo dato, 428 veces más lento. Por eso el agregador debe recorrer el fichero en orden, y por eso madvise(MADV_SEQUENTIAL) de la lección anterior tiene sentido.
SSD y memoria NAND: otra física, otras reglas
Un SSD no tiene partes móviles. Almacena bits como carga eléctrica atrapada en celdas de memoria flash NAND. Esto elimina búsqueda y latencia rotacional, pero introduce restricciones nuevas y muy peculiares.
La estructura interna:
SSD
└── Canales (4-8, en paralelo)
└── Chips NAND
└── Bloques de borrado (256 KB - 4 MB)
└── Páginas (4-16 KB) ← unidad de LECTURA y ESCRITURAY aquí está la asimetría que lo explica todo:
| Operación | Unidad | Tiempo típico | Restricción |
|---|---|---|---|
| Leer | Página (4-16 KB) | 25-100 µs | Ninguna |
| Escribir | Página (4-16 KB) | 200-900 µs | Solo en páginas ya borradas |
| Borrar | Bloque (256 KB-4 MB) | 2-10 ms | Afecta a todo el bloque |
No se puede sobrescribir una página de flash. Hay que borrarla antes, y el borrado solo funciona sobre bloques enteros que son cientos de veces más grandes que la página.
Esta restricción, que parece un detalle técnico menor, tiene consecuencias en cascada sobre todo el comportamiento del dispositivo.
El problema de la escritura desalineada
Supón que quieres modificar 4 KB dentro de un bloque de 2 MB que está lleno de datos. La secuencia ingenua sería:
1. Leer los 2 MB del bloque a un búfer interno → 2 MB de lectura 2. Modificar los 4 KB en el búfer 3. Borrar el bloque de 2 MB → 5 ms de borrado 4. Reescribir los 2 MB → 2 MB de escritura
Has escrito 2 MB en la flash para modificar 4 KB. El factor de amplificación es de 512.
Ningún SSD real hace esto, precisamente porque sería inaceptable. En su lugar, el controlador escribe los 4 KB nuevos en una página ya borrada de otro sitio, y actualiza una tabla interna que traduce direcciones lógicas a físicas. La página antigua queda marcada como inválida, pendiente de reciclaje.
Esa tabla se llama FTL (Flash Translation Layer) y es, conceptualmente, una tabla de páginas dentro del SSD: el mismo mecanismo de indirección que estudiamos en la lección anterior, aplicado al almacenamiento. Ni el sistema operativo ni tú veis nunca las direcciones físicas de la flash.
Amplificación de escritura, recolección de basura y TRIM
Como las páginas inválidas se acumulan, el SSD necesita reciclarlas. Ese proceso es la recolección de basura (garbage collection):
Bloque A (2 MB) antes: [válida][inválida][válida][inválida][inválida][válida][libre][libre] Proceso: 1. Copiar las 3 páginas válidas a un bloque nuevo 2. Borrar el bloque A entero 3. El bloque A queda disponible Bloque A después: [libre][libre][libre][libre][libre][libre][libre][libre]
El coste: para liberar espacio ha habido que copiar datos que ya estaban escritos. Eso es amplificación de escritura (write amplification):
| Escenario | WA típica | Por qué |
|---|---|---|
| Escritura secuencial, SSD vacío | 1,0-1,1 | Los bloques se llenan y se reciclan enteros |
| Escritura aleatoria, SSD al 50 % | 2-3 | Hay que reubicar páginas válidas |
| Escritura aleatoria, SSD al 95 % | 5-10 | Apenas quedan bloques libres para reciclar |
| Escritura aleatoria, sin TRIM | 10-20 | El SSD no sabe qué datos están obsoletos |
Un SSD casi lleno se comporta mucho peor que uno con espacio libre. Y no es solo cuestión de rendimiento: la flash tiene un número limitado de ciclos de borrado por celda.
| Tipo de NAND | Bits por celda | Ciclos de borrado | Uso |
|---|---|---|---|
| SLC | 1 | 50.000-100.000 | Industrial, caché |
| MLC | 2 | 3.000-10.000 | Empresa |
| TLC | 3 | 1.000-3.000 | Consumo y servidor |
| QLC | 4 | 300-1.000 | Archivo, lectura intensiva |
Con esto se puede calcular la vida útil del SSD de meteo-01:
SSD TLC de 1 TB, 1.500 ciclos de borrado Escritura total soportada = 1 TB × 1.500 = 1.500 TBW (terabytes escritos) Escritura diaria de Meteora: Lecturas: 17 MB/día Registros: ~200 MB/día Backups y temporales: ~500 MB/día Total: ~720 MB/día Con amplificación de escritura de 3: 720 MB × 3 = 2,16 GB/día en la flash Vida útil = 1.500 TB / 2,16 GB/día = 694.444 días = 1.902 años
La carga de Meteora no desgastará el SSD nunca. Pero cambia el escenario: un servidor de base de datos que escriba 500 GB/día con WA de 5 gastaría 2,5 TB/día, y esos mismos 1.500 TBW durarían 600 días. Por eso el TBW es una especificación que hay que mirar al comprar SSD para servidores de escritura intensiva.
Nivelado de desgaste
Si el controlador escribiera siempre en los mismos bloques, esos se agotarían mientras el resto queda intacto. El nivelado de desgaste (wear leveling) reparte las escrituras uniformemente, e incluso mueve datos estáticos que llevan mucho tiempo sin cambiar para liberar sus bloques poco desgastados.
Es otra de las razones por las que el SSD necesita indirección: la relación entre dirección lógica y ubicación física cambia constantemente.
TRIM
Cuando borras un fichero, el sistema de archivos marca sus bloques como libres en sus propias estructuras, pero el SSD no se entera: para él, esos datos siguen siendo válidos y los seguirá copiando durante la recolección de basura.
La orden TRIM (discard en NVMe) le comunica al SSD qué bloques ya no contienen datos útiles:
$ sudo fstrim -av
/var/lib/meteora: 128,4 GiB (137886920704 bytes) trimmed on /dev/nvme0n1p2
/: 12,1 GiB (12992958464 bytes) trimmed on /dev/nvme0n1p1
$ systemctl status fstrim.timer
● fstrim.timer - Discard unused blocks once a week
Loaded: loaded (/lib/systemd/system/fstrim.timer; enabled)
Active: active (waiting) since Mon 2026-08-24 00:00:12 CEST
Trigger: Mon 2026-09-07 00:00:00 CEST; 6 days leftSin TRIM, el SSD acaba creyendo que está lleno aunque el sistema de archivos vea espacio libre, y la amplificación de escritura se dispara. Las distribuciones modernas activan fstrim.timer semanalmente, que es la opción recomendada frente a discard en las opciones de montaje (esta última emite un TRIM por cada borrado y puede penalizar el rendimiento).
Comparativa HDD frente a SSD
| Característica | HDD 7.200 RPM | SSD SATA | SSD NVMe |
|---|---|---|---|
| Latencia de lectura | 12,7 ms | 150 µs | 50 µs |
| IOPS aleatorias 4K | ~120 | ~90.000 | ~600.000 |
| Ancho de banda secuencial | 150 MB/s | 550 MB/s | 3.500 MB/s |
| Aleatorio frente a secuencial | 168× peor | 1,2× peor | ~1× igual |
| Consumo | 6-10 W | 2-3 W | 5-8 W |
| Coste por GB | 0,02 € | 0,06 € | 0,08 € |
| Modo de fallo | Progresivo, con avisos | Súbito al agotar ciclos | Súbito |
La fila más importante es la cuarta: en un SSD, el acceso aleatorio cuesta prácticamente lo mismo que el secuencial. Esa única diferencia invalida décadas de optimizaciones diseñadas para discos mecánicos, incluidos casi todos los algoritmos de planificación que veremos a continuación.
NVMe y por qué cambia las reglas
Los primeros SSD se conectaban por SATA con el protocolo AHCI, diseñado en 2004 para discos mecánicos. Sus supuestos ya no valían:
| AHCI (SATA) | NVMe | |
|---|---|---|
| Colas de comandos | 1 | 65.535 |
| Comandos por cola | 32 | 65.536 |
| Interfaz física | SATA 6 Gb/s | PCIe (4 GB/s por carril ×4) |
| Instrucciones por E/S | ~4 registros MMIO | 2 |
| Interrupciones | Una línea compartida | MSI-X, una por cola y núcleo |
| Latencia del protocolo | ~6 µs | ~2,8 µs |
La diferencia estructural es la paralelización. Con AHCI, una única cola significa que todos los núcleos compiten por ella con un cerrojo compartido. NVMe da una cola por núcleo, eliminando la contención por completo: cada CPU envía sus peticiones a su propia cola sin sincronizarse con nadie.
Y aquí conecta con lo que sabemos: un SSD tiene 4-8 canales internos trabajando en paralelo. Para saturarlo hacen falta muchas peticiones simultáneas en vuelo. Con una sola cola de 32 comandos es imposible; con 65.535 colas, trivial.
$ lsblk -d -o NAME,ROTA,SIZE,MODEL NAME ROTA SIZE MODEL nvme0n1 0 931,5G Samsung SSD 980 PRO 1TB sda 1 7,3T ST8000NM0055-1RM112
La columna ROTA (rotacional) es la que hay que mirar: 1 es un disco mecánico, 0 un SSD. El núcleo la usa para decidir la lectura anticipada, el planificador por defecto y otras políticas. Comprobarla es siempre el primer paso al diagnosticar rendimiento de disco.
LBA y la abstracción del dispositivo de bloques
Todo lo anterior —cilindros, cabezales, canales NAND, FTL— está oculto. El sistema operativo ve una abstracción uniforme: el dispositivo de bloques.
Ese numerado es el LBA (Logical Block Addressing). Antes de 1990 se usaba direccionamiento CHS (cilindro-cabezal-sector), que exponía la geometría física y limitaba la capacidad a 8 GB. LBA lo sustituyó por un número secuencial y el firmware del disco hace la traducción.
$ sudo blockdev --getsize64 /dev/nvme0n1 1000204886016 $ sudo blockdev --getbsz /dev/nvme0n1 4096 $ cat /sys/block/nvme0n1/queue/logical_block_size 512 $ cat /sys/block/nvme0n1/queue/physical_block_size 512
La abstracción da al sistema operativo exactamente cuatro operaciones:
| Operación | Qué hace |
|---|---|
read(lba, n) |
Lee n bloques desde el LBA indicado |
write(lba, n, datos) |
Escribe n bloques |
flush() |
Fuerza el volcado de la caché interna del dispositivo |
discard(lba, n) |
TRIM: estos bloques ya no contienen datos útiles |
Esta uniformidad es lo que permite que el mismo código del núcleo funcione sobre un disquete, un SSD NVMe, un volumen RAID o un disco de red. Es la misma idea de máquina extendida que vimos en 01-01, aplicada al almacenamiento. La operación flush() es especialmente importante y volverá en Asignación de Espacio, Journaling e Integridad, porque un fsync() que no llegue hasta el plato físico no garantiza nada.
Planificación de peticiones de disco
Con un disco mecánico, el orden en que se sirven las peticiones determina cuánto se mueve el brazo, y ya sabemos que ahí está el 99,8 % del coste. Es un problema de planificación análogo al de la CPU, pero con una métrica distinta: el desplazamiento total del cabezal.
Trabajaremos todos los algoritmos sobre la misma cola:
Cola de peticiones (cilindros): 98, 183, 37, 122, 14, 124, 65, 67 Posición inicial del cabezal: 53 Rango del disco: 0 a 199
FCFS
Se sirven en el orden de llegada.
| Movimiento | Distancia |
|---|---|
| 53 → 98 | 45 |
| 98 → 183 | 85 |
| 183 → 37 | 146 |
| 37 → 122 | 85 |
| 122 → 14 | 108 |
| 14 → 124 | 110 |
| 124 → 65 | 59 |
| 65 → 67 | 2 |
| Total | 640 |
El brazo cruza el disco de un extremo a otro varias veces. Es justo y simple, pero pésimo.
SSTF (el más cercano primero)
Se elige siempre la petición más próxima a la posición actual.
| Movimiento | Distancia |
|---|---|
| 53 → 65 | 12 |
| 65 → 67 | 2 |
| 67 → 37 | 30 |
| 37 → 14 | 23 |
| 14 → 98 | 84 |
| 98 → 122 | 24 |
| 122 → 124 | 2 |
| 124 → 183 | 59 |
| Total | 236 |
Una reducción del 63 % frente a FCFS. Pero SSTF es el equivalente en disco de SJF, y comparte su defecto: inanición. Si llegan continuamente peticiones cerca del cilindro 60, la del cilindro 183 puede no servirse nunca.
SCAN (el algoritmo del ascensor)
El cabezal se mueve en una dirección sirviendo todo lo que encuentra, llega al extremo y vuelve. Como un ascensor.
Supongamos que se mueve hacia cilindros menores:
| Movimiento | Distancia |
|---|---|
| 53 → 0 | 53 |
| 0 → 183 | 183 |
| Total | 236 |
Mismo total que SSTF aquí, pero sin inanición: toda petición se sirve como mucho en dos recorridos completos. Esa garantía es lo que lo hace utilizable.
Su defecto: las peticiones justo detrás del cabezal esperan un recorrido entero, mientras que las de justo delante se sirven de inmediato. El tiempo de espera no es uniforme.
C-SCAN (SCAN circular)
Solo sirve peticiones en una dirección; al llegar al extremo, vuelve al principio sin servir nada en el retorno.
| Movimiento | Distancia |
|---|---|
| 53 → 199 | 146 |
| 199 → 0 (retorno rápido) | 199 |
| 0 → 37 | 37 |
| Total | 382 |
Recorre más, pero a cambio ofrece un tiempo de espera mucho más uniforme: el disco se comporta como una lista circular y ninguna zona está sistemáticamente favorecida. Es el compromiso que suelen preferir los sistemas donde la previsibilidad importa más que el rendimiento medio.
LOOK y C-LOOK
Optimización obvia de SCAN y C-SCAN: no ir hasta el extremo físico si no hay peticiones allí.
LOOK:
| Movimiento | Distancia |
|---|---|
| 53 → 14 | 39 |
| 14 → 183 | 169 |
| Total | 208 |
C-LOOK:
| Movimiento | Distancia |
|---|---|
| 53 → 183 | 130 |
| 183 → 14 (retorno) | 169 |
| 14 → 37 | 23 |
| Total | 322 |
Comparación completa
| Algoritmo | Desplazamiento | Frente a FCFS | Inanición | Espera uniforme |
|---|---|---|---|---|
| FCFS | 640 | — | No | Sí |
| SSTF | 236 | −63 % | Sí | No |
| SCAN | 236 | −63 % | No | No |
| C-SCAN | 382 | −40 % | No | Sí |
| LOOK | 208 | −67,5 % | No | No |
| C-LOOK | 322 | −50 % | No | Sí |
LOOK gana en desplazamiento total y es el que históricamente han usado los sistemas UNIX. C-SCAN y C-LOOK son preferibles cuando la varianza de la latencia importa más que la media.
Y ahora la observación que hay que tener siempre presente: todo este apartado presupone un cabezal que se mueve. En un SSD, la "distancia" entre el LBA 14 y el 183 es cero: ambos accesos cuestan lo mismo. Reordenar peticiones para un SSD no solo no ayuda, sino que añade latencia y consume CPU sin beneficio alguno. Es exactamente lo que motivó el planificador none de Linux.
Los planificadores reales de Linux
Linux permite elegir el planificador de E/S por dispositivo:
$ cat /sys/block/nvme0n1/queue/scheduler [none] mq-deadline kyber bfq $ cat /sys/block/sda/queue/scheduler none [mq-deadline] kyber bfq
Los corchetes indican el activo. Fíjate en la decisión que ha tomado el núcleo por sí solo: none para el NVMe, mq-deadline para el disco mecánico.
| Planificador | Estrategia | Adecuado para | Sobrecoste |
|---|---|---|---|
none (noop) |
FIFO, sin reordenar | NVMe, SSD rápidos | Mínimo |
mq-deadline |
Ordena por LBA con plazos máximos | HDD, SSD SATA | Bajo |
kyber |
Limita las colas según latencia objetivo | NVMe multi-cola con carga mixta | Bajo |
bfq |
Reparto justo por proceso, con pesos | Escritorio, cargas interactivas | Alto |
none no hace nada: pasa las peticiones al dispositivo en el orden de llegada. Suena a rendición, pero es la opción correcta para NVMe: el dispositivo tiene sus propias colas paralelas y su propio planificador interno, y sabe más que el núcleo sobre su geometría. Cualquier reordenación del sistema operativo sería una suposición equivocada.
mq-deadline mantiene dos colas ordenadas por LBA (una de lectura, otra de escritura) más dos colas FIFO por plazo. Sirve en orden de LBA —lo que da un comportamiento tipo LOOK— salvo cuando una petición está a punto de agotar su plazo, momento en el que salta a servirla. Los plazos por defecto son reveladores:
$ cat /sys/block/sda/queue/iosched/read_expire 500 $ cat /sys/block/sda/queue/iosched/write_expire 5000
500 ms para lecturas y 5.000 ms para escrituras. Las lecturas tienen diez veces más prioridad, y la razón es sólida: una lectura es casi siempre síncrona (hay un proceso bloqueado esperándola, en estado D), mientras que una escritura suele ser asíncrona (el proceso ya continuó, y el núcleo la volcará cuando pueda). Retrasar una lectura bloquea a alguien; retrasar una escritura no.
bfq (Budget Fair Queueing) da a cada proceso un presupuesto de sectores y reparte el ancho de banda de forma justa, con pesos configurables mediante ionice. Es lo que permitía la solución del backup en la lección 02-02:
Clase de ionice |
Nombre | Comportamiento |
|---|---|---|
| 1 | Tiempo real | Acceso prioritario garantizado |
| 2 | Mejor esfuerzo | Prioridad 0-7, por defecto 4 |
| 3 | Idle | Solo cuando nadie más pide disco |
Cambiar el planificador es inmediato y no requiere reiniciar:
$ echo bfq | sudo tee /sys/block/sda/queue/scheduler $ cat /sys/block/sda/queue/scheduler none mq-deadline kyber [bfq]
Para hacerlo persistente se usa una regla de udev, mecanismo que veremos en la próxima lección.
Regla práctica de elección:
| Dispositivo y carga | Elección |
|---|---|
| NVMe, servidor | none |
| SSD SATA, servidor | mq-deadline |
| HDD, servidor | mq-deadline |
| Cualquiera, escritorio | bfq |
| NVMe con cargas de latencia mixta | kyber |
RAID: combinar discos para capacidad, velocidad o fiabilidad
Un disco falla. La probabilidad anual de fallo de un disco de servidor ronda el 1-2 %, lo que parece poco hasta que tienes 100 discos: entonces esperas uno o dos fallos al año con certeza práctica.
RAID (Redundant Array of Independent Disks) combina varios discos en un volumen lógico. Los niveles se distinguen por cómo reparten datos y redundancia.
RAID 0 (división, striping)
Los datos se reparten en franjas entre todos los discos. Sin redundancia.
- Capacidad: 100 % de la suma.
- Rendimiento: multiplica por N en lectura y escritura.
- Tolerancia a fallos: ninguna. Si falla un disco, se pierde todo el volumen.
Y la trampa estadística: RAID 0 es menos fiable que un disco solo. Con 4 discos al 2 % de fallo anual:
P(que sobrevivan los 4) = 0,98^4 = 0,922 P(fallo del volumen) = 7,8 % anual, frente al 2 % de un disco suelto
Multiplicas el riesgo por cuatro. Solo tiene sentido para datos reproducibles: cachés, ficheros temporales, resultados intermedios.
RAID 1 (espejo)
Cada dato se escribe idéntico en todos los discos.
- Capacidad: 50 % con dos discos.
- Lectura: se puede repartir entre ambos, hasta 2× más rápida.
- Escritura: la de un disco (hay que escribir en los dos).
- Tolera el fallo de un disco sin perder nada ni degradar apenas.
RAID 5 (paridad distribuida)
Los datos se dividen entre N discos y se añade un bloque de paridad calculado con XOR, rotando qué disco lo guarda.
Disco A: [D0] [D3] [P2] [D8] Disco B: [D1] [P1] [D6] [D9] Disco C: [P0] [D4] [D7] [P3] Disco D: [D2] [D5] [P?] [D10] P0 = D0 XOR D1 XOR D2
La magia del XOR: si se pierde D1, se recupera como D1 = D0 XOR D2 XOR P0. La misma operación sirve para calcular y para reconstruir.
- Capacidad: (N−1)/N. Con 4 discos, el 75 %.
- Tolera un fallo.
- Penalización de escritura: modificar un bloque exige leer el dato antiguo, leer la paridad antigua, calcular la nueva y escribir dos bloques. Cuatro operaciones de E/S por escritura.
El riesgo serio de RAID 5 con discos grandes es la reconstrucción. Al sustituir un disco de 8 TB hay que leer los otros tres enteros:
Casi dos días con el array degradado y sin redundancia, sometiendo a los discos supervivientes —de la misma edad y el mismo lote— a una carga intensa de lectura. Es exactamente cuando más probable es un segundo fallo, y un segundo fallo en RAID 5 significa pérdida total. Por eso RAID 5 está desaconsejado con discos de más de 2 TB.
RAID 6 (doble paridad)
Como RAID 5 pero con dos bloques de paridad independientes.
- Capacidad: (N−2)/N. Con 6 discos, el 66,7 %.
- Tolera dos fallos simultáneos.
- Penalización de escritura: seis operaciones por escritura.
Es la respuesta al problema de reconstrucción de RAID 5: durante las 44 horas de reconstrucción todavía queda un nivel de redundancia.
RAID 10 (espejo + división)
Espejos de dos discos, unidos por división.
- Capacidad: 50 %.
- Sin penalización de paridad: dos operaciones por escritura.
- Tolera un fallo por espejo; con suerte, hasta la mitad de los discos.
- Reconstrucción rapidísima: solo hay que copiar el disco espejo, no leer todo el array.
Con discos de 8 TB, reconstruir es copiar 8 TB: unas 15 horas, y sin poner en riesgo al resto del array.
Tabla comparativa
Con 4 discos de 8 TB cada uno:
| Nivel | Capacidad útil | Fallos tolerados | E/S por escritura | Lectura | Reconstrucción |
|---|---|---|---|---|---|
| RAID 0 | 32 TB (100 %) | 0 | 1 | 4× | Imposible |
| RAID 1 (2+2) | 16 TB (50 %) | 1 por espejo | 2 | 4× | Copia: rápida |
| RAID 5 | 24 TB (75 %) | 1 | 4 | 3× | Lenta y arriesgada |
| RAID 6 | 16 TB (50 %) | 2 | 6 | 2× | Lenta pero segura |
| RAID 10 | 16 TB (50 %) | 1-2 | 2 | 4× | Copia: rápida |
Y la advertencia imprescindible:
RAID no es una copia de seguridad. Protege del fallo de hardware, y de nada más. No te salva de un
rm -rfaccidental, de ransomware, de un fallo del sistema de archivos, de un error del controlador RAID ni de un incendio. Una copia de seguridad es una copia separada en el tiempo y en el espacio.
La decisión de Meteora para /var/lib/meteora
Apliquemos todo a un caso concreto. Requisitos:
| Requisito | Valor |
|---|---|
| Volumen de datos | 17 MB/día = 6,2 GB/año |
| Retención | 10 años = 62 GB, más margen: 500 GB |
| Patrón de escritura | Secuencial, un fichero por día, append continuo |
| Patrón de lectura | Secuencial (agregador), aleatorio ligero (meteo-api) |
| Criticidad | Alta: las lecturas perdidas no se recuperan |
| Presupuesto | Moderado |
Análisis de opciones:
| Opción | Capacidad | Valoración |
|---|---|---|
| Un solo SSD | 1 TB | Descartada: un fallo pierde 10 años de datos |
| RAID 0 (2 SSD) | 2 TB | Descartada: duplica el riesgo sin necesitar la velocidad |
| RAID 5 (4 HDD 8 TB) | 24 TB | Descartada: 24 TB para 500 GB, y reconstrucción de 44 h |
| RAID 6 (6 discos) | — | Descartada: exceso de coste y de penalización de escritura |
| RAID 1 (2 SSD 1 TB) | 1 TB | Elegida |
Justificación de RAID 1 con dos SSD:
- El volumen es pequeño. 500 GB proyectados a 10 años caben de sobra en 1 TB. Optimizar capacidad no aporta nada aquí, y ese es precisamente el argumento de RAID 5 y 6.
- La escritura es continua y en
append. RAID 5 penaliza con 4 operaciones de E/S por escritura; RAID 1 solo con 2. Con elingestorescribiendo constantemente, esa diferencia importa más que la capacidad. - La reconstrucción es una simple copia. Sustituir un SSD implica copiar como mucho 500 GB, unas 15 minutos a 550 MB/s, sin exponer los datos como haría RAID 5.
- La lectura mejora:
agregadorymeteo-apipueden leer de ambos discos en paralelo. - Simplicidad. RAID 1 es el nivel más fácil de entender, montar y recuperar. En una emergencia a las tres de la madrugada, eso vale más que un 25 % de capacidad extra.
Configuración:
# Crear el array
$ sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 \
/dev/nvme0n1p2 /dev/nvme1n1p2
# Comprobar el estado
$ cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
976630464 blocks super 1.2 [2/2] [UU]
# Planificador: none, porque son NVMe
$ echo none | sudo tee /sys/block/nvme0n1/queue/scheduler
$ echo none | sudo tee /sys/block/nvme1n1/queue/schedulerLa línea [2/2] [UU] es la que hay que vigilar: dos discos de dos activos, ambos U (up). Si viera [2/1] [U_], el array estaría degradado y habría que sustituir un disco con urgencia.
Y la parte que RAID no cubre: una copia diaria a otro servidor, en otra ubicación física. RAID 1 protege del fallo de un SSD; solo la copia protege de un rm accidental o de un incendio en el rack.
Medición con lsblk e iostat -x
$ lsblk -o NAME,ROTA,SIZE,TYPE,MOUNTPOINT,SCHED NAME ROTA SIZE TYPE MOUNTPOINT SCHED nvme0n1 0 931,5G disk none ├─nvme0n1p1 0 512M part /boot/efi none └─nvme0n1p2 0 931G part none └─md0 0 931G raid1 /var/lib/meteora nvme1n1 0 931,5G disk none └─nvme1n1p2 0 931G part none └─md0 0 931G raid1 /var/lib/meteora sda 1 7,3T disk mq-deadline └─sda1 1 7,3T part /backup mq-deadline
De un vistazo tienes la topología completa: dos NVMe formando md0 montado en /var/lib/meteora, un disco mecánico de 7,3 TB para /backup, y el planificador correcto en cada uno.
iostat -x es la herramienta de diagnóstico principal:
$ iostat -x 2 2 Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s r_await w_await aqu-sz %util nvme0n1 142,50 388,00 4104,00 9820,00 0,00 12,50 0,08 0,12 0,04 3,20 nvme1n1 138,00 388,00 4020,00 9820,00 0,00 12,50 0,09 0,12 0,04 3,15 md0 280,50 388,00 8124,00 9820,00 0,00 0,00 0,00 0,00 0,00 0,00 sda 2,00 118,50 64,00 18204,00 0,00 84,00 11,20 28,40 3,44 92,10
Columna a columna, con lo que significa cada una:
| Columna | Qué mide | Cuándo preocupa |
|---|---|---|
r/s, w/s |
Operaciones por segundo (IOPS) | Comparar con el máximo del dispositivo |
rkB/s, wkB/s |
Ancho de banda | Comparar con el máximo |
rrqm/s, wrqm/s |
Peticiones fusionadas por el núcleo | Alto = acceso secuencial (bueno) |
r_await, w_await |
Latencia media en ms, incluida la cola | La métrica clave |
aqu-sz |
Longitud media de la cola | > 1 sostenido = saturación |
%util |
% de tiempo con al menos una petición en curso | Engañosa en NVMe |
Lectura de estos datos concretos:
nvme0n1ynvme1n1tienen cifras casi idénticas, como debe ser en RAID 1: mismas escrituras en ambos, lecturas repartidas.md0suma las lecturas (280,5 = 142,5 + 138) pero no duplica las escrituras (388), que es exactamente el comportamiento esperado del espejo.r_awaitde 0,08 ms en los NVMe. Excelente, dentro de lo esperable.sdaes el problema:w_awaitde 28,4 ms,aqu-szde 3,44 y%utildel 92,1 %. El disco de backup está saturado escribiendo 18 MB/s. Como es un disco mecánico con escritura intensiva, es su comportamiento normal, pero conviene que el backup no compita con nada crítico (de ahí elionice -c 3).wrqm/sde 84 ensda: el núcleo está fusionando muchas peticiones contiguas antes de enviarlas, señal de escritura secuencial. Es lo que se quiere en un disco mecánico.
Un aviso importante sobre %util: en discos mecánicos es fiable (solo pueden servir una petición a la vez, así que el 100 % significa saturación). En NVMe es engañosa: el dispositivo sirve decenas de peticiones en paralelo, así que puede marcar el 100 % estando al 5 % de su capacidad real. En SSD, la métrica de referencia es await, no %util.
$ iostat -x 1 | awk '/^(nvme|sd|md)/ {printf "%-8s await_r=%6.2f await_w=%6.2f cola=%5.2f\n", $1, $10, $11, $21}'Y para medir la capacidad real del dispositivo antes de poner nada en producción:
$ sudo fio --name=aleatorio4k --filename=/var/lib/meteora/prueba \
--rw=randread --bs=4k --iodepth=32 --numjobs=4 \
--size=1G --runtime=30 --group_reporting
read: IOPS=487k, BW=1903MiB/s (1995MB/s)
lat (usec): min=8, avg=64.21, max=1842487.000 IOPS aleatorias de 4 KB con 64 µs de latencia media. Compáralo con las ~120 IOPS de un disco mecánico: un factor de 4.000.
Errores Comunes y Consejos
Aplicar la intuición del disco mecánico al SSD. Desfragmentar un SSD no sirve de nada y consume ciclos de escritura. Reordenar peticiones tampoco: en flash no hay distancia. Lo primero al analizar rendimiento es mirar lsblk -o NAME,ROTA y saber con qué estás tratando.
Confiar en %util para SSD. Un NVMe al 100 % de %util puede estar completamente ocioso en términos reales. Usa await y aqu-sz.
Llenar un SSD al máximo. Por encima del 90 % de ocupación, la recolección de basura pierde eficacia y la amplificación de escritura se dispara de 2 a 10. Deja siempre un 10-20 % libre; muchos SSD de servidor lo reservan de fábrica (over-provisioning).
Usar RAID 5 con discos grandes. Con discos de 8 TB, una reconstrucción de 44 horas sin redundancia es un riesgo real de perderlo todo. Para discos de más de 2 TB, RAID 6 o RAID 10.
Confundir RAID con copia de seguridad. RAID protege del fallo de un disco. No protege de borrados accidentales, corrupción lógica, ransomware ni desastres físicos. Son problemas distintos con soluciones distintas.
Olvidar el TRIM. Sin fstrim.timer activo, un SSD acaba con el rendimiento de escritura degradado sin causa aparente. Compruébalo con systemctl status fstrim.timer.
Cambiar el planificador de E/S sin medir. El valor por defecto que elige el núcleo suele ser correcto. Si vas a cambiarlo, mide antes y después con fio o con la carga real; muchos cambios "de optimización" empeoran las cosas.
Consejo de diagnóstico: ante una sospecha de problema de disco, este es el orden que funciona: lsblk -o NAME,ROTA,SCHED (qué tienes), iostat -x 2 (mirar await y aqu-sz), iotop -o (qué proceso está haciendo E/S) y cat /proc/mdstat si hay RAID (¿está degradado?). Y recuerda mirar también la columna b de vmstat: si hay procesos en estado D, ya sabes de la lección 02-01 que están atascados esperando exactamente esto.
Ejercicios
Ejercicio 1: calcular tiempos de acceso a disco
meteo-01 tiene un disco de backup con estas características:
- Calcula el tiempo de leer un bloque de 4 KB aleatorio.
- Calcula el tiempo de leer los 17 MB de
2026-08-31.datde forma secuencial. - Calcula el tiempo de leer esos mismos 17 MB en bloques de 4 KB dispersos por el disco.
- ¿Cuántas IOPS aleatorias de 4 KB ofrece este disco? Compáralo con los 487.000 del NVMe.
- Si el
agregadortarda 90 segundos en procesar el día leyendo el fichero secuencialmente, ¿qué proporción del tiempo es CPU y qué proporción es disco?
Ejercicio 2: planificación de peticiones de disco
Un disco de 0 a 4.999 cilindros tiene el cabezal en el 2.150 y esta cola de peticiones:
- Calcula el desplazamiento total del cabezal con FCFS, SSTF, SCAN (hacia arriba), C-SCAN (hacia arriba), LOOK (hacia arriba) y C-LOOK (hacia arriba).
- Ordénalos de mejor a peor.
- ¿Cuál elegirías si el requisito fuera que ninguna petición espere más de 2 recorridos completos? ¿Y si fuera minimizar el tiempo total?
- Si este dispositivo fuera un SSD NVMe, ¿cuál sería tu respuesta y por qué?
Ejercicio 3: decidir una configuración RAID
Meteora quiere ampliar el almacenamiento. Tienes 6 discos de 4 TB y estos requisitos:
- Datos de lecturas (
/var/lib/meteora): 500 GB, críticos, escritura secuencial continua, lectura intensiva. - Registros y temporales (
/var/log,/tmp): 200 GB, reproducibles, escritura intensiva. - Archivo histórico (
/archivo): 8 TB, se escribe una vez y se lee raramente, importante pero no crítico.
- Propón una configuración RAID para cada uno de los tres usos, indicando cuántos discos asignas.
- Calcula la capacidad útil de cada volumen.
- Justifica cada elección con los criterios de la lección.
- Calcula el tiempo de reconstrucción de cada volumen si falla un disco (asume 180 MB/s).
- ¿Qué queda sin cubrir por RAID y qué harías al respecto?
Soluciones
Solución 1
1. Bloque de 4 KB aleatorio.
Tiempo de búsqueda: 9,000 ms
Latencia rotacional: (60.000 ms/min ÷ 7.200 RPM) ÷ 2 = 8,33 ÷ 2 = 4,167 ms
Transferencia: 4 KB ÷ 160 MB/s = 0,0244 ms
─────────
Total: 13,191 msReparto del tiempo:
2. Los 17 MB secuencialmente.
Búsqueda inicial: 9,000 ms
Latencia rotacional: 4,167 ms
Transferencia: 17 MB ÷ 160 MB/s = 106,25 ms
─────────
Total: 119,42 msEn la práctica un fichero de 17 MB no está perfectamente contiguo, así que habría alguna búsqueda adicional, pero el orden de magnitud es correcto: unos 120 ms.
3. Los mismos 17 MB en bloques dispersos.
Número de bloques: 17.000.000 ÷ 4.096 = 4.150 bloques Tiempo: 4.150 × 13,191 ms = 54.743 ms = 54,7 segundos
| Patrón | Tiempo | MB/s efectivos | Factor |
|---|---|---|---|
| Secuencial | 0,119 s | 143 MB/s | 1× |
| Aleatorio | 54,7 s | 0,31 MB/s | 459× peor |
El mismo dato, 459 veces más lento. Es la diferencia entre que el agregador termine antes de tomar un café o tarde casi un minuto solo en leer.
4. IOPS aleatorias.
Comparación:
| Dispositivo | IOPS 4K aleatorias | Factor |
|---|---|---|
| HDD 7.200 RPM | 76 | 1× |
| SSD SATA | ~90.000 | 1.184× |
| SSD NVMe | 487.000 | 6.408× |
Ese factor de 6.408 es una de las cifras más importantes de la informática de la última década. Explica por qué bases de datos que eran inviables pasaron a ser triviales, y por qué muchas optimizaciones de software diseñadas para minimizar E/S aleatoria dejaron de tener sentido.
Una lectura complementaria del dato: 76 IOPS significa que ese disco no puede servir ni 76 peticiones aleatorias por segundo. Si meteo-api recibe 40 peticiones/segundo y cada una provoca 2 lecturas aleatorias, ese disco ya está al límite.
5. Reparto CPU/disco en los 90 segundos.
Tiempo de disco (lectura secuencial): 0,119 s Tiempo total: 90,000 s Proporción de disco: 0,119 / 90 = 0,13 % Proporción de CPU: 99,87 %
El agregador está limitado por CPU, no por disco. Esto confirma cuantitativamente lo que dedujimos en 02-02 a partir de sus cambios de contexto (ratio de 63 a 1 entre voluntarios e involuntarios, muy inferior al de los otros procesos).
La consecuencia práctica es importante: cambiar el disco de backup por un NVMe no aceleraría el agregador en absoluto. Ahorrarías 0,1 segundos de 90. Para acelerarlo hay que optimizar el cálculo, paralelizarlo o darle más CPU. Es el tipo de conclusión que evita gastar dinero en el componente equivocado, y por eso se mide antes de comprar.
Nota: este cálculo cambiaría por completo si el agregador leyera de forma aleatoria. En ese caso serían 54,7 s de disco frente a 90 s totales, un 61 % de disco, y la conclusión se invertiría.
Solución 2
Cola: 2069, 1212, 2296, 2800, 544, 1618, 356, 1523, 4965, 3681. Cabezal en 2150. Disco de 0 a 4999.
Ordenadas: 356, 544, 1212, 1523, 1618, 2069, | 2150 | , 2296, 2800, 3681, 4965
FCFS:
| Movimiento | Distancia |
|---|---|
| 2150 → 2069 | 81 |
| 2069 → 1212 | 857 |
| 1212 → 2296 | 1084 |
| 2296 → 2800 | 504 |
| 2800 → 544 | 2256 |
| 544 → 1618 | 1074 |
| 1618 → 356 | 1262 |
| 356 → 1523 | 1167 |
| 1523 → 4965 | 3442 |
| 4965 → 3681 | 1284 |
| Total | 13.011 |
SSTF:
| Paso | Desde | Más cercana | Distancia |
|---|---|---|---|
| 1 | 2150 | 2069 (81) frente a 2296 (146) | 81 |
| 2 | 2069 | 2296 (227) frente a 1618 (451) | 227 |
| 3 | 2296 | 2800 (504) frente a 1618 (678) | 504 |
| 4 | 2800 | 3681 (881) frente a 1618 (1182) | 881 |
| 5 | 3681 | 4965 (1284) frente a 1618 (2063) | 1284 |
| 6 | 4965 | 1618 | 3347 |
| 7 | 1618 | 1523 | 95 |
| 8 | 1523 | 1212 | 311 |
| 9 | 1212 | 544 | 668 |
| 10 | 544 | 356 | 188 |
| Total | 7.586 |
SCAN (hacia arriba, hasta 4999):
| Tramo | Distancia |
|---|---|
| 2150 → 4999 | 2849 |
| 4999 → 356 | 4643 |
| Total | 7.492 |
C-SCAN (hacia arriba, salto de 4999 a 0):
| Tramo | Distancia |
|---|---|
| 2150 → 4999 | 2849 |
| 4999 → 0 (retorno) | 4999 |
| 0 → 2069 | 2069 |
| Total | 9.917 |
LOOK (hacia arriba, sin llegar al extremo):
| Tramo | Distancia |
|---|---|
| 2150 → 4965 | 2815 |
| 4965 → 356 | 4609 |
| Total | 7.424 |
C-LOOK:
| Tramo | Distancia |
|---|---|
| 2150 → 4965 | 2815 |
| 4965 → 356 (retorno) | 4609 |
| 356 → 2069 | 1713 |
| Total | 9.137 |
2. Ranking:
| Puesto | Algoritmo | Desplazamiento | Frente a FCFS |
|---|---|---|---|
| 1 | LOOK | 7.424 | −43 % |
| 2 | SCAN | 7.492 | −42 % |
| 3 | SSTF | 7.586 | −42 % |
| 4 | C-LOOK | 9.137 | −30 % |
| 5 | C-SCAN | 9.917 | −24 % |
| 6 | FCFS | 13.011 | — |
3. Elección según el requisito.
Si ninguna petición debe esperar más de dos recorridos completos: SCAN, C-SCAN, LOOK o C-LOOK, todos válidos. Lo determinante es descartar SSTF, que no ofrece esa garantía: si llegaran continuamente peticiones cerca del 2150, la del 4965 podría no servirse nunca. Que en este caso concreto SSTF dé buen resultado no cambia nada; la garantía es sobre el peor caso, no sobre un ejemplo. Entre los cuatro válidos, C-LOOK es la mejor opción si además se quiere que la espera sea uniforme, porque no favorece sistemáticamente ninguna zona del disco.
Si el objetivo es minimizar el tiempo total: LOOK, con 7.424 cilindros. Gana porque no desperdicia movimiento yendo a extremos vacíos (34 cilindros de más en SCAN) ni haciendo el retorno improductivo de las variantes circulares.
Nota metodológica: la diferencia entre LOOK (7.424) y SSTF (7.586) es solo del 2,1 %. Con otra cola SSTF podría ganar. La ventaja sólida de LOOK no es el 2 %, sino la garantía de no inanición al mismo precio.
4. Si fuera un SSD NVMe: none, y ninguno de estos algoritmos.
El razonamiento completo:
- La métrica pierde el sentido. "Desplazamiento total del cabezal" mide movimiento físico de un brazo. En flash no hay brazo. Acceder al LBA 356 y al 4965 cuesta exactamente lo mismo: unos 50 µs.
- Reordenar es contraproducente. Ordenar peticiones consume CPU y añade latencia en la cola del núcleo, a cambio de un beneficio que es cero. Estás pagando para no obtener nada.
- El dispositivo sabe más. El SSD tiene su propia FTL, sus 4-8 canales paralelos y su propio planificador interno, que conoce la ubicación física real —invisible para el núcleo por el nivelado de desgaste—. Cualquier orden que imponga el sistema operativo se basa en una geometría que no existe.
- NVMe quiere paralelismo, no orden. Con 65.535 colas, lo óptimo es enviar las 10 peticiones a la vez y dejar que el dispositivo las sirva en paralelo por sus distintos canales. Serializarlas en un orden "óptimo" destruye precisamente la ventaja del NVMe.
Estimación del resultado: las 10 peticiones, enviadas en paralelo con una latencia de ~50 µs cada una y suficiente paralelismo interno, se completarían en aproximadamente 50-100 µs en total. Con el disco mecánico y LOOK, 7.424 cilindros de desplazamiento suponen del orden de 150-200 ms. Un factor de unas 2.000 veces, obtenido no por planificar mejor sino por dejar de planificar.
Solución 3
1 y 2. Configuración propuesta.
| Uso | Discos | Nivel RAID | Capacidad útil | Necesita |
|---|---|---|---|---|
/var/lib/meteora |
2 × 4 TB | RAID 1 | 4 TB | 500 GB |
/var/log, /tmp |
(compartido con el anterior) | — | — | 200 GB |
/archivo |
4 × 4 TB | RAID 5 | 12 TB | 8 TB |
Detalle de los cálculos:
RAID 1 con 2 discos: 4 TB × 1 = 4 TB útiles (50 % de 8 TB) RAID 5 con 4 discos: 4 TB × (4−1) = 12 TB útiles (75 % de 16 TB) Total útil: 16 TB de 24 TB brutos (66,7 %)
Los datos críticos (500 GB) y los reproducibles (200 GB) caben juntos en el RAID 1 de 4 TB con margen de sobra, en subvolúmenes o particiones lógicas distintas. Dedicar discos aparte a /var/log sería desperdiciar dos discos de 4 TB para 200 GB.
3. Justificación de cada elección.
/var/lib/meteora en RAID 1:
- Criticidad máxima. Las lecturas perdidas son irrecuperables, así que la redundancia es innegociable.
- Escritura secuencial continua. RAID 1 cuesta 2 operaciones de E/S por escritura; RAID 5 cuesta 4 (leer dato, leer paridad, escribir dato, escribir paridad). Con el
ingestorescribiendo sin parar, esa diferencia se paga cada segundo. - Lectura intensiva. RAID 1 permite servir lecturas desde ambos discos en paralelo, lo que beneficia directamente al
agregadory ameteo-api. - La capacidad sobra. 500 GB de necesidad frente a 4 TB disponibles: no hay ningún argumento para sacrificar rendimiento o simplicidad a cambio de más espacio.
/var/log y /tmp en el mismo RAID 1:
- Son reproducibles, así que técnicamente RAID 0 bastaría. Pero dedicarles discos propios sería malgastar 8 TB brutos para 200 GB.
- Convivir con los datos críticos les da redundancia gratis, lo cual es un extra bienvenido: perder los registros justo cuando estás diagnosticando un fallo de disco es exactamente el peor momento posible.
- Precaución necesaria:
/var/logcreciendo sin control podría llenar el volumen y bloquear la escritura de lecturas. Hay que ponerle límite conlogrotateyjournald(SystemMaxUse=), o aislarlo en un subvolumen con cuota.
/archivo en RAID 5:
- Aquí sí manda la capacidad: 8 TB necesarios de 12 TB útiles. RAID 10 con los mismos 4 discos daría solo 8 TB, justo al límite y sin margen de crecimiento.
- Se escribe una vez y se lee raramente. La penalización de escritura de RAID 5 es irrelevante en una carga que casi no escribe: es precisamente el escenario para el que RAID 5 fue diseñado.
- Es importante pero no crítico: si se perdiera, sería recuperable desde los backups y desde el reproceso de los datos originales.
- Los discos son de 4 TB, no de 8, lo que sitúa la reconstrucción en un rango aceptable, como veremos en el punto siguiente.
4. Tiempos de reconstrucción a 180 MB/s.
RAID 1 (4 TB):
Y con solo 700 GB de datos reales, muchas implementaciones (mdadm con bitmap, o ZFS/btrfs) copian únicamente los bloques usados:
Durante la reconstrucción, el disco superviviente sigue sirviendo peticiones normalmente.
RAID 5 (4 discos de 4 TB):
Hay que leer los 3 discos supervivientes enteros: 3 × 4 TB = 12 TB Tiempo = 12.000.000 MB / 180 MB/s = 66.667 s = 18,5 horas
Comparación y riesgo:
| Volumen | Reconstrucción | Redundancia durante ella | Riesgo |
|---|---|---|---|
| RAID 1 | 1,1 - 6,2 h | Ninguna (queda 1 disco) | Bajo: ventana corta |
| RAID 5 | 18,5 h | Ninguna (tolera 0 fallos más) | Moderado: ventana larga con 3 discos bajo carga intensa |
Las 18,5 horas de RAID 5 son aceptables —muy lejos de las 44 horas del caso de 8 TB que veíamos en la lección— pero merecen dos precauciones concretas:
# 1. Limitar la velocidad de reconstrucción para no saturar el array $ echo 100000 | sudo tee /proc/sys/dev/raid/speed_limit_min # 2. Comprobación semanal de integridad para detectar sectores # ilegibles ANTES de que hagan falta en una reconstrucción $ sudo systemctl enable --now mdcheck_start.timer # 3. Vigilancia SMART para anticipar fallos $ sudo smartctl -a /dev/sda | grep -E 'Reallocated|Pending|Uncorrectable'
La comprobación periódica es la más importante de las tres: el escenario que mata a RAID 5 es descubrir un sector ilegible en el disco B justo durante la reconstrucción del disco A. Leer todo el array cada semana detecta esos sectores mientras aún hay redundancia para repararlos.
5. Lo que RAID no cubre.
RAID protege exclusivamente del fallo físico de un disco. Queda fuera:
| Amenaza | ¿RAID protege? | Qué hace falta |
|---|---|---|
| Fallo de un disco | Sí | RAID 1 / 5 |
rm -rf accidental |
No | Copia con historial |
| Ransomware | No | Copia inmutable o desconectada |
| Corrupción del sistema de archivos | No | Copia + suma de verificación |
| Fallo del controlador RAID | No | Copia en otro sistema |
| Incendio, robo, inundación | No | Copia fuera de la ubicación |
Bug en el ingestor que escribe basura |
No | Copia con historial |
La regla de referencia es 3-2-1: tres copias de los datos, en dos medios distintos, con una fuera del emplazamiento.
Copia 1: RAID 1 en meteo-01 (producción) Copia 2: /archivo en el RAID 5, con instantáneas diarias (mismo edificio, otro volumen) Copia 3: sincronización nocturna a almacenamiento remoto (otra ubicación)
# Copia diaria incremental con historial y verificación
$ rsync -avz --link-dest=/backup/anterior \
/var/lib/meteora/lecturas/ backup@remoto:/backup/meteora/$(date +%F)/--link-dest crea enlaces duros hacia la copia anterior, de modo que cada día ocupa solo lo que ha cambiado pero se ve como una copia completa e independiente. Con 17 MB diarios, un año de historial diario ocupa unos 6,2 GB en lugar de 6,2 TB.
Y una última pieza que se olvida siempre: una copia de seguridad que no se ha restaurado nunca no es una copia de seguridad, es una esperanza. Hay que programar una restauración de prueba periódica y verificar que los datos recuperados son legibles y correctos.
Conclusión
El almacenamiento es el nivel de la jerarquía donde aparece el abismo: de la RAM al SSD hay un factor de 500, y al disco mecánico de 80.000. Todo el diseño del subsistema de E/S consiste en evitar cruzarlo.
Un disco mecánico gasta el 99,8 % del tiempo posicionándose —búsqueda más latencia rotacional— y solo el 0,2 % transfiriendo, lo que lo hace 168 veces más lento en acceso aleatorio que secuencial. De ahí salen la lectura anticipada, la agrupación de escrituras y toda la planificación de peticiones. Un SSD invierte las reglas: sin partes móviles, el acceso aleatorio cuesta lo mismo que el secuencial, pero introduce restricciones propias —no se puede sobrescribir sin borrar el bloque entero— que obligan a una FTL, a la recolección de basura, al nivelado de desgaste y a TRIM, y que hacen que un SSD casi lleno se comporte mucho peor que uno con espacio. NVMe no es solo un conector más rápido: sustituye una cola por 65.535 y elimina la contención entre núcleos.
Sobre esa física, el sistema operativo levanta la abstracción del dispositivo de bloques direccionado por LBA, con solo cuatro operaciones, que es lo que permite que el mismo código sirva para un disquete y para un array RAID. La planificación de peticiones —FCFS, SSTF, SCAN, C-SCAN, LOOK, C-LOOK— reduce el desplazamiento hasta un 67 %, pero solo tiene sentido si hay un cabezal que mover: en NVMe la elección correcta es none, es decir, no planificar. Los planificadores reales de Linux reflejan exactamente eso, y mq-deadline incorpora además una asimetría muy razonada: las lecturas tienen un plazo diez veces más corto que las escrituras, porque detrás de una lectura casi siempre hay un proceso bloqueado en estado D.
RAID combina discos para capacidad, velocidad o fiabilidad, y la elección depende del patrón: RAID 1 para datos críticos con escritura continua y volumen pequeño —el caso de /var/lib/meteora—, RAID 5 solo con discos moderados y escritura escasa, RAID 6 o 10 cuando la reconstrucción sería larga. Y la advertencia que nunca sobra: RAID no es una copia de seguridad. Finalmente, lsblk te dice qué tienes e iostat -x cómo se comporta, con await como métrica de referencia y %util como trampa en SSD.
Hasta aquí hemos tratado el disco como el dispositivo. Pero un servidor tiene tarjetas de red, terminales, relojes, sensores y controladores de todo tipo, y el sistema operativo tiene que ofrecer una interfaz coherente para todos ellos sin conocer los detalles de ninguno. Cómo lo consigue —la clasificación en dispositivos de bloque, carácter y red, el principio de que todo es un fichero, /dev y udev, y las tres formas que tiene la CPU de hablar con un dispositivo— es lo que veremos en Gestión de Dispositivos.
Fundamentos de Sistemas Operativos
Módulo 1: Introducción a los Sistemas Operativos
- Conceptos Básicos de Sistemas Operativos
- Historia y Evolución de los Sistemas Operativos
- Tipos de Sistemas Operativos
- Funciones Principales de un Sistema Operativo
- Arquitectura del Núcleo: Monolítico, Microkernel e Híbrido
- Modo Usuario, Modo Núcleo y Llamadas al Sistema
Módulo 2: Gestión de Recursos
- Gestión de Procesos
- Planificación de la CPU
- Gestión de Memoria
- Memoria Virtual y Paginación
- Gestión de Almacenamiento
- Gestión de Dispositivos
- Controladores, Interrupciones y Operaciones de E/S
Módulo 3: Concurrencia
- Conceptos de Concurrencia
- Hilos y Procesos
- Comunicación entre Procesos (IPC)
- Sincronización y Exclusión Mutua
- Problemas Clásicos de Concurrencia
- Interbloqueos: Prevención, Detección y Recuperación
Módulo 4: Estructuras de Archivos
- Sistemas de Archivos
- Estructuras de Directorios
- Particiones, Montaje y Sistema de Archivos Virtual
- Gestión de Archivos
- Asignación de Espacio, Journaling e Integridad
- Seguridad y Permisos de Archivos
Módulo 5: Protección y Seguridad del Sistema
- Principios de Protección y Control de Acceso
- Usuarios, Autenticación y Escalada de Privilegios
- Amenazas Comunes y Endurecimiento del Sistema
- Auditoría, Registros y Respuesta a Incidentes
Módulo 6: Virtualización y Contenedores
- Virtualización: Hipervisores y Máquinas Virtuales
- Contenedores: Namespaces y cgroups
- El Sistema Operativo en la Nube
- Sistemas Operativos Móviles y de Tiempo Real
