Qual é a filosofia por trás de atrasar a gravação de dados no disco?

72

No Linux, uma execução finalizada de um comando como cp ou dd não significa que os dados foram gravados no dispositivo. É preciso, por exemplo, chamar sync ou invocar o item "Remover com segurança" ou "Ejetar" "função na unidade.

Qual é a filosofia por trás de tal abordagem? Por que os dados não são gravados de uma só vez? Não há perigo de que a gravação falhe devido a um erro de E / S?

    
por marmistrz 20.08.2015 / 15:32

12 respostas

47

What's the philosophy behind such an approach?

Eficiência (melhor uso das características do disco) e desempenho (permite que o aplicativo continue imediatamente após uma gravação).

Why isn't the data written at once?

A principal vantagem é que o sistema operacional é livre para reordenar e mesclar operações de gravação contíguas para melhorar o uso de largura de banda (menos operações e menos pesquisas). Os discos rígidos funcionam melhor quando um pequeno número de operações grandes é solicitado, enquanto os aplicativos tendem a precisar de um grande número de pequenas operações. Outra otimização clara é que o SO também pode remover todos, exceto a última gravação, quando o mesmo bloco é escrito várias vezes em um curto período de tempo, ou até mesmo remover algumas gravações, se o arquivo afetado tiver sido removido nesse meio tempo.

Essas gravações assíncronas são feitas após a chamada do sistema write foi retornada. Essa é a segunda e mais visível vantagem do usuário. As gravações assíncronas aceleram os aplicativos, já que estão livres para continuar seu trabalho sem esperar que os dados realmente estejam no disco. O mesmo tipo de buffering / caching também é implementado para operações de leitura nas quais blocos de leitura recentes ou frequentemente são retidos na memória, em vez de serem lidos novamente do disco.

Is there no danger that the write will fail due to an IO error?

Não necessariamente. Isso depende do sistema de arquivos usado e da redundância no local. Um erro de E / S pode ser inofensivo se os dados puderem ser salvos em outro lugar. Sistemas de arquivos modernos, como o ZFS, fazem a auto-cura de blocos de disco defeituosos. Note também que erros de E / S não travam sistemas operacionais modernos. Se ocorrerem durante o acesso a dados, eles serão simplesmente informados ao aplicativo afetado. Se eles acontecerem durante o acesso aos metadados estruturais e colocarem o sistema de arquivos em risco, eles poderão ser remontados como somente leitura ou ficarão inacessíveis.

Existe também um pequeno risco de perda de dados em caso de falha do sistema operacional, falta de energia ou falha de hardware. Esta é a razão pela qual os aplicativos que devem ter 100% de certeza de que os dados estão no disco (por exemplo, bancos de dados / aplicativos financeiros) estão fazendo gravações síncronas menos eficientes, porém mais seguras. Para atenuar o impacto no desempenho, muitos aplicativos ainda usam gravações assíncronas, mas acabam sincronizando-as quando o usuário salva explicitamente um arquivo (por exemplo, vim, processadores de texto).

Por outro lado, uma grande maioria de usuários e aplicativos não precisa nem se importa com a segurança que as gravações síncronas fornecem. Se houver uma queda ou falta de energia, o único risco é perder no pior dos últimos 30 segundos de dados. A menos que haja uma transação financeira envolvida ou algo semelhante que implique um custo muito maior que 30 segundos de seu tempo, o enorme ganho em desempenho (que não é uma ilusão, mas muito real) permite que as assinaturas assíncronas superem amplamente o risco.

Por fim, as gravações síncronas não são suficientes para proteger os dados gravados de qualquer maneira. Se o seu aplicativo realmente precisa ter certeza de que seus dados não podem ser perdidos, aconteça o que acontecer, a replicação de dados em vários discos e em vários locais geográficos deve ser implementada para resistir a desastres como incêndios, inundações, etc.

    
por 20.08.2015 / 15:36
59

Ele simplesmente dá uma ilusão de velocidade para programas que não precisam esperar até que uma gravação seja concluída. Monte seus sistemas de arquivos no modo de sincronização (que lhe dá suas gravações instantâneas) e veja como tudo está lento.

Às vezes, os arquivos existem apenas temporariamente ... um programa faz um pouco de trabalho e exclui o arquivo logo após o término do trabalho. Se você atrasou essas gravações, pode se safar de nunca tê-las escrito em primeiro lugar.

Is there no danger that the write will fail due to an IO error?

Oh, absolutamente. Nesse caso, geralmente o sistema de arquivos inteiro entra em modo somente leitura, e tudo é horrível. Mas isso raramente acontece, não adianta perder as vantagens de desempenho em geral.

    
por 20.08.2015 / 15:43
26

AE / S assíncrona e em buffer estava em uso antes do Linux e antes mesmo do Unix. O Unix tinha isso, e todos os seus desdobramentos.

Aqui está o que Ritchie e Thompson escreveram em seu artigo do CACM O Sistema de Compartilhamento de Tempo do UNIX :

To the user, both reading and writing of files appear to be synchronous and unbuffered. That is immediately after return from a read call the data are available, and conversely after a write the user’s workspace may be reused. In fact the system maintains a rather complicated buffering mechanism which reduces greatly the number of I/O operations required to access a file.

Na sua pergunta, você também escreveu:

Is there no danger that the write will fail due to an IO error?

Sim, a gravação pode falhar e o programa pode nunca saber disso. Embora nunca seja uma coisa boa, os efeitos disso podem ser minimizados nos casos em que um erro de I / O gera um pânico no sistema (em alguns sistemas operacionais isso é configurável - em vez de entrar em pânico, o sistema pode continuar rodando, mas o sistema de arquivos afetado é desmontado ou montado somente leitura). Os usuários podem então ser notificados de que os dados nesse sistema de arquivos são suspeitos. E uma unidade de disco pode ser monitorada de forma proativa para ver se sua lista de defeitos crescentes está aumentando rapidamente, o que é uma indicação de que a unidade está falhando.

O BSD adicionou o fsync conv=fsync para certificar-se de que todos os dados foram gravados antes do comando sair. Ele é útil quando se está escrevendo para desacelerar drives flash removíveis, onde os dados armazenados em buffer podem levar vários minutos para serem gravados.

Outra fonte de corrupção de arquivos é um desligamento repentino do sistema, por exemplo, de perda de energia. Praticamente todos os sistemas atuais suportam um sinalizador clean / dirty em seus sistemas de arquivos. O sinalizador é definido como limpo quando não há mais dados a serem gravados e o sistema de arquivos está prestes a ser desmontado, normalmente durante o encerramento do sistema ou chamando manualmente umount . Os sistemas normalmente executarão fsck na reinicialização se detectarem que os sistemas de arquivos não foram desligados corretamente.

    
por 20.08.2015 / 16:48
15

Muitas boas respostas, mas deixe-me adicionar uma outra coisa ... Lembre-se que o Unix é um sistema multi-processo e multi-usuários, então potencialmente muitos usuários estariam tentando fazer operações de arquivo (esp. gravações) em ( quase) ao mesmo tempo. Com antigos discos rígidos lentos - talvez montados através da rede - isso não só levaria tempo (para o qual os programas basicamente travariam e os usuários teriam que esperar), mas causariam muita movimentação da cabeça de leitura / gravação do disco rígido. disco para frente e para trás.

Então, em vez disso, os arquivos que estão esperando para serem gravados foram mantidos na memória por um tempo, e classificados depois de onde deveriam acabar no disco ... e quando o buffer estava cheio - ou o daemon de sincronização de disco esperou o número necessário de segundos (acho que usualmente foi cerca de 30 segundos) - o buffer inteiro foi escrito no disco "em ordem", com o cabeçote de gravação tendo apenas que fazer um contínuo. varrendo o movimento, escrevendo os arquivos para o disco como ele foi ... em vez de saltar por todo o lugar.

De acordo com os discos velozes de hoje - para não mencionar dispositivos de estado sólido - o ganho é muito menor ... espeicamente em um sistema linux doméstico, onde há apenas um usuário trabalhando por vez, e apenas com um alguns programas.

De qualquer forma, a combinação de antecipar leituras lendo (para o cache / buffer) mais do que era pedido - e ordenar dados esperando para serem escritos, para que pudesse ser escrita em "um movimento" - era realmente muito boa idéia na época, especialmente em sistemas com muita leitura e escrita por muitos usuários.

    
por 20.08.2015 / 21:41
13

Não é específico para Linux, e é chamado de cache de páginas (que o Linux faz muito bem). Veja também link ; então, se um arquivo é escrito, então leia novamente alguns segundos depois, muitas vezes nenhuma E / S de disco é necessária.

A principal vantagem é que em muitos sistemas, há muita RAM, e alguns deles podem ser usados como cache pelo kernel. Portanto, algumas operações de arquivos podem tirar proveito desse armazenamento em cache. Além disso, o tempo de E / S do disco é muito mais lento (normalmente milhares de vezes para o SDD e quase um milhão de vezes mais lento para discos rígidos mecânicos) do que a RAM.

O código do aplicativo pode fornecer dicas sobre esse armazenamento em cache: consulte, por exemplo, posix_fadvise (2) & madvise (2)

    
por 20.08.2015 / 15:46
8

Os pratos de giro são mais lentos que a RAM. Usamos o armazenamento em cache de leituras / gravações para "ocultar" esse fato.

A coisa útil sobre escrever E / S é que ele não requer que o E / S de disco ocorra imediatamente - ao contrário de uma leitura, em que você não pode retornar dados para o usuário até que a leitura seja concluída no disco.

Assim, as gravações operam sob uma restrição de tempo flexível - contanto que nossa taxa de transferência sustentada não exceda a de nosso disco, podemos ocultar muitas das penalidades de desempenho em um cache de gravação.

E precisamos gravar discos em cache, que são muito lentos comparativamente. Mas, para fazer os modernos tipos de RAID, há uma penalidade significativa na operação.

Um RAID 6, por exemplo, para concluir um IO de gravação deve:

  • Leia o bloco de atualização
  • leia parity1
  • leia a paridade 2
  • escrever novo bloco
  • paridade de gravação 1
  • paridade de gravação 2

Assim, cada gravação é realmente 6 operações IO - e particularmente quando você tem discos lentos como grandes unidades SATA, isso fica extremamente caro.

Mas há uma boa solução fácil - escrever em coalescência. Se você pode construir uma 'faixa completa' escrita em um buffer, você não precisa ler a paridade do seu disco - você pode calculá-la com base no que você tem na memória.

É muito desejável fazer isso, porque você não tem mais amplificação de gravação. De fato, você pode acabar com uma penalidade de gravação menor do que o RAID 1 + 0.

Considere:

RAID 6, 8 + 2 - 10 fusos.

8 blocos de dados consecutivos para gravar - calcule a paridade no cache e escreva um bloco em cada disco. 10 escritas por 8, significa uma penalidade de escrita de 1,25. 10 discos de RAID 1 + 0 ainda tem uma penalidade de escrita de 2 (porque você tem que escrever para cada subespelho). Portanto, neste cenário, você pode realmente fazer com que o RAID 6 tenha um desempenho melhor do que o RAID1 + 0. No uso do mundo real, você obtém um pouco mais de um perfil de IO misto.

Portanto, o cache de gravação faz uma enorme diferença no desempenho percebido dos conjuntos RAID - você pode gravar na velocidade da RAM e ter uma baixa penalidade de gravação - melhorando sua taxa de transferência sustentada, se fizer isso.

E se você não o fizer, sofrerá o lento desempenho do SATA, mas multiplicará por 6 e adicionará alguma contenção a ele. Seu 10 way SATA RAID-6 sem gravação em cache seria um pouco mais rápido do que uma única unidade sem RAID ... mas não por muito.

No entanto, você corre um risco - como você observou - perda de energia significa perda de dados. Você pode atenuar isso por ciclos de liberação de cache, bateria fazendo backup de seu cache ou usando SSD ou outros caches não voláteis.

    
por 20.08.2015 / 16:18
7

Nenhuma das outras respostas mencionadas atrasou a alocação . XFS, ext4, BTRFS e ZFS todos os usam. O XFS o usa desde antes da existência do ext4, então vou usá-lo como exemplo:

O XFS nem decide onde colocar os dados até que seja escrito. Atraso na alocação fornece ao alocador muito mais informações para basear suas decisões em. Quando um arquivo é escrito pela primeira vez, não há como saber se será um arquivo de 4k ou um arquivo de 1G e ainda crescente. Se houver 10G de espaço livre contíguo em algum lugar, colocar o arquivo 4k no início não será bom. Colocar o arquivo grande no início de um grande espaço livre reduz a fragmentação.

    
por 23.08.2015 / 01:41
4

Todas as outras respostas aqui estão no mínimo mais corretas para o caso normal, e eu recomendaria ler qualquer uma delas antes da minha, mas você mencionou dd e dd tem um caso de uso típico que não envolve o cache de gravação. O cache de gravação é implementado principalmente no nível do sistema de arquivos. Os dispositivos brutos normalmente não gravam em cache (vários drivers de dispositivos, como raid ou lvm, são outra bola de cera). Como o dd é freqüentemente usado com dispositivos de bloco brutos, ele fornece as opções bs e relacionadas para permitir gravações grandes para melhor desempenho em dispositivos brutos. Isso não é tão útil quando os dois pontos de extremidade são arquivos regulares (embora as gravações grandes usem menos chamadas de sistema nesse caso). O outro lugar comum em que isso é particularmente visível é o pacote mtools, que é uma implementação do sistema de arquivos do userspace. Usar mtools com uma unidade de disquete sempre se sente incrivelmente lento, pois as ferramentas são completamente síncronas e as unidades de disquete são incrivelmente lentas. Montar o disquete e usar o sistema de arquivos do kernel é muito mais responsivo, exceto por umount que é síncrono (e muito importante para que seja assim evitar a perda de dados, especialmente para dispositivos removíveis como disquetes). Existem apenas alguns outros programas que eu sei que estão sendo usados regularmente com dispositivos brutos, como bancos de dados especialmente configurados (que implementam seu próprio cache de gravação), tar e dispositivos especiais e ferramentas de sistema de arquivos como chdsk, mkfs e mt.

    
por 22.08.2015 / 16:59
3

A filosofia é insegura por padrão.

Existem duas estratégias razoáveis e óbvias possíveis: liberar as gravações no disco imediatamente ou atrasar a gravação. O UNIX escolheu historicamente o último. Então, fique seguro, você precisa chamar fsync depois.

No entanto, você pode especificar segurança antecipadamente montando um dispositivo com a opção sync ou por arquivo, abrindo-os com O_SYNC .

Lembre-se de que o UNIX foi projetado para especialistas em computação. "Seguro por padrão" não foi considerado. Segurança significa E / S mais lenta, e esses primeiros sistemas realmente tinham E / S lenta, fazendo com que a taxa de preço fosse alta. Infelizmente, nem o UNIX nem o Linux mudaram para o safe-be-default, mesmo que seja uma mudança sem quebra.

    
por 21.08.2015 / 11:30
2

Comercializa uma pequena quantidade de confiabilidade para um grande aumento no rendimento.

Suponha, por exemplo, um programa de compactação de vídeo. Com gravação atrasada ("write back"):

  1. gasta 10ms de compactação de quadros
  2. emita o quadro de gravação no disco
  3. aguarde 10ms para que o disco reconheça a gravação concluída
  4. GOTO 1

Versus

  1. gasta 10ms de compactação de quadros
  2. emite o quadro de gravação para o disco (conclui em segundo plano)
  3. GOTO 1

A segunda versão aparece duas vezes mais rápida porque pode usar a CPU e o disco ao mesmo tempo, enquanto a primeira versão está sempre à espera de um ou outro.

Geralmente, você deseja write-back para operações de streaming e operações de arquivos em massa e write-through para bancos de dados e aplicativos semelhantes a bancos de dados.

    
por 24.08.2015 / 11:03
1

Em muitos aplicativos, os dispositivos de armazenamento ficarão intermitentemente ocupados lendo os dados. Se um sistema sempre puder adiar gravações até um momento em que o dispositivo de armazenamento não estiver ocupado lendo dados, do ponto de vista de um aplicativo, as gravações levarão o tempo zero para serem concluídas. As únicas situações em que as gravações não seriam instantâneas seriam quando:

  1. Os buffers de gravação são preenchidos até o ponto em que nenhuma solicitação de gravação adiada possa ser aceita até que as gravações sejam realmente concluídas.

  2. É necessário desligar ou remover o dispositivo para o qual as gravações estão pendentes.

  3. Um aplicativo solicita especificamente a confirmação de que uma gravação está realmente concluída.

Na verdade, é apenas por causa dos requisitos acima que as gravações precisam realmente acontecer. Por outro lado, geralmente não há motivo para não executar gravações pendentes às vezes quando um dispositivo estaria inativo, então muitos sistemas os executam.

    
por 24.08.2015 / 18:51
0

Existe também isto:

Escreva "Olá, Joe Moe"
é mais rápido que:
Escreva "Olá",
Escreva "Joe"
Escreva "Moe"

E também:

Escreva "Olá, como vai você?" é mais rápido que:
Escreva "Oi, como está?" Excluir isso
Escreva "Howdy, como você está?" Excluir isso
Escreva "Olá, como vai você?"

É melhor que modificações e agregações ocorram na RAM do que no disco. Gravações em disco em lote liberam os desenvolvedores de aplicativos de tais preocupações.

    
por 20.02.2018 / 14:18