Estou tentando fazer um teste de importação a partir do nosso quadro existente. Temos cerca de 25 milhões de posts para importar (posts normais + conversas privadas), então, para acelerar isso, criei várias cópias do script de importação para executar simultaneamente e dividir a carga de tópicos. Isso funcionou bem por alguns dias, e com o tempo notei que o uso de memória de cada processo aumentava lentamente até cerca de 2 GB cada. Então, o servidor finalmente ficou sem memória e matou o banco de dados MySQL de origem por volta da marca de 16 milhões de posts.
Aumentei a memória do sistema de 24 GB para 32 GB, mas agora, ao tentar reiniciar até mesmo um processo de importação e retomar de onde parou, esse processo consome cerca de 10 GB de memória desde o início, antes mesmo de começar a importar posts. Antes, eu conseguia executar 8 processos de importação simultâneos; agora, consigo colocar apenas 2 em um pool de memória maior. Por que há essa enorme discrepância entre o uso de memória em uma instalação limpa e o uso de memória ao reiniciar uma importação após uma falha? Existe alguma maneira de reduzir essa pegada de memória para que eu possa acelerar o processo de importação novamente? Um servidor com 128 GB a 256 GB de memória será proibitivamente caro (e não será necessário após a importação), e operar com apenas 2 processos de importação fará com que a importação leve semanas para ser concluída.
O uso de memória parece ocorrer todo durante as seções “Carregando postagens existentes…” (ou tópicos) da inicialização do script de importação, e não durante o processamento real das postagens. Pelo que posso ver, essa seção está buscando informações de postagens e tópicos no banco de dados e não deveria envolver nenhuma expressão regular.
As variáveis @posts e @topics parecem ser usadas para coisas como o método “topic_lookup_from_imported_post_id”. Isso faz sentido, exceto que, quando o script estava na execução inicial, o uso de memória nunca chegou perto do que estou vendo agora, mesmo com esses métodos ainda funcionando.
Você viu os scripts de importação em massa? Eles podem ter um uso de memória menor.
Mas é verdade que os scripts de importação mantêm na memória um mapa dos IDs antigos de usuários, tópicos e posts para os novos, o que consome bastante RAM, especialmente se você quiser várias cópias.
Você entende que, após executar a importação inicial, você a executará novamente para importar apenas os novos dados e ela será muito mais rápida, certo? Então, depois de esperar um mês para fazer a importação inicial, a final não levará tanto tempo.
Não tenho conhecimento de nenhum script de importação em massa. Eles estão em algum lugar no diretório import_scripts?
Sim, é aqui que estou tendo dificuldades. As coisas estavam relativamente bem durante a importação inicial, com 8 processos de importação rodando, até que o sistema ficou sem memória. Agora, quando tento reiniciar o processo de importação e retomar de onde parou, cada processo está usando cerca de 5 vezes mais memória do que quando travou pela primeira vez.
Precisamos completar uma importação total para ter um teste adequado e definir expectativas sobre quando essa migração poderá ocorrer de verdade. No momento, ainda não tenho uma compreensão clara do que esperar em relação a aspectos como desempenho. Também notei que, mesmo no marco de 16 milhões de posts, o tamanho do banco de dados já é mais de 50% maior do que nosso banco de dados atual — isso foi uma surpresa. O longo tempo de importação não torna isso impossível, mas certamente seria muito mais conveniente se a expectativa fosse de dias em vez de semanas.
Para tópicos e posts, não é realmente viável executar importações paralelas de qualquer maneira, pois não é possível importar um post em um tópico se o tópico e todos os posts anteriores não já tiverem sido importados. Suponho que você pudesse ter processos paralelos para usuários e tópicos, mas não para posts, a menos que reescreva o script para buscar todos os posts de um tópico, o que permitiria importações paralelas; isso certamente é viável, mas não é assim que funcionam os scripts que eu usei. Mas você ainda terá o problema deles manterem na memória RAM um mapeamento de IDs antigos para novos.
É isso que estou fazendo. Dividi os tópicos de modo que cada um seja processado por apenas um processo. Não é uma divisão perfeita, mas é várias vezes mais rápida que um processo linear único.
Essa é a parte mais confusa. Acredito que esteja fazendo isso conforme avança, e é por isso que vi o uso de memória de cada processo aumentar ao longo de 3 dias. Eles chegavam a cerca de 2 a 2,5 GB de memória cada antes de perder a conexão com o banco de dados.
Cada processo estaria mantendo apenas o mapeamento para os posts que importou? Se for esse o caso, talvez faça sentido que o uso de memória tenha explodido após reiniciar a importação.
Acho que sim. E os outros não funcionarão corretamente porque não têm aqueles dias que foram importados por outros processos. Não acho que o que você está fazendo vá funcionar.
Você precisará ou examinar os scripts de importação em massa ou reescrever o base.rb para acompanhar os links para os IDs de importação de outra forma.
É provável que você passe mais semanas depurando seu código do que apenas esperando. A velocidade da CPU de um único processo é a melhor maneira de acelerar as coisas.
Até agora, não observei nenhum problema com essa abordagem, embora eu possa imaginar que alguns problemas possam ocorrer com alguns dos métodos que são executados após a importação do post. Provavelmente, vou querer garantir que tudo pare após isso e, em seguida, executar uma execução de thread única para assegurar que o restante seja tratado de forma limpa.
Dito isso, sua sugestão de lidar com os links de ID de importação de maneira diferente provavelmente é boa em qualquer caso. Manter uma quantidade arbitrariamente grande de dados em algumas variáveis durante a duração do script não é muito eficiente.