Compressão de rede MongoDB: uma situação em que todos ganham
Avalie esse Tutorial
{Um recurso pouco divulgado do MongoDB é sua capacidade de compactar dados entre o cliente e o servidor. A empresa de CRM Close tem um artigo ótimo sobre como a compactação reduziu o tráfego de rede de cerca de 140 Mbps para 65 Mpbs. Conforme observado pela Close, com os custos de transferência de dados na nuvem variando de US$0.01 por GB ou mais, é possível obter uma boa economia com uma simples alteração na configuração.
MongoDB é compatível com os seguintes compactadores:
Habilitar a compressão do cliente envolve simplesmente instalar a biblioteca de compressão desejada e, em seguida, passar o compressor como um argumento quando você se conectar ao MongoDB. Por exemplo:
1 client = MongoClient('mongodb://localhost', compressors='zstd')
Este artigo fornece dois scripts Python ajustáveis, read-from-mongo.py e write-to-mongo.py, que você pode usar para ver o impacto da compactação da rede.
Edite params.py e, no mínimo, defina sua string de conexão. Outros ajustes incluem a quantidade de bytes para ler e inserir (padrão 10 MB) e o tamanho do lote para ler (100 registros) e inserir (1 MB):
1 # Read to Mongo 2 target_read_database = 'sample_airbnb' 3 target_read_collection = 'listingsAndReviews' 4 megabytes_to_read = 10 5 batch_size = 100 # Batch size in records (for reads) 6 7 # Write to Mongo 8 drop_collection = True # Drop collection on run 9 target_write_database = 'test' 10 target_write_collection = 'network-compression-test' 11 megabytes_to_insert = 10 12 batch_size_mb = 1 # Batch size of bulk insert in megabytes
pip3 install python-snappy
pip3 install zstandard
Meu script read-from-mongo.py usa a amostra do conjunto de dados do AirBnB, mas QUALQUER conjunto de dados será suficiente para esse teste.
pip3 install faker
Os provedores de nuvem cobram notavelmente pela saída de dados, então qualquer coisa que reduza o tráfego de saída da rede é uma vitória.
Vamos primeiro executar o script sem compactação de rede (padrão):
1 ✗ python3 read-from-mongo.py 2 3 MongoDB Network Compression Test 4 Network Compression: Off 5 Now: 2021-11-03 12:24:00.904843 6 7 Collection to read from: sample_airbnb.listingsAndReviews 8 Bytes to read: 10 MB 9 Bulk read size: 100 records 10 11 1 megabytes read at 307.7 kilobytes/second 12 2 megabytes read at 317.6 kilobytes/second 13 3 megabytes read at 323.5 kilobytes/second 14 4 megabytes read at 318.0 kilobytes/second 15 5 megabytes read at 327.1 kilobytes/second 16 6 megabytes read at 325.3 kilobytes/second 17 7 megabytes read at 326.0 kilobytes/second 18 8 megabytes read at 324.0 kilobytes/second 19 9 megabytes read at 322.7 kilobytes/second 20 10 megabytes read at 321.0 kilobytes/second 21 22 8600 records read in 31 seconds (276.0 records/second) 23 24 MongoDB Server Reported Megabytes Out: 188.278 MB
Você obviamente notou que os Megabytes relatados (188 MB) são mais de 18 vezes o nosso tamanho de teste de 10 MBs. Há vários motivos para isso, incluindo outras cargas de trabalho em execução no servidor, replicação de dados para nós secundários e o pacote TCP ser maior do que apenas os dados. Concentre-se na diferença entre as outras execuções de testes.
O script aceita um argumento opcional de compressão, que deve ser
snappy
, zlib
ou zstd
. Vamos executar o teste novamente usandosnappy
, que é conhecido por ser rápido, mas sacrifica um pouco a compactação:1 ✗ python3 read-from-mongo.py -c "snappy" 2 3 MongoDB Network Compression Test 4 Network Compression: snappy 5 Now: 2021-11-03 12:24:41.602969 6 7 Collection to read from: sample_airbnb.listingsAndReviews 8 Bytes to read: 10 MB 9 Bulk read size: 100 records 10 11 1 megabytes read at 500.8 kilobytes/second 12 2 megabytes read at 493.8 kilobytes/second 13 3 megabytes read at 486.7 kilobytes/second 14 4 megabytes read at 480.7 kilobytes/second 15 5 megabytes read at 480.1 kilobytes/second 16 6 megabytes read at 477.6 kilobytes/second 17 7 megabytes read at 488.4 kilobytes/second 18 8 megabytes read at 482.3 kilobytes/second 19 9 megabytes read at 482.4 kilobytes/second 20 10 megabytes read at 477.6 kilobytes/second 21 22 8600 records read in 21 seconds (410.7 records/second) 23 24 MongoDB Server Reported Megabytes Out: 126.55 MB
Com a compressão
snappy
, nossa saída de bytes relatada foi cerca de 62 MBs
a menos. Essa é uma economia de 33%
. Mas espere, o 10 MBs
dos dados foi lido em 10
segundos a menos. Isso também é um aumento de desempenho de 33%
!Vamos tentar isso novamente usando
zlib
, que pode obter uma melhor compressão, mas às custas do desempenho.A compactação zlib suporta um nível de compactação opcional. Para este teste, eu o defini como
9
(compressão máxima).1 ✗ python3 read-from-mongo.py -c "zlib" 2 3 MongoDB Network Compression Test 4 Network Compression: zlib 5 Now: 2021-11-03 12:25:07.493369 6 7 Collection to read from: sample_airbnb.listingsAndReviews 8 Bytes to read: 10 MB 9 Bulk read size: 100 records 10 11 1 megabytes read at 362.0 kilobytes/second 12 2 megabytes read at 373.4 kilobytes/second 13 3 megabytes read at 394.8 kilobytes/second 14 4 megabytes read at 393.3 kilobytes/second 15 5 megabytes read at 398.1 kilobytes/second 16 6 megabytes read at 397.4 kilobytes/second 17 7 megabytes read at 402.9 kilobytes/second 18 8 megabytes read at 397.7 kilobytes/second 19 9 megabytes read at 402.7 kilobytes/second 20 10 megabytes read at 401.6 kilobytes/second 21 22 8600 records read in 25 seconds (345.4 records/second) 23 24 MongoDB Server Reported Megabytes Out: 67.705 MB
Com a compactação
zlib
configurada no nível máximo, conseguimos obter uma redução de 64%
na saída da rede, embora tenha levado 4 segundos a mais. No entanto, isso ainda representa uma melhoria de desempenho de 19%
se comparado ao não uso de compactação.Vamos executar um teste final usando
zstd
, que é anunciado para reunir a velocidade de snappy
com a eficiência de compactação de zlib
:1 ✗ python3 read-from-mongo.py -c "zstd" 2 3 MongoDB Network Compression Test 4 Network Compression: zstd 5 Now: 2021-11-03 12:25:40.075553 6 7 Collection to read from: sample_airbnb.listingsAndReviews 8 Bytes to read: 10 MB 9 Bulk read size: 100 records 10 11 1 megabytes read at 886.1 kilobytes/second 12 2 megabytes read at 798.1 kilobytes/second 13 3 megabytes read at 772.2 kilobytes/second 14 4 megabytes read at 735.7 kilobytes/second 15 5 megabytes read at 734.4 kilobytes/second 16 6 megabytes read at 714.8 kilobytes/second 17 7 megabytes read at 709.4 kilobytes/second 18 8 megabytes read at 698.5 kilobytes/second 19 9 megabytes read at 701.9 kilobytes/second 20 10 megabytes read at 693.9 kilobytes/second 21 22 8600 records read in 14 seconds (596.6 records/second) 23 24 MongoDB Server Reported Megabytes Out: 61.254 MB
E, com certeza,
zstd
faz jus à sua reputação, obtendo uma melhoria de 68%
por cento na compressão, juntamente com uma melhoria de 55%
no desempenho!Os provedores de nuvem geralmente não cobram pela entrada de dados. No entanto, considerando as melhorias substanciais de desempenho com cargas de trabalho de leitura, o que se pode esperar das cargas de trabalho de gravação?
O script write-to-Mongo.py grava um documento gerado aleatoriamente no banco de dados e na collection configurada em params.py, sendo o padrão
test.network_compression_test
.Como antes, vamos executar o teste sem compactação:
1 python3 write-to-mongo.py 2 3 MongoDB Network Compression Test 4 Network Compression: Off 5 Now: 2021-11-03 12:47:03.658036 6 7 Bytes to insert: 10 MB 8 Bulk insert batch size: 1 MB 9 10 1 megabytes inserted at 614.3 kilobytes/second 11 2 megabytes inserted at 639.3 kilobytes/second 12 3 megabytes inserted at 652.0 kilobytes/second 13 4 megabytes inserted at 631.0 kilobytes/second 14 5 megabytes inserted at 640.4 kilobytes/second 15 6 megabytes inserted at 645.3 kilobytes/second 16 7 megabytes inserted at 649.9 kilobytes/second 17 8 megabytes inserted at 652.7 kilobytes/second 18 9 megabytes inserted at 654.9 kilobytes/second 19 10 megabytes inserted at 657.2 kilobytes/second 20 21 27778 records inserted in 15.0 seconds 22 23 MongoDB Server Reported Megabytes In: 21.647 MB
Então, levou
15
segundos para gravar 27,778
registros. Vamos executar o mesmo teste com compressão zstd
:1 ✗ python3 write-to-mongo.py -c 'zstd' 2 3 MongoDB Network Compression Test 4 Network Compression: zstd 5 Now: 2021-11-03 12:48:16.485174 6 7 Bytes to insert: 10 MB 8 Bulk insert batch size: 1 MB 9 10 1 megabytes inserted at 599.4 kilobytes/second 11 2 megabytes inserted at 645.4 kilobytes/second 12 3 megabytes inserted at 645.8 kilobytes/second 13 4 megabytes inserted at 660.1 kilobytes/second 14 5 megabytes inserted at 669.5 kilobytes/second 15 6 megabytes inserted at 665.3 kilobytes/second 16 7 megabytes inserted at 671.0 kilobytes/second 17 8 megabytes inserted at 675.2 kilobytes/second 18 9 megabytes inserted at 675.8 kilobytes/second 19 10 megabytes inserted at 676.7 kilobytes/second 20 21 27778 records inserted in 15.0 seconds 22 23 MongoDB Server Reported Megabytes In: 8.179 MB
Nossos megabytes relatados foram reduzidos em
62%
. No entanto, nosso desempenho de gravação permaneceu idêntico. Pessoalmente, acho que muito disso se deve ao tempo que a biblioteca Faker leva para gerar os dados de amostra. Mas o fato de termos obtido compressão sem impacto no desempenho ainda é uma vitória.Há algumas opções para medir o tráfego de rede. Este script está usando o db.serverStatus()
physicalBytesOut
e physicalBytesIn
, relatando o delta entre a leitura no início e no final da execução do teste. Como mencionado anteriormente, nossas medições são corrompidas por outro tráfego de rede que ocorre no servidor, mas meus testes mostraram uma melhoria consistente quando executados. Visualmente, os resultados obtidos aparecem da seguinte forma:Outra opção seria usar uma ferramenta de análise de rede como o Wireshark. Mas isso está além do escopo deste artigo por enquanto.
Resumindo, a compactação reduz o tráfego de rede em mais de 60%, o que está consoante à melhoria observada pela Close. Mais importante ainda, a compactação também teve uma melhora significativa no desempenho de leitura. Isso é vantajoso para todos!