Escolhendo um arquivador para logs de backup

Olá pessoal!


Neste artigo, quero falar sobre como escolhi o arquivador para compactar os logs do nosso sistema de front-office.


A divisão em que trabalho está envolvida no desenvolvimento e manutenção de um sistema unificado de front office do Banco. Sou responsável por sua manutenção, monitoramento e DevOps.


Nosso sistema é um aplicativo altamente carregado que atende a mais de 5.000 usuários únicos diariamente. Hoje é um "monólito" com todas as suas vantagens e desvantagens. Mas agora o processo de transferência de funcionalidade para microsserviços está em andamento.


Todos os dias, nosso sistema gera mais de 130 GB de logs brutos e, apesar de usarmos a pilha ENG (Elasticsearch Nxlog Graylog), os logs de arquivos contêm muito mais informações (por exemplo, erros de rastreamento de pilha) e, portanto, requerem arquivamento e armazenamento.


Como o local de armazenamento é limitado, surge a pergunta: "E qual arquivador melhor lidará com esta tarefa".


Para resolver esse problema, escrevi um script do PowerShell que executava a análise para mim.


A tarefa do script é chamar os arquivadores rar, 7z e zip com diferentes parâmetros de compactação, para calcular a velocidade da formação do arquivo, bem como o espaço em disco usado.


ArchSearch.ps1
#Requires -Version 4.0 #  ,      Clear-Host #   ,     Set-Location $PSScriptRoot #  ,      $Archive = "Archive" $ArchFileName = "ArchFileName" [array]$path = (Get-ChildItem '.\logs').DirectoryName|Select-Object -Unique #      -.  ,     . if ((Test-Path -Path ".\$Archive") -ne $true){ New-Item -Path .\ -Name $Archive -ItemType Directory -Force } else { #    -    Get-ChildItem .\$Archive|Remove-Item -Recurse -Force } #      [array]$table=@() #   Rar #rar # m<0..5> Set compression level (0-store...3-default...5-maximal) 1..5|foreach{ $CompressionLevel = $("-m" + $_) $mc = Measure-Command {cmd /c .\rar.exe a -ep1 -ed $CompressionLevel -o+ -tsc .\$Archive\$($ArchFileName + $_) "$path"} [math]::Round(($mc.TotalMilliseconds), 0) $ArchFileNamePath = ".\$Archive\$($ArchFileName + $_ + ".rar")" $table += ""|Select-Object -Property @{name="ArchFileName"; expression={$ArchFileNamePath -split "\\"|Select-Object -Last 1}},` @{name="CompressionLevel"; expression={$CompressionLevel}},@{name="Extension"; expression={"rar"}},@{name="Size"; expression={(Get-ChildItem $ArchFileNamePath).Length}},` @{name="Time"; expression={[math]::Round(($mc.TotalMilliseconds), 0)}},` @{name="Size %"; expression={0}},@{name="Time %"; expression={0}},@{name="Result %"; expression={0}} } #   7z #7z # -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra) #cmd /c "$env:ProgramFiles\7-Zip\7z.exe" a -mx="$MX" -mmt="$MMT" -t7z -ssw -spf $($ArchFileName + "Fastest") "$path" 1..9|foreach{ $CompressionLevel = $("-mx=" + $_) $mc = Measure-Command {cmd /c "$env:ProgramFiles\7-Zip\7z.exe" a $CompressionLevel -t7z -ssw -spf .\$Archive\$($ArchFileName + $_) $path} #-mmt="$MMT" [math]::Round(($mc.TotalMilliseconds), 0) $ArchFileNamePath = ".\$Archive\$($ArchFileName + $_ + ".7z")" $table += ""|Select-Object -Property @{name="ArchFileName"; expression={$ArchFileNamePath -split "\\"|Select-Object -Last 1}},` @{name="CompressionLevel"; expression={$CompressionLevel}},@{name="Extension"; expression={"7z"}},@{name="Size"; expression={(Get-ChildItem $ArchFileNamePath).Length}},` @{name="Time"; expression={[math]::Round(($mc.TotalMilliseconds), 0)}},` @{name="Size %"; expression={0}},@{name="Time %"; expression={0}},@{name="Result %"; expression={0}} } #   zip (  PS "Compress-Archive") #zip 1..2|foreach{ Switch ($_){ 1{$CompressionLevel = "Fastest"} 2{$CompressionLevel = "Optimal"} } $mc = Measure-Command {Compress-Archive -Path $path -DestinationPath .\$Archive\$($ArchFileName + $_) -CompressionLevel $CompressionLevel -Force} [math]::Round(($mc.TotalMilliseconds), 0) $ArchFileNamePath = ".\$Archive\$($ArchFileName + $_ + ".zip")" $table += ""|Select-Object -Property @{name="ArchFileName"; expression={$ArchFileNamePath -split "\\"|Select-Object -Last 1}},` @{name="CompressionLevel"; expression={$CompressionLevel}},@{name="Extension"; expression={"zip"}},@{name="Size"; expression={(Get-ChildItem $ArchFileNamePath).Length}},` @{name="Time"; expression={[math]::Round(($mc.TotalMilliseconds), 0)}},` @{name="Size %"; expression={0}},@{name="Time %"; expression={0}},@{name="Result %"; expression={0}} } #     Size     [0] -     $Size = ($table|Sort-Object -Property Size)[0].Size / 100 #     Time     [0] -      $Time = ($table|Sort-Object -Property Time)[0].Time / 100 #    $table|foreach { $_.time $_."Size %" = [math]::Round(($_.Size / $Size), 0) $_."Time %" = [math]::Round(($_.Time / $Time), 0) if ($_."Size %" -ge $_."Time %"){ $_."Result %" = $_."Size %" - $_."Time %" } else { $_."Result %" = $_."Time %" - $_."Size %" } } #        "Size %" -     $table|Sort-Object -Property "Size %","Result %"|Select-Object -First 1|Format-Table -AutoSize #        "Result %" -          $table|Sort-Object -Property "Result %","Size %","Time %"|Select-Object -First 1|Format-Table -AutoSize $table|Sort-Object -Property "Size %","Result %"|Select-Object -First 1|Format-Table -AutoSize $table|Sort-Object -Property "Result %","Size %","Time %"|Select-Object -First 1|Format-Table -AutoSize #  !   ,     Get-ChildItem .\$Archive|Remove-Item -Force 

Trabalho preparatório:


 #   ,   PowerShell  4.0 ($PSVersionTable): #Requires -Version 4.0 #  ,      Clear-Host #   ,     (   .\) Set-Location $PSScriptRoot 

 #  ,      $Archive = "Archive" $ArchFileName = "ArchFileName" [array]$path = (Get-ChildItem '.\logs').DirectoryName|Select-Object -Unique #      -.  ,      if ((Test-Path -Path ".\$Archive") -ne $true){ New-Item -Path .\ -Name $Archive -ItemType Directory -Force } else { #   ,     Get-ChildItem .\$Archive|Remove-Item -Recurse -Force } #      [array]$table=@() 

Analisamos com mais detalhes


 #     1  5       foreach 1..5|foreach{ 

 #    $CompressionLevel   1  5($_),       $CompressionLevel = $("-m" + $_) 

 #  Measure-Command     ,   {} $mc = Measure-Command {cmd /c .\rar.exe a -ep1 -ed $CompressionLevel -o+ -tsc .\$Archive\$($ArchFileName + $_) "$path"} 

 #       [math]::Round(($mc.TotalMilliseconds), 0) #    $ArchFileName + $_ + ".rar": Archive1.rar $ArchFileNamePath = ".\$Archive\$($ArchFileName + $_ + ".rar")" #   $table (+=)   $table += ""|Select-Object -Property @{name="ArchFileName"; expression={$ArchFileNamePath -split "\\"|Select-Object -Last 1}},` @{name="CompressionLevel"; expression={$CompressionLevel}},@{name="Extension"; expression={"rar"}},@{name="Size"; expression={(Get-ChildItem $ArchFileNamePath).Length}},` @{name="SizeAVD"; expression={0}},@{name="Time"; expression={[math]::Round(($mc.TotalMilliseconds), 0)}},` @{name="Size %"; expression={0}},@{name="Time %"; expression={0}},@{name="Result %"; expression={0}} } 

 #     Size     [0] -     $Size = ($table|Sort-Object -Property Size)[0].Size / 100 #     Time     [0] -      $Time = ($table|Sort-Object -Property Time)[0].Time / 100 #    $table|foreach { $_.time $_."Size %" = [math]::Round(($_.Size / $Size), 0) $_."Time %" = [math]::Round(($_.Time / $Time), 0) if ($_."Size %" -ge $_."Time %"){ $_."Result %" = $_."Size %" - $_."Time %" } else { $_."Result %" = $_."Time %" - $_."Size %" } } #        "Size %" -     $table|Sort-Object -Property "Size %","Result %"|Select-Object -First 1|Format-Table -AutoSize #        "Result %" -          $table|Sort-Object -Property "Result %","Size %","Time %"|Select-Object -First 1|Format-Table -AutoSize #  !   ,    . Get-ChildItem .\$Archive|Remove-Item -Force 

 $table|Sort-Object -Property "Size %","Result %"|Format-Table -AutoSize 

ArchfilenameNível de compressãoExtensãoTamanhoTempoTamanho%% De tempo% De resultado
ArchFileName8.7z-mx = 87z265115206240410016741574
ArchFileName9.7z-mx = 97z265115206461410017331633
ArchFileName7.7z-mx = 77z289481765283210914171308
ArchFileName6.7z-mx = 67z30051742373391131002889
ArchFileName5.7z-mx = 57z3123935535169118943825
ArchFileName4.rar-m4rar3351469311426126306180
ArchFileName5.rar-m5rar3346515212894126346220
ArchFileName3.rar-m3rar336980799835127264137
ArchFileName2.rar-m2rar34399885835213022494
ArchFileName4.7z-mx = 47z38926348647014717427
ArchFileName3.7z-mx = 37z44545819588916815810
ArchFileName2.7z-mx = 27z51690114475419512867
ArchFileName1.rar-m1rar53605833460020212379
ArchFileName1.7z-mx = 17z574721723728217100117
ArchFileName2.zipÓtimozip6573324214025248376128
ArchFileName1.zipMais rápidozip81556824903130824266.

 $table|Sort-Object -Property "Result %","Size %","Time %"|Format-Table -AutoSize 

ArchfilenameNível de compressãoExtensãoTamanhoTempoTamanho%% De tempo% De resultado
ArchFileName3.7z-mx = 37z44545819588916815810
ArchFileName4.7z-mx = 47z38926348647014717427
ArchFileName1.zipMais rápidozip81556824903130824266.
ArchFileName2.7z-mx = 27z51690114475419512867
ArchFileName1.rar-m1rar53605833460020212379
ArchFileName2.rar-m2rar34399885835213022494
ArchFileName1.7z-mx = 17z574721723728217100117
ArchFileName2.zipÓtimozip6573324214025248376128
ArchFileName3.rar-m3rar336980799835127264137
ArchFileName4.rar-m4rar3351469311426126306180
ArchFileName5.rar-m5rar3346515212894126346220
ArchFileName5.7z-mx = 57z3123935535169118943825
ArchFileName6.7z-mx = 67z30051742373391131002889
ArchFileName7.7z-mx = 77z289481765283210914171308
ArchFileName8.7z-mx = 87z265115206240410016741574
ArchFileName9.7z-mx = 97z265115206461410017331633

 #  !   ,    . Get-ChildItem .\$Archive|Remove-Item -Force 

O resultado:
O mais econômico em termos de espaço em disco foi 7z com uma taxa de compressão de -mx = 8 e -mx = 9



O tempo de criação do arquivo mais rápido foi 7z com uma taxa de compactação de -mx = 1



O melhor em velocidade e espaço ocupado foi 7z com uma taxa de compressão de -mx = 3



Escolhemos 7z com uma taxa de compactação de -mx = 8, pois o tamanho do arquivo morto é -mx 9, mas funciona um pouco mais rápido.


Ótimo, a taxa de arquivamento e compactação está selecionada, agora vamos arquivar os logs!


Precisamos resolver os seguintes problemas:


  1. Evite alta carga do servidor durante a operação.
  2. Processe todas as pastas com os registros de uma subpasta.
  3. Exclua arquivos com mais de 30 dias (para não ficar sem espaço em disco).
  4. Crie arquivos por dia, dependendo da hora em que os arquivos foram modificados.

ArchLogs.ps1
 #Requires -Version 4.0 #          #SCHTASKS /Create /SC DAILY /ST 22:00 /TN ArchLogs /TR "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe C:\Scripts\ArchLogs.ps1" /RU "NT AUTHORITY\NETWORKSERVICE" /F /RL HIGHEST #  ,      Clear-Host #   ,     Set-Location $PSScriptRoot #           . #  1 Function Set-MMTCore { $Core = (Get-WmiObject –class Win32_processor|Measure-Object NumberOfLogicalProcessors -sum).Sum / 2 $CoreTMP = $Core / 4 IF ($Core -lt 4) { $Core = $Core -1 } Else { $Core = $Core - $CoreTMP } [math]::Round($Core) } #    $MX = 8 #     $MMT = Set-MMTCore #  ,      $SearchFolder = "C:\inetpub" #     $SearchFolder $InetpubFolder = Get-ChildItem $SearchFolder #     Logs #  2 $LogsFolder = $InetpubFolder|foreach {Get-ChildItem $_.Fullname|Where-Object{$_.PSIsContainer -eq $true}|Where-Object{$_.name -eq "logs"}} #  ,      $Archive = "Archive" $ArchiveFile = "ArchFiles.txt" #      $LogsFolder   $LogsFolderName   foreach($LogsFolderName in $LogsFolder.Fullname){ $LogsFolderName #   $Archive,       IF ((Test-Path -Path "$LogsFolderName\$Archive") -ne $true){New-Item -Path $LogsFolderName -Name $Archive -ItemType Directory -Force} #    30  #  3 Get-ChildItem "$LogsFolderName\$Archive"|Where-Object {$_.LastWriteTime -le (Get-Date).AddDays(-30)}| Remove-Item -Force #     [Array]$ArchiveItems = Get-ChildItem -Path $LogsFolderName -Exclude $Archive #   , .    -  IF ($ArchiveItems.Count -ne ^_^quot&#0;quot^_^){ #       $AllLogsFiles = Get-ChildItem $ArchiveItems -Recurse <#-Filter *.log#>|Where-Object {$_.LastWriteTime -lt (Get-Date).Date} #     #  4 $AllData = ($AllLogsFiles|Sort-Object -Property LastWriteTime).LastWriteTime.Date|Select-Object -Unique $AllData foreach ($Data in $AllData){ IF ($ArchiveItems.Count -ne ^_^quot&#0;quot^_^){ #         ($AllLogsFiles|Where-Object {$_.LastWriteTime -lt (Get-Date).Date}|Where-Object {$_.LastWriteTime -ge (Get-Date $Data) -and $_.LastWriteTime -lt (Get-Date $Data).AddDays(1)}).FullName|Out-File .\$ArchiveFile -Force -Encoding default Write-Host "===" $Data Write-Host "===" #      IF ($(Get-Content .\ArchFiles.txt -Encoding default) -ne $null){ $ArchiveFileName =$(($LogsFolderName.Remove($LogsFolderName.LastIndexOf("\"))) -split "\\"|Select-Object -Last 1) + "_" + $(Get-Date $Data -Format dd-MM-yyyy) cmd /c "$env:ProgramFiles\7-Zip\7z.exe" a -mx="$MX" -mmt="$MMT" -t7z -ssw -sdel "$LogsFolderName\$Archive\$ArchiveFileName" "@$ArchiveFile" #        IF(Test-Path ".\$ArchiveFile"){Remove-Item ".\$ArchiveFile" -Force} #      Logs $LogsFolderName|foreach {Get-ChildItem $_|Where-Object {(Get-ChildItem -Path $_.FullName) -eq $null}|Remove-Item -Force} } } } } } 

Aqui não vou pintar todas as linhas do script (descritas nos comentários), mas focar apenas na função Set-MMTCore, que nos permite calcular o número de threads para 7z para não carregar o processador em nosso servidor:


 Function Set-MMTCore { #        2 $Core = (Get-WmiObject –class Win32_processor|Measure-Object NumberOfLogicalProcessors -sum).Sum / 2 #      4 $CoreTMP = $Core / 4 IF ($Core -lt 4) { $Core = $Core -1 } Else { $Core = $Core - $CoreTMP } #    [math]::Round($Core) } 

Sem usar a função Set-MMTCore

Pode-se ver que a CPU fica em 100%. Isso significa que inevitavelmente causaremos problemas no servidor e receberemos um alerta do sistema de monitoramento.



Ao usar a função Set-MMTCore

Pode-se ver que a CPU é de 30 a 35%. Isso significa que o uso da função Set-MMTCore permite arquivar arquivos sem afetar a operação do servidor.



O resultado do script de backup:


Pasta antes do arquivamento:


Pasta após o arquivamento:


Arquivos criados durante o processo de arquivamento:


Arquivos no arquivo:


Source: https://habr.com/ru/post/pt484414/


All Articles