Devemos montar com data = write-back e barreira = 0 no ext3?

13

Executamos um servidor em uma VM em uma empresa de hospedagem e acabamos de se inscrever para um host dedicado (AMD Opteron 3250, 4 núcleos, 8 GB de RAM, 2 x 1 TB de software RAID, ext3).

Ao executar testes de desempenho, percebemos que algumas transações SQLite (combinação de inserções, exclusões e / ou atualizações) demoravam 10 a 15 vezes mais do que no meu MacBook Pro de 2010.

Após muita pesquisa e leitura no Google, pudemos observar as opções de montagem, que eram:

    data=ordered,barrier=1

Fizemos algumas experiências e obtivemos o melhor desempenho com

    data=writeback,barrier=0

Eu li sobre isso e entendi o básico do que eles estão fazendo, mas não tenho um bom senso / senso de saber se é uma boa ideia executarmos assim?

Questões

A configuração acima é sensata a considerar para um serviço hospedado?

Se tivermos uma queda de energia ou uma falha grave, poderemos acabar com os dados perdidos ou os arquivos corrompidos. Se tirássemos instantâneos do banco de dados a cada 15 minutos, isso pode atenuar a situação, mas o banco de dados pode não ser sincronizado quando o instantâneo é obtido. Como devemos (podemos?) Garantir a integridade de um instantâneo?

Existem outras opções que devemos considerar?

obrigado

NeilB
fonte
Muitos fatores estão envolvidos. Você espera muitas falhas difíceis? Você tem um no-break (ou algo equivalente) conectado à sua máquina hospedada? Você fez alguns testes de comparação com outros sistemas de arquivos (por exemplo, ext4, XFS, etc.)? Você pode controlar ((des) ativar) o cache do disco rígido? Como você configurou o seu RAID de software? Você está HDD alinhado corretamente (se tiver blocos de 4K)?
Huygens
Não esperamos muitos acidentes difíceis. Nós não temos um no-break. A especificação da máquina era um padrão "pronto para uso" da empresa de hospedagem, portanto: não comparamos outros fs, ext3 é o que obtivemos. Não sei sobre o cache do disco rígido, analisará isso e da mesma forma o alinhamento de RAID e HDD. Obrigado.
21413 NeilB
Outra pergunta que esqueci é quanto vale a pena perder na história? Ou você não pode se dar ao luxo de perder? Nota: O SQLite suporta snapshot ou, em outras palavras, o backup de um banco de dados em execução. sqlite.org/backup.html
Huygens
Qual é a sua versão do kernel? Barreiras são honradas pelo md desde 2.6.33, não na versão anterior do kernel.
Huygens
relatórios uname -r "2.6.32-220.2.1.el6.x86_64". O que é "md"? Se barreiras não são respeitadas nesta versão do kernel, por que vi uma melhoria de desempenho ao desativar barreiras?
21413 NeilB

Respostas:

15

Primeiro conselho
Se você não puder perder dados (quero dizer, uma vez que um usuário inseriu novos dados, se não puder ser perdido nos próximos segundos) e porque você não possui algo como um no-break, eu não removeria a barreira de gravação, nem eu mudaria para writeback.

Removendo Barreiras de Gravação
Se você remover a barreira de gravação, em caso de falha ou perda de energia, o sistema de arquivos precisará executar um fsck para reparar a estrutura do disco (observe que, mesmo com a barreira ativada, a maioria dos sistemas de arquivos de registro em diário ainda executaria um fsck embora a repetição do diário deva ter sido suficiente). Ao remover a barreira de gravação, é recomendável remover qualquer cache de disco (no hardware), se possível, isso ajuda a minimizar o risco. Você deve avaliar o impacto dessa mudança. Você pode tentar este comando (se o seu hardware suportar) hdparm -W0 /dev/<your HDD>.
Observe que o ext3 usa 2 barreiras para alteração de metadados, enquanto o ext4 usa apenas um ao usar a opção de montagem journal_async_commit.

Embora Ted T'so tenha explicado por que alguns poucos dados corrompidos ocorreram nos primeiros dias do ext3 (as barreiras estavam desativadas por padrão até o Kernel 3.1 ), o diário é colocado de uma maneira que, a menos que ocorra uma quebra do log do diário (o diário é um log cíclico) os dados são gravados no disco em uma ordem segura - primeiro o diário, os dados depois - mesmo com o disco rígido que permite reordenar as gravações.
Basicamente, seria azar que uma falha no sistema ou perda de energia aconteça quando o log do diário for encerrado. No entanto, você precisa manter data=ordered. Tente comparar com data=ordered,barrier=0além disso.

Se você puder perder alguns segundos de dados, poderá ativar as duas opções, data=writeback,barrier=0mas também poderá experimentar o commit=<nrsec>parâmetro. Verifique o manual para este parâmetro aqui . Basicamente, você fornece um número de segundos, que é um período em que o sistema de arquivos ext3 sincronizará seus dados e metadados.
Você também pode tentar mexer e comparar alguns ajustes do kernel em relação a páginas sujas (aquelas que precisam ser gravadas em disco); há um bom artigo aqui que explica tudo sobre esses ajustes e como jogar com eles.

Resumo sobre barreiras
Você deve comparar outras combinações de ajustes:

  1. Use data=writeback,barrier=0em conjunto comhdparm -W0 /dev/<your HDD>
  2. Usar data=ordered,barrier=0
  3. Use data=writeback,barrier=0em conjunto com a outra opção de montagem commit=<nrsec>e tente valores diferentes para o nrsec
  4. Use a opção 3. e tente outro ajuste no nível do kernel em relação às páginas sujas.
  5. Use o cofre data=ordered,barrier=1, mas tente outros ajustáveis: especialmente o elevador do sistema de arquivos (CFQ, Deadline ou Noop) e seus respectivos ajustes.

Considerando mover para ext4 e compará-lo
Como o ext4 requer menos barreira que ext3 para uma gravação. Além disso, o ext4 suporta extensões que, para arquivos grandes, podem trazer melhor desempenho. Portanto, é uma solução que vale a pena explorar, especialmente porque é fácil migrar de um ext3 para ext4 sem reinstalar: documentação oficial ; Eu fiz isso em um sistema, mas usando este guia Debian . O Ext4 é realmente estável desde o kernel 2.6.32, portanto é seguro usá-lo na produção.

Última consideração
Esta resposta está longe de ser completa, mas fornece materiais suficientes para começar a investigar. Isso depende tanto dos requisitos (no nível do usuário ou do sistema) que é difícil ter uma resposta direta, desculpe por isso.

Huygens
fonte
Obrigado - muitas coisas úteis lá. Eu já tinha lido o documento ext3 no kernel.org e tentei alterar o commit, mas não tinha noção do que era um grande valor. Definido para 15 em vez de 5 segundos, não vi alterações. Farei mais alguns testes comparativos, para cobrir as permutações que você sugeriu. Obrigado novamente.
21313 NeilB
Foi uma boa ideia tentar aumentar o tempo de consolidação, mantendo os padrões seguros! É possível que SQLite seja a única descarga / sincronização, o que poderia ser uma explicação por que você não mediu nenhuma alteração no desempenho usando a opção de confirmação.
Huygens
@ NeilB apenas tropeça nesses artigos: 1. sqlite.org/draft/lockingv3.html procure ext3nele. Dá uma explicação talvez mais fácil de entender (ou simplificada) do que tentei abordar na minha resposta. 2. sqlite.1065341.n5.nabble.com/… você pode tentar manter os padrões ext3 seguros (ordenados + barreira), mas remover a sincronização no SQLite. Em breve, atualizarei minha resposta sobre esse segundo aspecto.
Huygens
Obrigado por isso. Estou prestes a elaborar todas as permutações e executar testes de desempenho com eles, por sua vez. No início, tentei sincronizar no SQLite e obtive bons números de desempenho. Preciso escrever um código para reunir um intervalo de dados para diferentes combinações de operações de gravação primeiro. Vou postar um resumo aqui, mas se você quiser mais detalhes, eu vou falar com a bowers dot com.
21413 NeilB
10

Advertência: pode haver imprecisões abaixo. Eu tenho aprendido muitas dessas coisas à medida que avança, então leve com uma pitada de sal. Isso é bastante longo, mas você pode apenas ler os parâmetros com os quais estávamos jogando e pular para a Conclusão no final.

Há várias camadas nas quais você pode se preocupar com o desempenho de gravação do SQLite:

níveis diferentes para pensar em desempenho

Vimos os destacados em negrito. Os parâmetros particulares foram

  • Cache de gravação em disco. Os discos modernos têm cache de RAM, usado para otimizar as gravações de disco em relação ao disco rotativo. Com isso ativado, os dados podem ser gravados em blocos fora de ordem; portanto, se ocorrer uma falha, você poderá acabar com um arquivo parcialmente gravado. Verifique a configuração com hdparm -W / dev / ... e defina-a com hdparm -W1 / dev / ... (para ativá-la e -W0 para desativá-la).
  • barreira = (0 | 1). Muitos comentários online dizendo "se você executar com barreira = 0, não terá o cache de gravação em disco ativado". Você pode encontrar uma discussão sobre barreiras em http://lwn.net/Articles/283161/
  • data = (diário | pedido | write-back). Consulte http://www.linuxtopia.org/HowToGuides/ext3JournalingFilesystem.html para obter uma descrição dessas opções.
  • confirmar = N. Diz ao ext3 para sincronizar todos os dados e metadados a cada N segundos (padrão 5).
  • Pragma SQLite síncrono = LIGADO | FORA. Quando ativado, o SQLite garantirá que uma transação seja "gravada no disco" antes de continuar. Desativar isso basicamente torna as outras configurações em grande parte irrelevantes.
  • Pragma SQLite cache_size. Controla a quantidade de memória que o SQLite usará para o cache da memória. Tentei dois tamanhos: um em que o banco de dados inteiro caberia no cache e outro em que o cache tinha metade do tamanho máximo do banco de dados.

Leia mais sobre as opções ext3 na documentação ext3 .

Eu executei testes de desempenho em várias combinações desses parâmetros. O ID é um número de cenário, mencionado abaixo.

cenários que eu tentei

Comecei executando a configuração padrão em minha máquina como cenário 1. O cenário 2 é o que eu assumo ser o "mais seguro" e tentei várias combinações, quando apropriado / solicitado. Provavelmente é mais fácil de entender com o mapa que acabei usando:

mapa relacionando cenários a parâmetros

Escrevi um script de teste que executava muitas transações, com inserções, atualizações e exclusões, todas em tabelas com apenas INTEGER, somente TEXTO (com coluna id) ou mistas. Eu executei isso várias vezes em cada uma das configurações acima:

plot mostrando horários para cenários

Os dois cenários inferiores são os 6 e 17, que têm "pragma synchronous = off", tão surpreendente que foram os mais rápidos. O próximo cluster de três é # 7, # 11 e # 19. Esses três são destacados em azul no "mapa de configuração" acima. Basicamente, a configuração é cache de gravação em disco, barreira = 0 e conjunto de dados para algo diferente de 'diário'. Alterar a confirmação entre 5 segundos (nº 7) e 60 segundos (nº 11) parece fazer pouca diferença. Nesses testes, não parecia haver muita diferença entre dados = pedidos e dados = write-back, o que me surpreendeu.

O teste de atualização mista é o pico do meio. Há um cluster de cenários que são claramente mais lentos neste teste. Estes são todos aqueles com data = diário . Caso contrário, não há muito entre os outros cenários.

Eu fiz outro teste de temporização, que fez uma mistura mais heterogênea de inserções, atualizações e exclusões nas diferentes combinações de tipos. Isso levou muito mais tempo, e é por isso que não o incluí no gráfico acima:

tipos misturados e inserir / atualizar / excluir

Aqui você pode ver que a configuração de write-back (nº 19) é um pouco mais lenta que as solicitadas (nº 7 e nº 11). Eu esperava que o write-back fosse um pouco mais rápido, mas talvez dependa dos seus padrões de gravação ou talvez ainda não tenha lido o suficiente no ext3 :-)

Os vários cenários foram um pouco representativos das operações realizadas por nosso aplicativo. Após escolher uma lista de cenários, executamos testes de cronometragem com alguns de nossos conjuntos de testes automatizados. Eles estavam de acordo com os resultados acima.

Conclusão

  • O parâmetro commit parecia fazer pouca diferença, então estamos deixando isso em 5s.
  • Vamos continuar com o cache de gravação de disco, barreira = 0 e dados = ordenados . Li algumas coisas on-line que consideravam uma configuração ruim e outras que pareciam pensar que esse deveria ser o padrão em muitas situações. Acho que o mais importante é que você tome uma decisão informada, sabendo quais trade-offs você está tomando.
  • Não vamos usar o pragma síncrono no SQLite.
  • Definir o pragma SQLite cache_size para que o banco de dados caiba na memória melhorou o desempenho em algumas operações, como esperávamos.
  • A configuração acima significa que estamos correndo um pouco mais de risco. Usaremos a API de backup do SQLite para minimizar o risco de falha do disco em uma gravação parcial: tirando um instantâneo a cada N minutos e mantendo o último M por perto. Testei essa API durante a execução de testes de desempenho, e isso nos deu confiança para seguir esse caminho.
  • Se ainda quiséssemos mais, poderíamos examinar o kernel, mas melhoramos as coisas o suficiente sem ir para lá.

Obrigado a @Huygens por várias dicas e sugestões.

NeilB
fonte