Zachęcam do zapoznania się z transkrypcją raportu z początku 2020 roku Georgiego Rylova "WAL-G: nowe możliwości i rozwój społeczności"
U maintainerów open-source pojawia się wiele problemów w miarę ich wzrostu. Jak pisać coraz więcej wymaganych funkcji, naprawiać coraz więcej problemów i nadążać za rosnącą liczbą pull requestów? Na przykładzie WAL-G (narzędzie do tworzenia kopii zapasowych dla PostgreSQL) opowiem, jak rozwiązaliśmy te problemy, uruchamiając kurs dotyczący rozwoju open-source na uniwersytecie, co osiągnęliśmy i dokąd będziemy się dalej kierować.

Witam ponownie! Jestem programistą w Yandeksie z Jekaterynburga. Dziś opowiem o WAL-G.
W tytule wykładu nie było powiedziane, że chodzi o kopie zapasowe. Czy ktoś nie wie, co to jest WAL-G? Czy wszyscy wiedzą? Proszę podnieść rękę, kto nie wie. Niesamowite, przyszedłeś na wykład i nie wiesz, o czym on jest.
Pozwólcie, że opowiem, co dziś się wydarzy. Tak się złożyło, że nasza drużyna od dłuższego czasu zajmuje się tworzeniem kopii zapasowych. I to kolejny wykład w serii, w której opowiadamy o tym, jak przechowujemy dane w sposób bezpieczny, niezawodny, wygodny i efektywny.

W poprzednich seriach odbyło się wiele wykładów Andrieja Borodina, Władimira Liskowa. Byliśmy liczną grupą. I wszyscy opowiadaliśmy o WAL-G od wielu lat.
clck.ru/F8ioz —
clck.ru/Ln8Qw —
Ten wykład będzie nieco inny od pozostałych, ponieważ tamte były głównie o części technicznej, a tutaj opowiem, jak zmierzyliśmy się z problemami związanymi z rozwojem społeczności. I jak wymyśliliśmy mały pomysł, który pomaga nam w tym radzić.

Kilka lat temu WAL-G był dość małym projektem, który otrzymaliśmy od Citus Data. I dopiero zaczynaliśmy nad nim pracować. Był rozwijany przez jedną osobę.
I tylko w WAL-G nie było:
- Kopii zapasowej z repliki.
- Brakowało kopii inkrementalnych.
- Nie było kopii WAL-Delta.
- I jeszcze mnóstwo rzeczy nie było.
Na przestrzeni tych kilku lat WAL-G znacznie urosło.

I do roku 2020 wszystko wymienione powyżej już się pojawiło. A do tego doszło jeszcze to, że teraz mamy:
- Ponad 1000 gwiazdek na GitHubie.
- 150 forków.
- Około 15 otwartych PR.
- I jeszcze wielu współpracowników.
- I otwartych problemów nieustannie. A to wszystko pomimo, że dosłownie codziennie wchodzimy tam, coś z tym robimy.

I doszliśmy do wniosku, że ten projekt wymaga więcej naszej uwagi, nawet gdy sami nie potrzebujemy niczego wdrażać dla naszego serwisu Managed Databases w Yandeksie.
I gdzieś jesienią 2018 roku wpadliśmy na pomysł. Zazwyczaj zespół ma kilka sposobów na rozwijanie nowych funkcji lub naprawianie błędów, gdy brakuje rąk do pracy. Na przykład można zatrudnić dodatkowego programistę i mu zapłacić. Albo można wziąć stażystę na jakiś czas i również mu płacić. Ale jest też całkiem spora grupa osób, z których część potrafi już pisać kod. Po prostu nie zawsze wiesz, jakiej jakości jest ten kod.
Pomyśleliśmy i postanowiliśmy spróbować przyciągnąć studentów. Ale studenci nie będą uczestniczyć we wszystkim. Będą robić tylko część pracy. Na przykład będą pisać testy, naprawiać błędy, realizować funkcje, które nie wpływają na podstawową funkcjonalność. Podstawowa funkcjonalność to tworzenie kopii zapasowych i ich przywracanie. Jeśli dojdzie do błędu w tworzeniu kopii zapasowej, to stracimy dane. A nikt tego, oczywiście, nie chce. Wszyscy chcą, aby wszystko było bardzo niezawodne. Dlatego kod, któremu ufamy mniej niż swojemu własnemu, oczywiście nie chcemy tam wpuszczać. To znaczy, jakikolwiek niekrytyczny kod – to, co chcielibyśmy otrzymać od naszych dodatkowych rąk do pracy.
W jakich warunkach przyjmowany jest PR studenta
- Mają obowiązek pokrywać swój kod testami. Wszystko musi przechodzić w CI.
- I przechodzimy również przez 2 recenzje. Jedna od Andrieja Borodina i jedna moja.
- Dodatkowo, aby sprawdzić, że to nie zepsuje nic w naszym serwisie, osobno wrzucam składnię z tym commitem. I sprawdzamy w testach end-to-end, że nic nam się nie psuje.
Specjalny kurs Open Source

Chciałbym pokrótce opisać, po co to potrzebne i dlaczego, moim zdaniem, to świetny pomysł.
Dla nas korzyści są oczywiste:
- Zyskujemy dodatkowe ręce.
- I poszukujemy kandydatów do zespołu wśród zdolnych studentów, którzy piszą dobry kod.
Jaka jest korzyść dla studentów?
Może być mniej oczywista, ponieważ studenci przynajmniej nie dostają pieniędzy za kod, który piszą, a jedynie oceny na zaliczeniu.
Zapytałem ich o to. I z ich słów:
- Doświadczenie jako kontrybutor Open Source.
- Zdobycie wpisu w CV.
- Zaprezentowanie się i przejście rozmowy kwalifikacyjnej w Yandexie.
- Stanie się uczestnikiem GSoC.
- +1 specjalny kurs dla tych, którzy chcą pisać kod.
Nie będę opowiadać o tym, jak był zorganizowany kurs. Powiem tylko, że WAL-G był głównym projektem. Ponadto w ten kurs włączyliśmy takie projekty jak Odyssey, PostgreSQL i ClickHouse.
Zadania były nie tylko w tym kursie, ale także wydawali dyplomy i prace semestralne.
A co z korzyściami dla użytkowników?
Przejdźmy teraz do części, która najbardziej Was interesuje. Jaki z tego macie pożytek? Pożytek jest taki, że studenci naprawili wiele błędów. I zrealizowali prośby dotyczące funkcji, które prosiliście nas o wdrożenie.
Pozwólcie, że opowiem o rzeczach, które długo chcieliście mieć, a które zostały zrealizowane.

Wsparcie dla tablespaces. Tablespaces w WAL-G były oczekiwane prawdopodobnie od momentu wydania WAL-G, ponieważ WAL-G jest następcą innego narzędzia do tworzenia kopii zapasowych WAL-E, które obsługiwało kopie zapasowe baz danych z tablespaces.
Przypomnę krótko, czym to jest i dlaczego jest to potrzebne. Zazwyczaj wszystkie dane Postgres zajmują jeden katalog w systemie plików, który nazywamy katalogiem bazowym. Ten katalog już zawiera wszystkie pliki i podkatalogi potrzebne dla Postgres.
Tablespaces to katalogi, w których znajdują się dane Postgres, ale nie leżą one poza katalogiem bazowym. Na slajdzie widać, że tablespaces znajdują się poza katalogiem bazowym.

Jak to wygląda dla samego Postgresa? W katalogu bazowym znajduje się osobny podkatalog pg_tblspc. W nim są symlinkami wskazującymi na katalogi, w których faktycznie znajdują się dane Postgres poza katalogiem bazowym.

Kiedy z tego korzystacie, te komendy mogą wyglądać tak. Tzn. tworzycie tabelę w określonym tablespace i sprawdzacie, gdzie ona się teraz znajduje. Oto te dwie ostatnie linie, dwie ostatnio wywołane komendy. Widać, że jest jakiś ścieżka. Ale tak naprawdę - to nie jest prawdziwa ścieżka. To jest ścieżka z prefiksem katalogu bazowego do tablespace. I skądś jest to powiązane symlinkiem, który prowadzi do Waszych rzeczywistych danych.
Nie wykorzystujemy tego w naszym zespole, ale to było używane przez wielu innych użytkowników WAL-E, którzy pisali do nas, że chcą przenieść się na WAL-G, ale to im przeszkadzało. Teraz to jest wspierane.

Inna funkcja, którą przyniósł nam nasz kurs specjalistyczny, to catchup. O catchup wiedzą ludzie, którzy prawdopodobnie bardziej pracowali z Oracle niż z Postgres.
Krótko o tym, czym to jest. Tak może wyglądać topologia klastra w naszym serwisie. Mamy mastera. Jest replikacja, która streamuje z niego dziennik zapisów. I replikacja informuje mastera, na którym LSN się aktualnie znajduje. Równolegle może odbywać się archiwizacja dziennika. Oprócz archiwizacji, w chmurze przesyłane są również kopie zapasowe. I wysyłane są kopie różnicowe.
Jaki może być problem? Kiedy macie dość dużą bazę danych, może okazać się, że replikacja zaczyna znacznie odstawać od mastera. I odstawienie jest tak duże, że już nigdy nie może go dogonić. Zazwyczaj ten problem trzeba jakoś rozwiązać.
Najprostszym sposobem jest usunięcie replikacji i ponowne jej włączenie, ponieważ nigdy nie dogoni mastera, a trzeba zająć się problemem. Ale to dość czasochłonne, ponieważ przywracanie całej kopii zapasowej bazy o pojemności 10 TB zajmuje naprawdę dużo czasu. Chcemy to zrealizować jak najszybciej, gdy pojawią się takie problemy. I właśnie do tego służy catchup.
Catchup pozwala wykorzystać kopie różnicowe, które są przechowywane w chmurze. Mówisz, na którym LSN jest aktualnie odstająca replikacja i podajesz go w poleceniu catchup, aby utworzyć kopię różnicową między tym LSN a LSN, na którym znajduje się Twój klaster. Po tym przywracasz tę kopię zapasową na replikację, która odstawała.
Inne bazy
Studenci dostarczyli nam także wiele funkcji. Ponieważ w Yandex zajmujemy się nie tylko Postgres, mamy także MySQL, MongoDB, Redis, ClickHouse, w pewnym momencie potrzebowaliśmy, abyśmy mogli robić kopie zapasowe z możliwością odzyskiwania danych w dowolnym punkcie czasu dla MySQL i aby była możliwość przesłania ich do chmury.
Chcieliśmy to robić w sposób podobny do tego, który oferuje WAL-G. Postanowiliśmy przeprowadzić eksperymenty i zobaczyć, jak to wszystko będzie wyglądać.
Na początku, nie rozdzielając tej logiki w forku, napisaliśmy kod. Zobaczyliśmy, że mamy jakąś działającą modelę i to może zadziałać. Potem pomyśleliśmy, że naszą główną społecznością są postgresowcy, którzy używają WAL-G. Dlatego trzeba jakoś podzielić te części. To znaczy, gdy poprawiamy kod dla Postgresa, nie łamiemy MySQL, a gdy poprawiamy MySQL, nie łamiemy Postgresa.

Pierwszym pomysłem na to, jak to podzielić, było zastosowanie tego samego podejścia, które jest wykorzystywane w rozszerzeniach PostgreSQL. W rzeczywistości, aby zrobić kopię zapasową MySQL, musisz zainstalować jakąś dynamiczną bibliotekę.
Jednak od razu widać asymetrię tego podejścia. Kiedy robisz kopię zapasową Postgresa, instalujesz normalne narzędzie do tworzenia kopii zapasowych dla Postgresa i wszystko działa świetnie. A w przypadku MySQL okazuje się, że instalujesz narzędzie do robienia kopii zapasowych dla Postgresa, a dodatkowo musisz zainstalować dynamiczną bibliotekę dla MySQL. To brzmi trochę dziwnie. My też tak pomyśleliśmy i postanowiliśmy, że to nie jest rozwiązanie, którego szukamy.
Różne zbiory dla Postgresa, MySQL, MongoDB, Redis
Ale to pozwoliło nam, jak sądzimy, znaleźć właściwe rozwiązanie – wydzielić różne zbiory dla różnych baz. To umożliwiło izolację logiki związanej z kopiami zapasowymi różnych baz danych, które będą korzystać ze wspólnego API, które realizuje WAL-G.

To jest ta część, którą napisaliśmy sami – zanim daliśmy studentom zadania. To znaczy, to jest dokładnie ta część, gdzie mogli zrobić coś nie tak, więc postanowiliśmy, że lepiej będzie, jeśli zrobimy to sami, a wszystko będzie w porządku.

Po tym wystawiliśmy zadania. Od razu zostały podjęte. Od studentów wymagano wsparcia trzech baz.
To MySQL, które robimy kopię zapasową przy użyciu WAL-G w ten sposób już od ponad roku.
A teraz MongoDB zbliża się do produkcji, jest tam dopracowywane. W zasadzie to my napisaliśmy szkielet dla tego wszystkiego. Potem studenci stworzyli jakieś działające rzeczy. A my je doprowadzamy do takiego stanu, który możemy przyjąć w naszej produkcji.
Te zadania nie wyglądały tak, że studenci musieli napisać pełne narzędzia do tworzenia kopii zapasowych dla każdej z tych baz. Nie mieliśmy takiego problemu. Naszym problemem było to, że chcieliśmy odzyskiwania w punkcie w czasie i chcieliśmy robić kopie zapasowe do chmury. Poprosiliśmy studentów o napisanie jakiegoś kodu, który to rozwiąże. Studenci skorzystali z już istniejących narzędzi do tworzenia kopii zapasowych, które w jakiś sposób robiły kopie zapasowe, a potem łączyli to wszystko z WAL-G, który przesyłał to do chmury. A także dodawali do tego odzyskiwanie w punkcie w czasie.

Co jeszcze przynieśli studenci? Wnieśli do WAL-G wsparcie szyfrowania Libsodium.
Ponadto pojawiły się polityki przechowywania kopii zapasowych. Teraz kopie zapasowe można oznaczać jako permanentne. I w jakiś sposób wygodniej dla twojej usługi automatyzować proces ich przechowywania.

Co wyszło w wyniku tego eksperymentu?
Na kurs pierwotnie zarejestrowało się ponad 100 osób. Na początku nie powiedziałem, że uniwersytet w Jekaterynburgu to Ural Federalny Uniwersytet. Tam wszystko ogłosiliśmy. 100 osób się zarejestrowało. Rzeczywiście coś zaczęło robić znacznie mniej, około 30 osób.
Jeszcze mniej osób ukończyło kurs, ponieważ trzeba było napisać testy do istniejącego kodu oraz naprawić jakiś błąd lub stworzyć jakąś funkcję. I część studentów mimo wszystko ukończyła kurs.
Na ten moment studenci naprawili około 14 problemów, zrealizowali 10 funkcji różnej wielkości. I, jak mi się wydaje, to pełnoprawna wymiana jednego lub dwóch programistów.
Oprócz tego wydawaliśmy dyplomy i prace kursowe. 12 osób otrzymało dyplomy. 6 z nich zdało już obronę na "5". Pozostali jeszcze nie obronili, ale myślę, że i im pójdzie dobrze.
Plany na przyszłość
Jakie mamy plany na przyszłość?
Przynajmniej te prośby o funkcje, które już słyszeliśmy od użytkowników i chcemy je zrealizować. To:
- Śledzenie poprawności śledzenia osi czasu w archiwum kopii zapasowych klastra HA. Można to zrobić za pomocą WAL-G. I myślę, że znajdą się studenci, którzy się tym zajmą.
- Już mamy odpowiedzialną osobę za przenoszenie kopii zapasowych i WAL-a między chmurami.
- Niedawno opublikowaliśmy pomysł, że możemy jeszcze bardziej przyspieszyć WAL-G za pomocą dekompresji przyrostowych kopii zapasowych bez nadpisywania stron i optymalizacji archiwów, które tam wysyłamy.
Możecie się nimi podzielić tutaj
Po co było to wystąpienie? Chodziło o to, że obecnie, oprócz nas czterech osób, które wspierają ten projekt, mamy dodatkowe ręce, których jest dość dużo. Szczególnie, jeśli napiszecie im na prywatną wiadomość. I jeśli tworzycie kopie zapasowe swoich danych i robicie to za pomocą WAL-G lub chcielibyście przejść na WAL-G, to wasze życzenia możemy dość łatwo uwzględnić.

To jest kod QR i link. Możecie po nich przejść i napisać wszystkie swoje sugestie. Na przykład, jeśli nie naprawiamy jakiegoś błędu, lub jakąś funkcję bardzo chcecie, ale z jakiegoś powodu nie ma jej jeszcze w żadnej usłudze backupowej, w tym także w naszej. Koniecznie o tym napiszcie.

Pytania
Witaj! Dziękuję za prezentację! Mam pytanie dotyczące WAL-G, ale nie w kontekście Postgresa. WAL-G wykonuje kopie zapasowe MySQL i inicjuje dodatkową kopię zapasową. Jeśli weźmiemy pod uwagę nowoczesne instalacje na CentOS i jeśli zainstalujesz MySQL za pomocą polecenia yum install, to zainstalujesz MariDB. Od wersji 10.3 dodatkowa kopia zapasowa nie jest wspierana, wspierana jest kopia zapasowa MariDB. Jak sobie z tym radzicie?
Na chwilę obecną nie próbowaliśmy robić kopii zapasowych MariDB. Mieliśmy zapytania o wsparcie dla FoundationDB, ale ogólnie rzecz biorąc, jeśli jest takie zapytanie, to możemy znaleźć ludzi, którzy się tym zajmą. To nie zajmuje tak dużo czasu i nie jest tak trudne, jak mi się wydaje.
Dzień dobry! Dziękuję za prezentację! Pytanie dotyczące potencjalnie nowych funkcji. Czy jesteście gotowi, aby uruchomić WAL-G z taśmami, aby można było robić kopie zapasowe na taśmy?
Chodzi o kopię zapasową w magazynie taśmowym, prawda?
Tak.
Jest tam Andriej Borodin, który może lepiej odpowiedzieć na to pytanie.
(Andriej) Tak, dziękuję za pytanie! Mieliśmy zapytanie o przeniesienie kopii zapasowej z chmury na taśmę. I dla tego przeniesieniem między chmurami. Ponieważ przeniesienie między chmurami to pewnego rodzaju zgeneralizowana wersja przeniesienia na taśmę. Ponadto mamy rozszerzalną architekturę w zakresie magazynów. A tak przy okazji, wiele magazynów zostało stworzonych przez studentów. I jeśli napiszesz magazyn dla taśmy, to na pewno będzie wspierany. Jesteśmy gotowi rozpatrzyć pull request. Trzeba napisać plik, przeczytać plik. Jeśli te rzeczy zrobi się w Go, to zazwyczaj zajmuje to 50 linii kodu. Wtedy w WAL-G będzie obsługiwany napęd taśmowy.
Dziękuję za prezentację! Interesujący proces rozwoju. Kopia zapasowa to poważna część funkcjonalności, która powinna być solidnie testowana. Kiedy implementowaliście funkcjonalność dla nowych baz danych, testy również pisali studenci, czy sami napisaliście testy, a potem przekazaliście realizację studentom?
Testy również pisali studenci. Ale studenci pisali głównie dla takich funkcji, jak nowe bazy. Pisywali testy integracyjne. I pisali testy jednostkowe. Jeśli testy integracyjne przechodzą, to znaczy, że w tej chwili – to scenariusz, który wykonujecie ręcznie, albo robi to za Was np. cron. To znaczy, że scenariusz jest bardzo zrozumiały.
Studenci nie mają zbyt dużego doświadczenia. Ile czasu zajmuje przeglądanie?
Tak, recenzja zajmuje dość dużo czasu. Tzn. zwykle, kiedy przychodzi kilku commitujących i mówią, że zrobiłem to, zrobiłem tamto, muszę pomyśleć i przeznaczyć gdzieś pół dnia na zrozumienie tego, co tam napisali. Trzeba dokładnie czytać kod. Oni nie przechodzili rozmowy kwalifikacyjnej. Nie znamy ich zbyt dobrze, więc to zajmuje znaczną ilość czasu.
Dziękuję za referat! Wcześniej Andriej Borodin mówił, że archive_command w WAL-G powinien być wywoływany bezpośrednio. Ale w przypadku jakiegoś klastra patrona, potrzebujemy dodatkowej logiki do określenia węzła, z którego należy wysyłać WAL-e. Jak wy rozwiązujecie ten problem?
W czym macie tutaj problem? Załóżmy, że macie synchronizowaną replikę, z której robicie kopię zapasową? Czy coś innego?
(Andriej) Rzecz w tym, że rzeczywiście WAL-G zakłada użycie bez otaczających go skryptów powłoki. Jeśli czegoś brakuje, to dodajmy logikę, która powinna być wewnątrz WAL-G. Jeśli chodzi o archiwizację, uważamy, że powinna być z aktualnego mastera w klastrze. Archiwizacja z repliki to zły pomysł. Mogą występować różne scenariusze z problemami. W szczególności problemy z archiwizacją linii czasowych i dodatkowych informacji. Dziękuję za pytanie!
(Uaktualnienie: Zrezygnowaliśmy z otoczek skryptów powłoki) )
Dobry wieczór! Dziękuję za referat! Zainteresowała mnie funkcja catchup, o której opowiadałeś. Mieliśmy sytuację, w której replikacja opóźniała się i nie mogła nadążyć. A w dokumentach WAL-G nie znalazłem opisu tej funkcji.
Catchup pojawił się dosłownie w okolicach 20 stycznia 2020 roku. Może warto lepiej popracować nad dokumentacją. Sami ją piszemy i nie robimy tego idealnie. Może warto zacząć wymagać od studentów, aby również ją pisali.
Czy to już w wydaniu?
Pull request został już połączony, tzn. sprawdziłem to. Próbowałem to na testowym klastrze. Na razie nie mieliśmy sytuacji, w której moglibyśmy to sprawdzić na faktycznym przykładzie.
Kiedy można się tego spodziewać?
Nie wiem. Poczekajcie miesiąc, wtedy na pewno to sprawdzimy.
Źródło: habr.com
