Na temat tego, jak skonfigurować replikację w MySQL można znaleźć w internecie sporo informacji. Z resztą, na tym blogu taki krótki opis także się pojawi. Tym razem jednak wspomnę kilka słów o tym, jak działa mechanizm replikacji w MySQL. Replikacja to jeden z najprostszych sposobów aby zapewnić sobie skalowalność aplikacji. Ogólna idea jest taka, że mamy jeden serwer – master, na którym wykonywane są wszystkie zapytania modyfikujące dane. Modyfikacje te przenoszone są przez replikację na drugi serwer (albo serwery, może ich być więcej) – slave. W efekcie mamy dwie, teoretycznie identyczne kopie bazy danych, na których możemy wykonywać zapytania typu SELECT. Jak to wygląda w praktyce?
MySQL do przenoszenia zmian z mastera na slave wykorzystuje binlogi. Po skonfigurowaniu replikacji, na serwerach uruchamiane są dodatkowe wątki. Na masterze jest to jeden wątek na każdy serwer slave. Wątek ten zajmuje się wysyłaniem do slave nowo powstałych binlogów. Jak wiemy, MySQL wykorzystuje binlogi do logowania zapytań, które modyfikowały dane, tak więc wykorzystanie tych logów do replikacji jest rozwiązaniem, które samo się nasuwa. Na każdym serwerze slave tworzone są dwa wątki. Pierwszy, tak zwany I/O thread, zajmuje się odbieraniem binlogów przesyłanych przez mastera, zapisywaniem ich na dysku i zgłaszaniem zapotrzebowania na kolejną partię. Logi te lądują na slave jako relay-log, ich struktura jest dokładnie taka sama jak binlogów. Drugi z wątków, SQL thread, zajmuje się parsowaniem relay-logów i wykonywaniem zapisanych tam modyfikacji.
Tu pojawia się pierwszy haczyk, który uważni czytelnicy być może już zauważyli. Modyfikacje danych na slave realizuje jeden wątek. Odczytuje on z logów transakcję za transakcją i wykonuje. Na masterze natomiast zapytania modyfikujące dane wykonywane są normalnie, czyli w wielu wątkach na raz. Efektem tego jest mniejsza zdolność serwera slave do przetworzenia modyfikacji. Po prostu, przy identycznej konfiguracji sprzętowej obu serwerów, master może sobie radzić z obciążeniem (bo INSERTy czy inne UPDATE lecą w kilkudziesięciu wątkach na raz), slave natomiast, z jednym wątkiem do dyspozycji, nie będzie w stanie nadążyć z wykonaniem wszystkich modyfikacji w tym samym czasie, co na masterze i w efekcie zawartość bazy na slave będzie odbiegać o pewien czas od tego, co jest na masterze. Jeśli tego typu sytuacja jest przejściowa, a potem obciążenie mastera się zmniejszy, to być może da się to zaakceptować. Slave chwilowo odstaje, ale jak zmniejszy się obciążenie, to nadrobi zaległości. Gorzej, jeśli taki stan jest stanem permanentnym. W takiej sytuacji jedyną opcją jest rozbicie mastera na dwa, ewentualnie zakupienie mocniejszego sprzętu na slave.
Z powyższego haczyka wynika kolejny. Wbrew temu, co niektórzy sądzą, replikacja MySQL nie jest sposobem na skalowanie zapisów. Jeśli serwer nie radzi sobie z ilością modyfikacji danych, nie da się tego rozwiązać przy pomocy replikacji. Da się przenieść wszelkie inne zapytania na serwery slave, ale jeśli master jest przeciążony samymi zapytaniami modyfikującymi dane, to jedyną dostępną wtedy opcją jest rozbicie danych na kilka serwerów (sharding). Zastosowanie replikacji master – master nie jest (powtarzam, nie jest!) sposobem na skalowanie zapisów. Wręcz przeciwnie. Popatrzmy na to logicznie. Mamy serwer A, obciążony na 100%. Dokładamy serwer B, rozbijamy zapisy na dwa. W efekcie mamy: serwer A – 50% obciążenia + replikowane 50% obciążenia z serwera B. Serwer B – 50% obciążenia + replikowane 50% obciążenia z serwera A. W dodatku, te replikowane 50% obciążenia realizowane jest na gorszych warunkach, bo przy pomocy tylko jednego wątku.
To znaczy, owszem, można w ten sposób, do pewnego stopnia zmniejszyć chwilowe obciążenie dysku. Wiąże się to z tym właśnie, że modyfikacje replikowane wykonywane są w jednym wątku. W efekcie wykonują się dłużej i mniej agresywnie konkurują o zasoby dyskowe. Takie coś można zastosować jeśli obciążenie nie jest równomierne w ciągu dnia – wątek SQL musi mieć szansę nadążyć z replikacją (czyli serwer w perspektywie całodniowej nie jest obciążony w 100%). Drugim problemem jest to, że taka konfiguracja wiąże się z planowym opóźnieniem w replikacji. Jeśli do przyjęcia jest czasowe rozjechanie się zawartości baz danych na obu serwerach, to można próbować taką konfigurację zastosować. Natomiast nie jest to sposób na zwiększenie ilości operacji zapisu wykonanych w jednostce czasu. No nie da się tak, po prostu.
Tyle na ten raz, o kolejnych cechach replikacji MySQL napiszę za kilka dni.
Komentarze