7. Serwis
Blog
select * from User where id=ID
select * from Message where id=ID order by ts desc limit …
Stream
select * from User where id=JA
select Message.*, User.* from Message
join Follow on Message.owner_id=Follow.whom_id
join User on Message.owner_id=User.id where
Follow.who_id=JA; (!)
Dodaj wpis
insert into Message(`owner_id`,`message`) values ...
8. Serwis
Gdzie jesteśmy?
Replikacja danych użytkownik PHP MySQL HaProxy
9. Serwis
Gdzie jesteśmy?
LB i workery ”dokładamy w nieskończoność”
Kolejne repliki bazy zwiększają odczyt
Nie zapis
Nie pojemność
full-mesh
12. Wprowadzamy zmiany
Rozdzielamy ma moduły
Partycjonowanie funkcjonalne
User (API)
Message (API)
Front
Front
Moduł stanowy (sesja)
Prezentacja User Message
Agregacja danych z API
użytkownik Moduł
13. Wprowadzamy zmiany
Moduły są niezależne
Ma swój zestaw maszyn
Load balancery, Workery, Bazy
Jedna maszyna = jedna rola
Moduł A nie wie jak zorganizowany jest moduł B
Wie tylko jak go używać (API)
Komunikacja między modułami
tylko za pomocą API (dostępne przez LB)
14. Wprowadzamy zmiany
Blog
Front => User (podaj dane użytkownika X)
Front => Message (podaj wpisy użytkownika X)
Stream
Front => User (podaj listę obserwowanych przez
użytkownika X)
Front => Message (podaj ostatnie wpisy
użytkowników o zadanych id)
Zrób join na liscie użytkowników i wpisów
15. Wprowadzamy zmiany
Zalety
Moduł Front prostszy
Wiemy gdzie są wąskie gardła
Separacja obowiązków
Wady
Więcej maszyn
Workery Front robią joiny
Odciąża bazy, workery można dokładać
Jest wolniej
Spójność danych (skasowanie użytkownika?)
17. Wprowadzamy zmiany
Dodajemy cache
Każdy moduł zarządza swoim cache
Dwa poziomy cache
Loadbalancery (zamieniamy haproxy na varnisha)
”chroni” workery, memcached, DB
Memcached
”chroni” DB
Dwie metody
Odczyt z DB, zapis do cache na X sekund
Odczyt z DB, zapis do cache ”w nieskończoność” (!)
18. Wprowadzamy zmiany
Blog
Front => Message (podaj wpisy użytkownika X)
Message API LB (cache)
MessageAPI Worker => DB
Lista wiadomości zapisana w
Memcached ?
Varnish ?
19. Wprowadzamy zmiany
Stream
Front=> User (podaj listę obserwowanych)
Front => Message (podaj blogi użytkowników z
listy)
Message: dla każdego użytkownika z listy
pobierz wpisy użytkownika (blog)
join w workerze
Tak zwane pull on demand
20. Wprowadzamy zmiany
Dodaj wpis
Front => Message (dodaj wpis użytkownika X)
Worker Message dodaje wpis do bazy
Worker Message dodaje wpis do memcached
Worker niszczy (łatwiej) listę wpisów (blog)
ze swojego varnisha
ze swojego memcached
troche się skomplikowało....
21. Wprowadzamy zmiany
Zalety
Jest szybciej
Odciążamy DB i sieć(!)
Duże hit-ratio na memcached przy blogach
Brak dog-pile effect (varnish)
Wady
Trudniej (więcej worker-side)
Spójność cache i baz danych
Im więcej lb, tym mniejsze hit-ratio
23. Wprowadzamy zmiany
Shardujemy
Partycjonowanie horyzontalne
Shardy są niezależne
Mają inne dane
Nic nie wiedzą o sobie
Funkcja(klucz) = numer sharda
24. Wprowadzamy zmiany
Shardujemy
Tabela Follow
Klucz who_id
Funkcja who_id modulo liczba shardów
Tabela Message
Klucz owner_id
Funkcja owner_id modulo liczba shardów
Tabela User
Bez shardowania
25. Wprowadzamy zmiany
Zalety
Zwiększamy wydajność zapisów (i odczytów)
Zwiększamy pojemność bazy
Więcej mniejszych baz (zarządzanie, szybkość)
Wady
Komplikacja logiki
Kto mnie obserwuje
Cross-shard query
Dokładanie shardów
27. Podsumowanie
Prosty serwis
Zrobił się skomplikowany
Skomplikowanie wydelegowane do modułów ;)
Dodaliśmy sporo maszyn
Optymalizacja jeszcze ważniejsza (IO)
Sieć dostaje w kość
Dużo pracy
może scale-up ?