Czy powinniśmy montować z data = writeback i barierą = 0 na ext3?

13

Uruchomiliśmy serwer na maszynie wirtualnej w firmie hostingowej i właśnie zapisaliśmy się na dedykowanego hosta (AMD Opteron 3250, 4 rdzenie, 8 GB pamięci RAM, 2 x 1 TB w oprogramowaniu RAID, ext3).

Podczas przeprowadzania testów wydajności zauważyliśmy, że niektóre transakcje SQLite (kombinacja wstawiania, usuwania i / lub aktualizacji) zajmowały 10–15 razy dłużej niż na moim MacBooku Pro 2010.

Po wielu googlingach i czytaniu, musimy spojrzeć na opcje montowania, które były:

    data=ordered,barrier=1

Przeprowadziliśmy eksperymenty i uzyskaliśmy najlepszą wydajność

    data=writeback,barrier=0

Przeczytałem o nich i rozumiem podstawy tego, co robią, ale nie mam poczucia, czy to dobry pomysł, abyśmy tak działali?

pytania

Czy powyższą konfigurację można nawet rozważyć w przypadku hostowanej usługi?

Gdybyśmy mieli awarię zasilania lub poważną awarię, moglibyśmy stracić dane lub pliki uszkodzone. Gdybyśmy robili migawki bazy danych co 15 minut, mogłoby to złagodzić sytuację, ale baza danych może nie zostać zsynchronizowana podczas robienia migawki. W jaki sposób (możemy?) Zapewnić integralność takiej migawki?

Czy są inne opcje, które powinniśmy rozważyć?

Dzięki

NeilB
źródło
W grę wchodzi wiele czynników. Czy spodziewasz się wielu trudnych awarii? Czy masz zasilacz UPS (lub coś podobnego) podłączony do hostowanej maszyny? Czy przeprowadzałeś testy porównawcze z innymi systemami plików (np. Ext4, XFS itp.)? Czy możesz kontrolować (dezaktywować) pamięć podręczną dysku twardego? Jak skonfigurowałeś oprogramowanie RAID? Czy dysk HDD jest właściwie wyrównany (jeśli masz bloki 4K)?
Huygens
Nie oczekujemy wielu ciężkich awarii. Nie mamy UPS. Specyfikacja maszyny była standardem „od półki” od firmy hostingowej, więc: nie porównaliśmy innych FS, to właśnie otrzymaliśmy ext3. Nie wiem na temat pamięci podręcznej HDD, zajrzy do tego i podobnie do wyrównania RAID i HDD. Dzięki.
NeilB,
Innym pytaniem, które zapomniałem, jest to, ile historii możesz sobie pozwolić na utratę? A może nie stać Cię na zgubę? Uwaga: SQLite obsługuje migawkę lub innymi słowy tworzenie kopii zapasowej działającej bazy danych. sqlite.org/backup.html
Huygens,
Jaka jest twoja wersja jądra? Bariery są honorowane przez md od 2.6.33, a nie w poprzedniej wersji jądra.
Huygens,
uname -r zgłasza „2.6.32-220.2.1.el6.x86_64”. Co to jest „md”? Jeśli bariery nie są honorowane w tej wersji jądra, dlaczego zauważyłem poprawę wydajności po wyłączeniu barier?
NeilB

Odpowiedzi:

15

Pierwsza rada
Jeśli nie możesz sobie pozwolić na utratę jakichkolwiek danych (mam na myśli to, że użytkownik wprowadził nowe dane, jeśli nie można ich utracić w najbliższych sekundach) i ponieważ nie masz czegoś takiego jak UPS, to nie usunęłbym bariery zapisu, nie przejdę też na zapis zwrotny.

Usuwanie barier zapisu
Jeśli usuniesz barierę zapisu, to w przypadku awarii lub utraty zasilania system plików będzie musiał wykonać fsck, aby naprawić strukturę dysku (zwróć uwagę, że nawet przy włączonej barierze, większość systemów plików z dziennikiem nadal wykona fsck nawet choć powtórka dziennika powinna być wystarczająca). Podczas usuwania bariery zapisu zaleca się, jeśli to możliwe, usunięcie buforowania dysku (sprzętowego), co pomaga zminimalizować ryzyko. Powinieneś jednak porównać wpływ takiej zmiany. Możesz wypróbować to polecenie (jeśli sprzęt je obsługuje) hdparm -W0 /dev/<your HDD>.
Zauważ, że ext3 używa 2 barier dla zmiany metadanych, podczas gdy ext4 używa tylko jednej, gdy używasz opcji montowania journal_async_commit.

Chociaż Ted T'so wyjaśnił, dlaczego niektóre przypadki uszkodzenia danych miały miejsce we wczesnych dniach ext3 (bariery były domyślnie WYŁĄCZONE aż do jądra 3.1 ), dziennik jest umieszczony w taki sposób, że chyba że nastąpi zawijanie dziennika dziennika (dziennik jest dziennikiem cyklicznym) dane są zapisywane na dysk w bezpiecznej kolejności - najpierw dziennik, dane drugi - nawet przy twardym dysku obsługuje zmianę kolejności zapisów.
Zasadniczo niefortunne byłoby, że podczas zawijania dziennika dziennika nastąpi awaria systemu lub utrata zasilania. Musisz jednak zachować data=ordered. Spróbuj dodatkowo przeprowadzić testy porównawcze data=ordered,barrier=0.

Jeśli możesz sobie pozwolić na utratę kilku sekund danych, możesz aktywować obie opcje, data=writeback,barrier=0ale następnie spróbuj również eksperymentować z commit=<nrsec>parametrem. Sprawdź instrukcję obsługi tego parametru tutaj . Zasadniczo podajesz liczbę sekund, czyli okres, w którym system plików ext3 zsynchronizuje swoje dane i metadane.
Możesz także spróbować pogłaskać i przetestować niektóre tunery jądra dotyczące brudnych stron (tych, które wymagają zapisu na dysk), jest tutaj dobry artykuł , który wyjaśnia wszystko o tych tunelach i jak się nimi bawić.

Podsumowanie dotyczące barier
Należy porównać kilka innych kombinacji tunerów:

  1. Używaj data=writeback,barrier=0w połączeniu zhdparm -W0 /dev/<your HDD>
  2. Posługiwać się data=ordered,barrier=0
  3. Użyj data=writeback,barrier=0w połączeniu z inną opcją montowania commit=<nrsec>i wypróbuj różne wartości dla nrsec
  4. Użyj opcji 3. i spróbuj dalej przestrajać na poziomie jądra w odniesieniu do brudnych stron.
  5. Skorzystaj z sejfu data=ordered,barrier=1, ale wypróbuj inne elementy dostrajające: w szczególności windę systemu plików (CFQ, Deadline lub Noop) i odpowiednie elementy dostrajające.

Rozważenie przejścia na ext4 i przetestowanie go
Jak wspomniano, ext4 wymaga mniejszej bariery niż ext3 do zapisu. Ponadto ext4 obsługuje zakresy, które w przypadku dużych plików mogą przynieść lepszą wydajność. Jest to więc rozwiązanie, które warto zbadać, zwłaszcza że łatwo jest migrować z ext3 na ext4 bez ponownej instalacji: oficjalna dokumentacja ; Zrobiłem to na jednym systemie, ale korzystając z tego przewodnika Debiana . Ext4 jest naprawdę stabilny od jądra 2.6.32, więc można go bezpiecznie używać w produkcji.

Ostatnie rozważanie
Ta odpowiedź jest daleka od ukończenia, ale zapewnia wystarczającą ilość materiałów do rozpoczęcia badania. Jest to tak bardzo zależne od wymagań (na poziomie użytkownika lub systemu), że trudno jest uzyskać jednoznaczną odpowiedź, przepraszam za to.

Huygens
źródło
Dzięki - wiele przydatnych rzeczy. Przeczytałem już dokument ext3 na kernel.org i próbowałem zmienić zatwierdzenie, ale nie miałem pojęcia, co było dużą wartością. Ustaw na 15 zamiast 5 sekund Nie widziałem żadnych zmian. Zrobię więcej testów porównawczych, aby objąć zasugerowane przez ciebie permutacje. Dzięki jeszcze raz.
NeilB
To był dobry pomysł, aby spróbować wydłużyć czas zatwierdzania, zachowując bezpieczne wartości domyślne! Możliwe jest, że SQLite jest opróżnianiem / synchronizacją, co może wyjaśniać, dlaczego nie zmierzyłeś żadnej zmiany wydajności za pomocą opcji zatwierdzenia.
Huygens
@ NeilB natknął się na następujące artykuły: 1. sqlite.org/draft/lockingv3.html szukaj ext3w nim. Daje to być może łatwiejsze do zrozumienia (lub uproszczone) wyjaśnienie tego, do czego próbowałem się odnieść w mojej odpowiedzi. 2. sqlite.1065341.n5.nabble.com/… możesz spróbować zachować bezpieczne ustawienia domyślne ext3 (uporządkowane + bariera), ale usuń synchronizację w SQLite. Wkrótce zaktualizuję moją odpowiedź dotyczącą tego drugiego aspektu.
Huygens
Dzięki za te. Zaraz opracuję wszystkie permutacje i przeprowadzę z nimi testy wydajności. Na początku próbowałem z synchronizacją w SQLite i uzyskałem dobre wyniki. Najpierw muszę napisać kod, aby zebrać zakres danych dla różnych kombinacji operacji zapisu. Zamieszczę tutaj streszczenie, ale jeśli chcesz więcej szczegółów, jestem neil w bowers dot com.
NeilB
10

Uwaga: poniżej mogą występować nieścisłości. Nauczyłem się o wielu z tych rzeczy, więc weź to ze szczyptą soli. To jest dość długie, ale możesz po prostu odczytać parametry, z którymi graliśmy, a następnie przejść do Wniosku na końcu.

Istnieje wiele warstw, w których możesz się martwić wydajnością zapisu SQLite:

różne poziomy myślenia o wydajności

Spojrzeliśmy na te wyróżnione pogrubioną czcionką. Konkretne parametry to

  • Pamięć podręczna zapisu dysku. Nowoczesne dyski mają pamięć podręczną RAM, która służy do optymalizacji zapisu na dysku w stosunku do wirującego dysku. Po włączeniu tej opcji dane mogą być zapisywane w blokach poza kolejnością, więc jeśli nastąpi awaria, możesz otrzymać częściowo zapisany plik. Sprawdź ustawienie za pomocą hdparm -W / dev / ... i ustaw je za pomocą hdparm -W1 / dev / ... (aby je włączyć, i -W0, aby je wyłączyć).
  • bariera = (0 | 1). Wiele komentarzy online mówiących: „jeśli uruchamiasz z barierą = 0, nie włączaj buforowania zapisu na dysku”. Dyskusję na temat barier można znaleźć na stronie http://lwn.net/Articles/283161/
  • data = (dziennik | zamówiony | zapis zwrotny). Zajrzyj na http://www.linuxtopia.org/HowToGuides/ext3JournalingFilesystem.html, aby uzyskać opis tych opcji.
  • zatwierdzenie = N. Informuje ext3, aby synchronizował wszystkie dane i metadane co N sekund (domyślnie 5).
  • Pragnienie synchroniczne SQLite = ON | POZA. Po włączeniu SQLite zapewni, że transakcja zostanie „zapisana na dysk” przed kontynuowaniem. Wyłączenie tego powoduje, że inne ustawienia są w dużej mierze nieistotne.
  • SQLite pragma cache_size. Kontroluje, ile pamięci zajmie SQLite na pamięć podręczną w pamięci. Wypróbowałem dwa rozmiary: jeden, w którym cała baza danych zmieściłaby się w pamięci podręcznej, i jeden, w którym pamięć podręczna była o połowę większa od wielkości bazy danych.

Przeczytaj więcej o opcjach ext3 w dokumentacji ext3 .

Przeprowadziłem testy wydajności dla wielu kombinacji tych parametrów. Identyfikator to numer scenariusza, o którym mowa poniżej.

scenariusze, które próbowałem

Zacząłem od uruchomienia z domyślną konfiguracją na moim komputerze jak w scenariuszu 1. Scenariusz 2 jest tym, co uważam za „najbezpieczniejszy”, a następnie wypróbowałem różne kombinacje, w stosownych przypadkach / monitowane. Prawdopodobnie najłatwiej to zrozumieć na mapie, którą ostatecznie wykorzystałem:

odwzorować scenariusze odnoszące się do parametrów

Napisałem skrypt testowy, który przeprowadził wiele transakcji, z wstawkami, aktualizacjami i usunięciami, wszystkie na tabelach z tylko INTEGER, tylko TEXT (z kolumną id) lub mieszane. Uruchomiłem to kilka razy w każdej z powyższych konfiguracji:

wykres pokazujący czasy dla scenariuszy

Dolne dwa scenariusze to # 6 i # 17, które mają „pragma synchronous = off”, więc nic dziwnego, że były najszybsze. Kolejna grupa trzech to # 7, # 11 i # 19. Te trzy są podświetlone na niebiesko na „mapie konfiguracji” powyżej. Zasadniczo konfiguracja obejmuje pamięć podręczną zapisu na dysku, barierę = 0 i zestaw danych do czegoś innego niż „dziennik”. Zmiana zatwierdzenia między 5 sekund (# 7) a 60 sekund (# 11) wydaje się nie mieć większego znaczenia. W tych testach nie było chyba żadnej różnicy między danymi = uporządkowanymi a danymi = zapisywanie zwrotne, co mnie zaskoczyło.

Test mieszanej aktualizacji jest środkowym pikiem. Istnieje zestaw scenariuszy, które są wyraźnie wolniejsze w tym teście. Wszystkie z danymi = dziennik . W przeciwnym razie nie ma wiele między innymi scenariuszami.

Miałem kolejny test synchronizacji, w którym wykonano bardziej heterogeniczną mieszankę wstawek, aktualizacji i usunięć dla różnych kombinacji typów. Zajęło to dużo dłużej, dlatego nie umieściłem go na powyższej fabule:

typy mieszane i wstaw / aktualizuj / usuń

Tutaj możesz zobaczyć, że konfiguracja zapisu zwrotnego (# 19) jest nieco wolniejsza niż w zamówionych (# 7 i # 11). Spodziewałem się, że zapis będzie nieco szybszy, ale być może zależy to od twoich wzorców zapisu, a może po prostu jeszcze nie czytałem wystarczająco dużo na ext3 :-)

Różne scenariusze były nieco reprezentatywne dla operacji wykonywanych przez naszą aplikację. Po wybraniu krótkiej listy scenariuszy przeprowadziliśmy testy czasowe z niektórymi naszymi automatycznymi zestawami testów. Były zgodne z powyższymi wynikami.

Wniosek

  • Popełnić parametr wydawało się trochę zmienić, tak, że wyjeżdżamy na 5s.
  • Idziemy z pamięcią podręczną zapisu na dysku, barierą = 0 i danymi = uporządkowanymi . Przeczytałem kilka rzeczy online, które uważały, że jest to zła konfiguracja, a inne, które wydawały się uważać, że powinno to być domyślne w wielu sytuacjach. Najważniejsze jest to, że podejmujesz świadomą decyzję, wiedząc, jakie kompromisy podejmujesz.
  • Nie będziemy używać synchronicznej pragmy w SQLite.
  • Ustawienie pragmy SQLite cache_size, aby baza danych zmieściła się w pamięci, poprawiła wydajność niektórych operacji, zgodnie z oczekiwaniami.
  • Powyższa konfiguracja oznacza, że ​​podejmujemy nieco większe ryzyko. Będziemy używać SQLite Backup API, aby zminimalizować ryzyko awarii dysku przy częściowym zapisie: robienie migawki co N minut i utrzymywanie ostatniego M. Testowałem ten interfejs API podczas testów wydajności i daje nam to pewność, że pójdziemy tą drogą.
  • Gdybyśmy nadal chcieli więcej, moglibyśmy popatrzeć na zabawę z jądrem, ale poprawiliśmy wszystko bez wchodzenia tam.

Dzięki @Huygens za różne wskazówki i wskazówki.

NeilB
źródło