Armazenamento do arquivo DVR e cache SSD

Apêndice para instalações com um arquivo grande: como o nó lê o arquivo DVR, como estimar a carga sobre os discos e escolher entre HDD e SSD, como colocar um cache SSD na frente de um array de HDDs com os recursos do SO e como configurar o sistema. A configuração dos armazenamentos em si e da limpeza está descrita em Armazenamentos DVR, e o acompanhamento deles, em Monitor de DVR.

Todos os números desta página são referências e exemplos para estimativa, e não uma promessa de desempenho: a carga real depende da audiência, do conjunto de canais e do hardware.

1. Como o nó lê o arquivo

O nó grava o arquivo em arquivos comuns no diretório do armazenamento e os lê com a leitura comum de arquivos. Por isso, toda leitura do arquivo passa pelo cache de páginas do Linux: a releitura dos mesmos segmentos é atendida pela memória RAM, sem acesso ao disco. A memória RAM é o primeiro nível de cache, e é gratuito; o nó não precisa de nenhuma configuração para isso.

Quase sem acessos ao disco, a memória atende:

  • a visualização com deslocamento (timeshift) e desde o início do programa dentro de cerca de meia hora a uma hora da transmissão ao vivo: esses segmentos acabaram de ser gravados e ainda estão no cache;

  • programas e eventos populares assistidos ao mesmo tempo por centenas de espectadores: o disco lê esse segmento uma vez, e os demais espectadores o recebem da memória;

  • o catch-up recente do horário nobre de ontem, que é assistido repetidamente.

A cauda longa — diferentes canais e dias do arquivo, cada um assistido por poucos — não cabe na memória e é lida dos discos. O Linux mantém por mais tempo as páginas lidas várias vezes, enquanto as visualizações únicas são expulsas pelo fluxo de gravação em meia hora a uma hora. Por isso, com um arquivo de dezenas de terabytes e uma audiência ampla, a memória tira dos discos, como regra, de um quarto a um terço das leituras: ela acelera o que é mais quente, mas não substitui o desempenho dos discos.

2. Estimativa da carga e escolha dos discos

Gravação, volume e leitura

Três grandezas são calculadas assim:

  • Fluxo de gravação = número de canais gravados × bitrate total de todas as variantes do canal. Por exemplo, 150 canais de 8 Mbit/s (três variantes de qualidade) dão 1200 Mbit/s, ou seja, 150 MB/s de gravação contínua.

  • Volume do arquivo = fluxo de gravação × profundidade de retenção. 150 MB/s são cerca de 13 TB por dia, 7 dias — cerca de 91 TB, 14 dias — cerca de 182 TB de espaço útil, sem contar o RAID.

  • Fluxo de leitura = espectadores simultâneos do arquivo × bitrate médio de visualização. O número de espectadores do arquivo é a fração de pico de espectadores simultâneos multiplicada pela fração dos que assistem ao arquivo, e não à transmissão ao vivo. Por exemplo, 10 000 assinantes, no pico 30 % diante das telas e 30 % deles no arquivo — 900 espectadores; a 4 Mbit/s em média, isso dá 3,6 Gbit/s, cerca de 450 MB/s de leitura.

Ao fluxo de leitura dos discos soma-se o fluxo de gravação: os discos atendem os dois ao mesmo tempo. Parte das leituras é tirada pela memória RAM (1. Como o nó lê o arquivo).

HDD e SSD

Cada espectador do arquivo é um fluxo de leitura sequencial separado, e centenas desses fluxos juntos parecem ao disco um acesso aleatório em blocos grandes.

  • HDD (NL-SAS ou SATA de 7200 rpm), com muitos fluxos simultâneos, entrega, como regra, 60–100 MB/s por disco, se a leitura antecipada for grande (4. Configuração do sistema). O custo por terabyte do HDD é o mais baixo.

  • SSD NVMe entrega gigabytes por segundo, e o acesso aleatório não o atrapalha. O terabyte custa várias vezes mais. A durabilidade de gravação é indicada em DWPD — quantos volumes completos do disco por dia podem ser gravados durante todo o período de garantia. Para o arquivo, ela é calculada assim: volume diário de gravação ÷ capacidade total dos discos. 13 TB por dia em oito discos de 15,36 TB dão cerca de 0,1 DWPD, com folga até para discos de 1 DWPD.

Exemplo para um arquivo de 7 dias (cerca de 91 TB): um RAID 6 de dez HDDs de 20 TB dá 160 TB de espaço útil e algo como 500–800 MB/s de leitura total. Isso basta para centenas de espectadores simultâneos do arquivo junto com a gravação. Quando há mais de mil espectadores do arquivo, esse array trabalha no limite: são necessários mais discos, um cache SSD (3. Cache SSD com os recursos do SO) ou um array de SSDs.

Escolha do RAID e recomendações gerais

  • RAID 6 é a escolha principal para grandes arrays de HDDs: a reconstrução após a troca de um disco de 20 TB demora muito, e o RAID 6 sobrevive à falha de um segundo disco nesse tempo. O RAID 5 não é recomendado em discos desse tamanho.

  • RAID 10 dá mais desempenho em carga mista, mas apenas metade da capacidade.

  • Para arrays de SSDs servem RAID 5, RAID 6 ou RAID 10: o tempo de reconstrução deles é muito menor.

  • Para cada disco ou array, um armazenamento (Armazenamentos DVR).

  • Referências para a escolha:

    • até cerca de mil espectadores simultâneos do arquivo — um array de HDDs (RAID 6 ou RAID 10) e 256–512 GB de memória RAM para o cache de páginas;

    • mais espectadores ou um arquivo de 30–90 dias com catch-up ativo — HDDs para a capacidade e cache SSD para o último dia, ou a distribuição dos canais entre vários nós;

    • um array somente de SSDs — quando o espaço no rack, o consumo de energia ou uma carga muito alta importam mais do que o custo do terabyte.

3. Cache SSD com os recursos do SO

O cache SSD não atrapalha o nó e não exige nada dele: o nó lê e grava arquivos, e o cache fica abaixo do sistema de arquivos (nível de blocos) ou dentro dele. Ordem por força do efeito: primeiro a memória RAM (cache de páginas), depois o SSD para os dados quentes do próximo dia ou dois (normalmente 2–8 TB de NVMe), depois os HDDs para a capacidade.

Gravação direta e gravação adiada

  • Gravação direta (writethrough) é o modo recomendado para o arquivo. A gravação vai imediatamente para o HDD, e o SSD guarda os blocos lidos com frequência. A falha do SSD não perde dados: o array continua funcionando sem o cache.

  • Gravação adiada (writeback) mantém no SSD também a gravação recente, o que acelera o timeshift e o catch-up recente. Mas os dados ainda não transferidos para o HDD se perdem junto com o SSD; por isso, nesse modo o cache é colocado somente em um espelho de dois SSDs (RAID 1), e ele consome a durabilidade de gravação do SSD.

  • dm-writecache faz cache apenas da gravação e não acelera a leitura do arquivo; para o arquivo ele não serve.

lvmcache: RHEL, AlmaLinux, Rocky Linux, Oracle Linux

O lvmcache (dm-cache) é a opção principal para sistemas baseados em RHEL, nos quais é suportado nativamente. O cache é um volume lógico no SSD, conectado ao volume do arquivo no mesmo grupo de volumes. A política padrão (smq) transfere para o SSD os blocos lidos repetidamente, por isso as visualizações únicas não poluem o cache. O cache pode ser conectado e desconectado em um volume em operação, sem parar a gravação.

No exemplo, o arquivo está no volume vg_dvr/dvr (array de HDDs), e o SSD é /dev/nvme0n1. Adicione o SSD ao grupo de volumes e crie nele o volume de cache:

sudo pvcreate /dev/nvme0n1
sudo vgextend vg_dvr /dev/nvme0n1
sudo lvcreate -n dvr_cache -L 3T vg_dvr /dev/nvme0n1

Conecte o cache no modo de gravação direta:

sudo lvconvert --type cache --cachevol dvr_cache --cachemode writethrough vg_dvr/dvr

Verifique o modo e as estatísticas de acertos:

sudo lvs -o name,size,cache_mode,cache_policy,cache_read_hits,cache_read_misses vg_dvr

A razão entre cache_read_hits e a soma de acertos e falhas é a fração das leituras atendidas pelo SSD. Para desconectar o cache: --splitcache mantém o volume de cache para nova conexão, --uncache o remove; os dados do arquivo permanecem nos HDDs nos dois casos. Nas versões antigas do LVM (por exemplo, no RHEL 7) não há --cachevol: nelas o volume de cache é primeiro transformado em um pool (lvconvert --type cache-pool) e conectado com --cachepool.

sudo lvconvert --splitcache vg_dvr/dvr

bcache: Debian e Ubuntu

O bcache faz parte do kernel do Linux e é difundido no Debian e no Ubuntu; no RHEL ele não é fornecido. Ele é criado em dispositivos vazios: em um array existente com arquivo, não é possível ativá-lo sem transferir os dados. O sistema de arquivos é criado já no dispositivo /dev/bcache0.

No exemplo, o array de HDDs é /dev/md0 e o SSD é /dev/nvme0n1. Crie o dispositivo com cache (por padrão, no modo de gravação direta):

sudo apt install bcache-tools
sudo make-bcache -B /dev/md0 -C /dev/nvme0n1

A principal configuração para o arquivo é sequential_cutoff. Por padrão, o bcache deixa passar fora do cache a leitura e a gravação sequenciais maiores que 4 MB, e cada espectador do arquivo é justamente um fluxo sequencial; portanto, com a configuração padrão o cache quase não guarda nada. Desative o limite:

echo 0 | sudo tee /sys/block/bcache0/bcache/sequential_cutoff

Esse valor não é mantido após a reinicialização: defina-o na inicialização, por exemplo com uma regra udev ou um serviço systemd. Verifique o modo e a fração de acertos:

cat /sys/block/bcache0/bcache/cache_mode
cat /sys/block/bcache0/bcache/stats_day/cache_hit_ratio

ZFS: ARC e L2ARC

No ZFS (pacotes OpenZFS), o papel do cache de páginas é exercido por um cache próprio na memória — o ARC, e o SSD é conectado ao pool como segundo nível de cache — o L2ARC. O L2ARC faz cache somente da leitura; a falha do SSD não perde dados. Conecte o SSD ao pool dvr:

sudo zpool add dvr cache /dev/nvme0n1

Por padrão, o L2ARC não aceita os dados lidos pela leitura antecipada, ou seja, os fluxos sequenciais dos espectadores do arquivo. Para o arquivo isso precisa ser desativado e também mantido para as próximas inicializações:

echo 0 | sudo tee /sys/module/zfs/parameters/l2arc_noprefetch
echo "options zfs l2arc_noprefetch=0" | sudo tee -a /etc/modprobe.d/zfs.conf

Mais algumas configurações para o arquivo:

  • recordsize=1M para o conjunto de dados com o arquivo — o arquivo é composto de arquivos grandes, lidos por inteiro;

  • atime=off — sem gravar o horário de acesso a cada leitura;

  • zfs_arc_max — limite de memória para o ARC; deixe memória também para o nó;

  • l2arc_write_max — velocidade de preenchimento do L2ARC; o valor padrão é pequeno e, com um arquivo grande, o cache é preenchido lentamente.

As estatísticas do ARC e do L2ARC são mostradas por arc_summary, e a carga nos dispositivos do pool, por zpool iostat -v dvr 5.

4. Configuração do sistema

  • Leitura antecipada. Para o array de HDDs, defina uma leitura antecipada grande, por exemplo 4 MB (8192 setores de 512 bytes); ela é mantida até a reinicialização, por isso defina-a também na inicialização (com uma regra udev). Para um volume LVM, o mesmo é definido por lvchange --readahead.

    sudo blockdev --setra 8192 /dev/md0
    sudo blockdev --getra /dev/md0
    
  • Memória para o cache. O cache de páginas ocupa toda a memória livre, por isso deixe uma reserva para o nó: não execute nele outros processos que consomem muito e não permita que o sistema entre em swap. A devolução da memória não utilizada pelo nó está descrita em Memória.

  • Sistema de arquivos. Servem o XFS (padrão em sistemas baseados em RHEL) e o ext4. Monte o armazenamento com noatime, para que a leitura do arquivo não gere gravações do horário de acesso.

  • Acompanhamento. A carga nos discos é mostrada por iostat -x 5 (colunas de leitura e gravação em MB/s, tempo de espera, utilização do dispositivo), o volume do cache de páginas, pela linha buff/cache na saída de free -h, e os acertos do cache SSD, pelos comandos das seções acima. As latências de leitura e gravação do arquivo por fluxo são mostradas pela tela «Monitor de DVR» (Monitor de DVR), e, em leituras e gravações demoradas, é acionado o alerta de código 50 (dvr-rw-time, Lista de alertas).