Wpis z mikrobloga

#programowanie #programista15k #cloud

Hej Mirasy, mam pewną zagwozdkę. Mam pewien system, w którym zarządzam wykonywanymi jobami gdzieś tam w chmurze. Te joby (Lambda/Cloud function) mi wysyłają przez kolejkę logi, statusy oraz inne informacje. Ja robię persystencję tego w Firestore (NoSQL od Google). I właśnie o to chciałbym zapytać - o operacje na bazie w rozproszonym środowisku.

Pojawiła się ostatnio potrzeba wyskalowania tego, bo backend nie wyrabia, dodatkowo jest za dużo operacji i jest to za drogie. Mam to w k8s, także samo skalowanie jest możliwe, zastanawiam się jak zrobić tak zapisy / odczyty do bazy, żeby przy wielu instancjach mi się dane nie zepsuły. Skala: Do 1000 zapisów /s, do 10000 odczytów/s.

Jak u Was to działa? Możecie coś podpowiedzieć?
  • 17
via Wykop Mobilny (Android)
  • 0
@Orzeech: polecam na spokojnie przeczytać sobie lekturę: https://github.com/donnemartin/system-design-primer#database

Generalnie jeśli problemem jest read to robisz replikację i masz 1 master bazę tylko do zapisu i kilka baz tylko do odczytu (tu trzeba rozważyć consistency). Jeśli problemem jest write performance możesz użyć federation czyli więcej baz a w każdej zapisywany inny typ danych ( ale wtedy np joiny są bardziej problematyczne) albo sharding czyli porcjowanie danych wg klucza.
@rosiv: Sam performance bazy jest bardziej niż ok i wiem jak usprawnić to, gdyby kiedykolwiek było potrzebne. Chodzi o performance mojego backendu, który obrabia jakoś te dane przed odczytem / zapisem do/z bazy - to tę aplikację chcę skalować wszerz, bo nie daje rady przy tylu requestach. Chodzi mi o taki dostęp do tych danych z wielu instancji, żeby nie było gówna.

Przykład:
Obiekt w bazie ma stan X
Instancja A
@zibizz1: Z tym zapisywaniem mam problem, bo często jest to częściej niż 1/s. Radzę sobie z tym poprzez retry i exponential backoff, ale to wprowadza mi tak naprawdę stan. Mogę podzielić sobie kolekcje w firestore tak, żeby nie trzena było update'ować tak często jednego dokumentu, tylko wtedy musiałbym sobie "składać" w backendzie ten obiekt przy każdej próbie odczytu, czyli robić takiego "joina". Wydaje mi się to strasznie słabe.
@Orzeech: albo rybka albo pipka. Musiałbyś opisać dokładnie o co chodzi i dlaczego to trzeba łączyć itp. Dlaczego tak często jakiś dokument zapisujesz. Ja na twoim miejscu wypieprzyłbym Backend:) gdzie się da. I podłaczył workery i clientów do firestore gdzie się da
@Orzeech: Jeżeli masz dużo zapytań i nie jesteś w stanie ich obrabiać zanim przyjdzie następne to ja bym zrobił to na kolejce. Zrobiłbym tak, że backend podzieliłbym na część odbierającą i część obrabiającą.

Zapytanie leci do backendu i backend wrzuca dane na kolejkę bez żadnej obróbki, czyli tutaj jest szybko.
No I obrabiarka bierze z kolejki, przerabia i wrzuca do bazy. Zarówno część odbierającą możesz skalować za pomocą HPA w Kubernetesie,
@yggdrasil: To, co wchodzi do backendu do właśnie jest kolejka (pub/sub). Backend jest właśnie tą obrabiarką, ale jakby było więcej instancji tego backendu, to bym miał data corruption, bo nie synchronizuję się na tej bazie danych, czyt. jedna instancja odbiera wiadomość A, druga wiadomość B i teraz zależy od tego, która będzie pierwsza to stan obiektu w bazie będzie A albo B. Swoją drogą, kolejka nie dość, że nie gwarantuje kolejności,
tak robię, mam timestamp, i przy więcej niż jednej instancji tego "obrabiacza/zapisywacza" sytuacja by wyglądała następująco:

Obiekt jest w bazie z timestampem 100
- Instancja A dostaje wiadomość z timestampem 105, patrzy sobie do bazy, ma 100, może zapisać
- Instancja B dostaje wiadomość z timestampem 102, patrzy sobie do bazy, ma 100 (ponieważ jest to praktycznie w tym samym czasie co instancja A), może zapisać

efekt -> obiekt powinien mie ćtimestamp
@Orzeech: mi właśnie chodził po głowie kiedyś taki pomysł żeby liczbę wyświetleń zapisywać jako osobne dokumenty w zagnieżdżonej kolekcji i raz na jakis czas zliczać je, dodawać do licznika w głównym dokumencie i usuwać, i okazało się że firestore proponuje podobne podejście, tylko z góry zaklada się liczbe dokumentów które obslugują zapis i przy każdym odczycie zlicza się je
https://firebase.google.com/docs/firestore/solutions/counters
@zibizz1: Widzialem. No właśnie zrobię coś, co Tobie chodziło po głowie, u mnie niestety pola, które są zapisywane są bardziej skomplikowane niż licznik, ale fajnie że to zrobili.