Skip to content

Caché del archivo en un nodo edge

Un nodo que sirve el archivo ajeno en lugar del propio — a través de remotes o de una fuente legacy — va a la fuente por absolutamente cada fragmento. La caché del archivo cambia esto: el fragmento leído se asienta en un disco de caché local, y la siguiente solicitud de la misma parte del archivo se sirve localmente, sin ida y vuelta por la red.

Así se construye un edge de CDN: el origin guarda el archivo, los edges guardan lo que los espectadores de verdad ven.

La caché es transparente. Cambia de dónde vienen los bytes, no lo que se sirve: las URL de los fragmentos, las playlists y las fronteras del archivo siguen exactamente iguales para el espectador.

Qué distingue a un disco de caché de un disco de archivo

Un disco de caché es un papel del disco, no una bandera en él:

  • la grabación en vivo nunca lo elige — el archivo se escribe solo en los discos listados en disks;
  • la retención del stream no lo gobiernamax_depth y max_bytes del stream no se aplican a la caché;
  • el espacio lo libera el desalojo — según cuánto hace que se accedió por última vez a un blob, no según la antigüedad de su contenido;
  • está aislado en el catálogo — los blobs de caché viven en sus propias tablas, y los recorridos del archivo (limpieza, backfill, el reparto del espacio ocupado en cubos) no los ven en absoluto.

Por eso la caché de un edge no aparece en la consola como un archivo huérfano, y por eso el desalojo de la caché no compite con la grabación del archivo por el mismo mutex.

Configuración

La caché se configura en dos sitios: los discos en el nodo, el interruptor en el stream.

dvr:
  root: /storage
  cache_disks:
  - path: ssd1              # relativo a root, como un disco de archivo
    max_bytes: 536870912000 # techo de la caché en este disco, bytes
    min_free_bytes: 10737418240
  - path: ssd2

streams:
  - name: cam1
    remotes:
    - url: http://origin:5080
    cache: {}               # activa el cacheo de las lecturas del archivo

Parámetros del disco de caché:

Parámetro Descripción
path ruta del disco relativa a root
max_bytes cuánto puede ocupar la caché en este disco; vacío — limitada solo por el espacio libre
min_free_bytes cuánto espacio libre dejar en el volumen

Los límites son independientes: el desalojo funciona hasta que el disco cumpla ambos. El disco de caché no tiene modeDegraded describe a un miembro del RAID del archivo, y la caché no replica nada.

La sección cache del stream es una sección de primer nivel del documento, hermana de dvr, no un campo dentro de esta: el cacheo y la grabación son propiedades independientes. Un edge cachea el archivo ajeno sin grabar el propio. La sección todavía no tiene campos — su mera presencia activa el cacheo.

La validación de la configuración rechaza:

  • una ruta listada a la vez en disks y en cache_disks;
  • un duplicado dentro de cache_disks;
  • un disco de caché cuya ruta sea igual a root — el desalojo borraría la casa del catálogo.

Rutas distintas en el mismo volumen físico son una configuración válida, pero al arrancar se registra un aviso: el desalojo libera espacio que el archivo ocupa de inmediato.

Una sección cache en un nodo sin discos de caché es un no-op válido con un aviso en el log. Es normal en un clúster, donde un mismo documento de stream se reparte entre nodos distintos.

Un edge puro

Un almacenamiento hecho de root y discos de caché solamente, sin discos de archivo, es una configuración válida: hay catálogo, no hay grabación en vivo, y el archivo se va trayendo de los remotes.

dvr:
  root: /storage
  cache_disks:
  - path: ssd1
    max_bytes: 536870912000

streams:
  - name: cam1
    remotes:
    - url: http://origin:5080
    cache: {}

Warning

root es la casa del catálogo, no un disco de escritura. Una lista disks vacía solía significar «escribir directamente en root»; ahora es un error de escritura visible en las estadísticas, en lugar de una escritura silenciosa por fuera del RAID. Si el nodo debe grabar un archivo, enumere los discos explícitamente en disks.

Admisión en la caché

Cachearlo todo desde la primera solicitud significa desalojar lo popular en favor de lo aleatorio: un solo salto hacia lo profundo del archivo echaría del disco lo que todo el mundo está viendo. Por eso la admisión tiene dos ejes, y se configuran en el nodo, para la caché entera:

Parámetro Descripción
cache_fresh_age_secs un fragmento más joven que esta profundidad (segundos hacia atrás desde ahora) se cachea en la primera solicitud; por defecto, un día
cache_admission_hits a partir de qué solicitud repetida empieza a cachearse un fragmento más antiguo que la frontera de frescura; por defecto, la segunda; 1 desactiva la barrera
dvr:
  root: /storage
  cache_fresh_age_secs: 86400
  cache_admission_hits: 2
  cache_disks:
  - path: ssd1

Casi todo el mundo ve la cola fresca del archivo, así que entra en la caché de inmediato. Las profundidades del archivo interesan a unos pocos espectadores — entran en la caché solo cuando se las vuelve a pedir.

Orden de las fuentes de lectura

Un fragmento del archivo se busca a lo largo de una cadena, y la primera fuente que responde cierra la solicitud:

  1. el segmentador del stream en vivo;
  2. la caché;
  3. el archivo local;
  4. el clúster (remotes);
  5. la fuente legacy old_m4f;
  6. el archivo legacy en disco.

Un acierto de caché responde sin tocar nada por debajo. Si un fragmento está a la vez en un disco de archivo y en un disco de caché, la lectura la sirve la caché: la caché en SSD gana a los discos mecánicos. Un stream sin sección cache no tiene ningún paso de caché en la cadena.

Qué pone un fallo en la caché

Una lectura con éxito de una fuente por debajo de la caché se escribe en un disco de caché junto con su fragmento init. Las diferencias respecto a la grabación del archivo:

  • el recorte de max_depth no se aplica — en la caché entra lo que pidió el espectador, aunque sea más profundo que cualquier profundidad de archivo configurada;
  • un segmento multipista se guarda entero, con todas las pistas — así el cambio de bitrate de un espectador lo sirven aciertos y no fallos;
  • la escritura es idempotente — varios espectadores que fallen a la vez sobre el mismo fragmento dejan exactamente una copia en la caché;
  • un error de escritura en la caché no afecta a la respuesta del cliente — este ya tiene los bytes; el error solo se registra y se cuenta en las métricas.

El texto cifrado se guarda en la caché tal cual, junto con su fragmento init: el edge no tiene con qué descifrarlo y entrega exactamente los bytes que llegaron. Ese medio se reconoce por la descripción de su pista — el esquema y el identificador de la clave llegan a MediaInfo desde el fragmento init y forman parte de la identidad de la pista igual que el códec, así que un cambio de clave se resuelve con el mismo mecanismo que un cambio de códec. El texto cifrado nunca llega al archivo: el archivo alimenta vistas previas, miniaturas y la línea de tiempo, y todas ellas leen dentro de la muestra.

Lectura anticipada

Ver el archivo es secuencial, así que tras servir una lectura Sapsan descarga en segundo plano el fragmento siguiente de la misma pista, si todavía no está en la caché. La lectura anticipada funciona en un edge puro y al leer de una fuente remota, se limita a un fragmento por delante y nunca retrasa la respuesta al cliente.

Esto no es un precalentamiento: aquí no existe rellenar la caché por calendario ni por EPG.

Desalojo

El espacio en un disco de caché lo liberan blobs horarios enteros, en orden de último acceso — el primero en irse es el usado menos recientemente — hasta que el disco vuelve a entrar en ambos límites.

  • La edad del contenido no es un criterio: el programa popular de ayer sobrevive al impopular de hoy, y la hora actual se desaloja en igualdad de condiciones con las demás.
  • La única excepción es un blob al que un escritor está añadiendo datos justo ahora: ese se queda, y en su lugar se va el siguiente menos recientemente usado.
  • La limpieza del archivo (max_depth y max_bytes del stream) y la protección de episodios no consideran los discos de caché en absoluto.

El orden de desalojo lo mantiene su propio índice del catálogo y sobrevive a un reinicio. La marca de acceso se vuelca al catálogo de forma diferida — como mucho una vez cada 10 minutos por blob — para que la lectura no se convierta en escritura.

La contabilidad de la caché (volumen ocupado, tiempos de acceso) se restaura al arrancar mediante un escaneo de rangos del catálogo, sin recorrer los ficheros de datos. Un disco de caché borrado es un estado frío válido: el servidor arranca, la caché se llena desde cero, el archivo queda intacto.

Línea de tiempo y profundidad en un edge

La profundidad del rebobinado y los rangos del archivo de un stream cacheado se calculan como la unión del catálogo local (archivo y caché) y de todas las fuentes remotas — y se anuncian en las playlists de rebobinado y en las respuestas sobre los rangos del archivo. Un espectador en el edge ve la misma profundidad que en el origin.

Las ventanas de las fuentes se fusionan en una lista, conservando los huecos entre ellas: un intervalo continuo desde el inicio hasta el fin de una fuente no debe sustituir a esa lista — de lo contrario la línea de tiempo pinta de verde intervalos sin datos, y un clic en ellos acaba en un 404. Los huecos no mayores que la resolución solicitada se siguen fusionando por la regla general.

Si el origin no está accesible pero el rango pedido está entero en la caché, la playlist se construye a partir del catálogo local y los fragmentos se sirven de la caché — la reproducción continúa.

Observabilidad

Cada lectura del archivo se atribuye al eslabón de la cadena que la sirvió:

  • cache — la sirvió el disco de caché del nodo (un acierto);
  • local — la sirvió el disco de archivo del nodo;
  • remote — hubo que ir a una fuente remota (un fallo).

Solo la lectura de un fragmento por un cliente cuenta como lectura del archivo. La salida del segmentador en vivo y las descargas de lectura anticipada no entran en la atribución — de lo contrario, la lectura anticipada inflaría la tasa de aciertos cuanto mejor funcionara; las descargas se cuentan aparte.

A Prometheus y a local-prom van los contadores acumulativos:

Métrica Significado
dvr_archive_reads_total{source} lecturas del archivo según los ejes cache / local / remote
dvr_archive_read_bytes_total{source} bytes de esas lecturas
dvr_read_ahead_fetches_total descargas de lectura anticipada
dvr_disk_reads_total{disk_id}, dvr_disk_read_bytes_total{disk_id} accesos al disco; en un disco de caché son sus aciertos
dvr_disk_cache_bytes{disk_id} volumen de caché en el disco

La dirección local GET /streamer/api-v4/dvr reporta el papel, el volumen y el límite de cada disco de caché, y las velocidades de lectura del nodo según los tres ejes. Los contadores acumulativos no se exponen en la management API: ahí van velocidades y gauges.

La tasa de aciertos nunca se entrega como un número listo — es cache / (cache + local + remote), y la calcula el consumidor: las velocidades se suman, la división va después. Un promedio de promedios miente cuando los nodos pesan distinto.

Las pantallas de la consola donde esto se ve están descritas en la documentación de Catena: capacidad de DVR en el clúster y ajustes del nodo; el montaje de un edge en un clúster de Catena — Streamers edge.

En qué se diferencia de la replicación diferida por remotes

Los remotes tienen un comportamiento parecido: un fragmento leído de un servidor remoto se añade al archivo local. La diferencia es fundamental:

Replicación diferida por remotes Caché del archivo
Dónde se escribe en discos de archivo en discos de caché
Para qué traer aquí para siempre la historia ajena servir localmente las solicitudes repetidas
Cuándo se libera con la limpieza según la retención del stream con el desalojo según el último acceso
Discos de archivo necesarios no, un edge puede funcionar sin ellos

La replicación consiste en reubicar el archivo; la caché, en ahorrar red en lo popular.

Qué viene después