Skalowanie Bacula na przykładach

Klienci często mnie pytają czy Bacula Enterprise jest dla nich odpowiednio skalowalna. Jako skalowanie mają na myśli dwa podstawowe elementy: ilość możliwych do obsłużenia klientów (generalnie zadań backupowych) oraz ilość obsługiwanych plików w pojedynczej bazie katalogowej. W przypadku oprogramowania Bacula Enterprise zarówno ilość obsługiwanych klientów (zadań), jak i ilość obsługiwanych plików nie jest technicznie ograniczona i w rzeczywistych środowiskach zależy głównie od dostępnych zasobów serwera na którym działają Bacula Director oraz bazy katalogowe. Specjalnie w poprzednim zdaniu użyłem liczby mnogiej, gdyż Bacula Enterprise ma możliwość jednoczesnej obsługi większej ilości baz katalogowych, które przechowują informacje o backupach poszczególnych klientów. Faktycznie działające instalacje na świecie moga poszczycić się ponad 130M plików obsługiwanych w pojedynczej bazie katalogowej oraz obsługę ponad 2000 klientów przez pojedynczy Bacula Director. To sporo, może nawet lepiej niż komercyjna konkurencja. Jednak opisywanie i chwalenie się usłyszanymi (nawet formalnymi referencjami) nie jest tak przekonujące jak własne doświadczenia. Postanowiłem więc wykonać kilka testów do których zmobilizował mnie jeden z klientów (pozdrawiam koleżankę Gosię :)) chcący mieć potwierdzenie, że skalowalność Bacula nie jest tylko mityczna.

Test jaki chciałem wykonać to wykonanie backupu oraz budowanie drzewa odtwarzania dla środowiska zawierającego ponad 6M plików backupowanych w pojedynczym zadaniu. Na początek specyfikacja środowiska:

Jako serwer testowy posłuży nam maszyna wirtualna o poniższych parametrach:
# lscpu
Architecture:          x86_64
CPU op-mode(s):        64-bit
CPU(s):                2
Thread(s) per core:    1
Core(s) per socket:    1
CPU socket(s):         2
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 2
Stepping:              3
CPU MHz:               3411.978
Hypervisor vendor:     KVM
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              4096K

# free
             total       used       free     shared    buffers     cached
Mem:       2061392    1656472     404920          0        684     896068
-/+ buffers/cache:     759720    1301672
Swap:       385016        420     384596

Jest to więc niewielkie środowisko testowe o bardziej niż ograniczonych zasobach.
Backupowane zasoby to katalog /data/test o wspomnienej wcześniej ilości plików:

# find /data/test -print|wc -l
6040201

Uruchamiamy zadanie.

| jobid | name          | starttime           | type | level | jobfiles  | jobbytes | jobstatus |
+-------+---------------+---------------------+------+-------+-----------+----------+-----------+
|     1 | BackupClient1 | 2012-03-28 11:11:03 | B    | F     | 6,040,201 |        0 | T         |

Zadanie wykonane, teraz rozpoczynamy procedurę testów budowy drzewa odtwarzania. Wybieramy wykonane wcześniej zadanie i już po niecałej 1,5min możemy dowoli wybierać pliki (poniższe logi zostały przycięte wyłącznie do interesujacych informacji):

# time echo "restore jobid=1" | bconsole
You have selected the following JobId: 1

Building directory tree for JobId(s) 1 ...  +++++++++++++++++++++++++++++++++++++++++++++++++
6,000,000 files inserted into the tree.

cwd is: /
$
real    1m23.276s
user    0m0.008s
sys     0m0.000s

We wskazanym powyżej zadaniu Bacula musiała wykonać dwa czasochłonne kroki: najpierw pobrać z bazy danych wszystkie pliki należące do wskazanego zadania a następnie w pamięci zbudować drzewo katalogów tak aby możliwe było bardzo szybkie przeglądanie i wybieranie plików do odtworzenia. Szybkość może wynikać z tego, że w bazie katalogowej znajduje się tylko 6M plików, zróbmy więc kolejny backup i test odtwarzania:

# time echo restore jobid=2|bconsole
You have selected the following JobId: 2

Building directory tree for JobId(s) 2 ...  +++++++++++++++++++++++++++++++++++++++++++++++++
6,000,000 files inserted into the tree.

cwd is: /
$
real    1m57.407s
user    0m0.016s
sys     0m0.000s

Jak widać czas się nieznacznie wydłużył i w dalszym ciągu czas budowania jest relatywnie niewielki. Sprawdzmy także czy ilość danych w bazie wpłynęła na inne backupy, np. bardzo małe:

# time echo restore jobid=5|bconsole
You have selected the following JobId: 5

Building directory tree for JobId(s) 5 ...  ++++++++++++++++++++++++++++++++++++++
115 files inserted into the tree.

cwd is: /
$
real    0m0.048s
user    0m0.008s
sys     0m0.000s

Jak widać absolutnie nie wpływa. To potwierdza, że czas budowania drzewa odtwarzania zależy w głównej mierze od ilości plików w danym zadaniu backupowym a nie od ilości plików w całej bazie katalogowej.
Sprawdźmy także jak wygląda budowanie drzewa dla zadań Full + Incremental (w naszym przykładzie incr zmienił ok. 20k plików):

# time echo restore jobid=2,6|bconsole
You have selected the following JobIds: 2,6

Building directory tree for JobId(s) 2,6 ...  +++++++++++++++++++++++++++++++++++++++++++++++++
6,000,000 files inserted into the tree.

cwd is: /
$
real    2m11.753s
user    0m0.008s
sys     0m0.004s

Troszkę dłużej niż w sam backup Full. To może kolejne przyrostowe???

# time echo restore jobid=2,6,7|bconsole
You have selected the following JobIds: 2,6,7

Building directory tree for JobId(s) 2,6,7 ...  +++++++++++++++++++++++++++++++++++++++++++++++++
6,000,000 files inserted into the tree.

cwd is: /
$
real    2m19.992s
user    0m0.008s
sys     0m0.016s

# time echo restore jobid=2,6,7,8|bconsole
You have selected the following JobIds: 2,6,7,8

Building directory tree for JobId(s) 2,6,7,8 ...  +++++++++++++++++++++++++++++++++++++++++++++++++
6,000,000 files inserted into the tree.

cwd is: /
$
real    2m5.344s
user    0m0.008s
sys     0m0.004s

Z powyższych przykładów widać, że backupy przyrostowe nie za bardzo zmieniają uzyskane czasy i są one praktycznie stałe.

Podstawowym czynnikiem ograniczającym wydajność procesu budowania drzewa odtwarzania jest wielkość pamieci serwera i pamięci przydzielonej dla silnika bazodanowego. W przykładowym teście PostgreSQL otrzymał 1024MB pamięci dzielonej co przy 2GB fizycznej pamięci dla serwera skutkowało niewielkim swapowaniem (swap ok. 15MB-20MB). Poza tym środowisko nie było praktycznie tuningowane ani optymalizowane. Parametry testowego serwera były niewiele lepsze od dostępnych aktualnie na rynku tabletów czy smartfonów. Mimo tego osiągnięte wyniki są rewelacyjne!

Ładnie,  jak przy 7,867,178

Ładnie,  jak przy 7,867,178 files

cwd is: /
$
real    5m39.337s

Baza MySQL, staram się coś podkręcić.

Może PGSQL?

Nie chciałbym być złośliwy, ale ja "tuning" rozpoczął bym od migracji na PostgreSQL. Wprawdzie 7M plików w jednym zadaniu to sporo, a finalnie liczy się całkowita wielkość bazy danych, w której może być 100M czy 500M plików. Wtedy silnik będzie miał znaczenie.

Radosław Korzeniewski

Modyfiakcja bazy danych

Modyfiakcja bazy danych przyniosła nawet niezły wynik:

 

linux-backup-01 ~ # time echo "restore jobid=529" | bconsole
Connecting to Director 10.9.254.10:9101
1000 OK: 1 beyond-backup-dir Version: 7.0.5 (28 July 2014)
Enter a period to cancel a command.
restore jobid=529
Automatically selected Catalog: PrimaryCatalog
Using Catalog "PrimaryCatalog"
You have selected the following JobId: 529

Building directory tree for JobId(s) 529 ...  +++++++++++++++++++++++++++++++++++++++++++++
7,867,178 files inserted into the tree.

You are now entering file selection mode where you add (mark) and
remove (unmark) files to be restored. No files are initially added, unless
you used the "all" keyword on the command line.
Enter "done" to leave this mode.

cwd is: /
$
real    1m36.503s
user    0m0.016s
sys    0m0.006s

Gratulacje.

Gratuluję! Ciekaw jestem jak to by wyglądało na stuningowanym PostgreSQL?

Radosław Korzeniewski