Jak zsynchronizowac local db z remote?

0

Witam,
Appka mobilna ma lokalna db (zeby zminimalizowac zapytania do remote api).
Tabela posiada dane na temat np. produktu, dane te nie beda czesto aktualizowane ale chcialbym aby lokalna db byla zgodna z ta zdalna. (synchronizacja odbyla by sie przy kazdym uruchamianiu appki).
Teraz mam pytanie jak to najlepiej rozwiazac:

  1. Zapisanie gdzies aktualnego numeru wersji bazy (timestamp ostaniego update czy cokolowiek) i porownanie z lokalna - jezeli jest wieksza to drop calej lokalnej tabeli w bazie, zczytanie zdalnej i wgranie na nowo.
  2. Sprwadzic baze i zaciagac tylko rekordy ktore byly zmienione / usuniete(chociaz raczej nie beda usuwane), jezeli lastUpdate time jest wiekszy niz lokalnej?

Synchronizacja bedzie tylko w jedna strone, lokalna baza nie ma w ogole wplywu na zdalna, ma byc aktualnym odzwierciedleniem zdalnej.
Czy jest jakis lepszy sposob niz dwa powyzsze? Dodam jeszcze ze nie bedzie tam duzo pozycji (max moze 1k). uzywam xamarin forms + backend w asp net core 2.2
Dzieki.

0

Ja bym to zrobił leniwie. Czy w bazie lokalnej timestamp synchronizacji. W apce timestamp uruchomienia instancji. Jeśli sięgam po krotkę, która ma sync_time < run_time, to synchronizuje tylko 1 krotkę (lub jakiś pakiet - to zależy jak często sięga i ile danych potrzebuje). To pozwoli na dociąganie tylko tych danych które są potrzebne. Po co ściągać dane, które nie zostaną użyte podczas danej sesji pracy z aplikacją? Niemniej to zależy od częstotliwości i wagi danych - wszystko trzeba brać pod uwagę, jednak jeśli chcemy zminimalizować ilość strzałów do remote i ilość przesyłanych danych to chyba jest optymalne.

0

W appce mozna filtrowac "produkty" (nazwijmy tak te rekordy zeby bylo latwiej), mam pole entry, jak uzytkownik cos wpisuje to mu filtruje dane wypisane w listView.
Teraz musailbym np zaciagnac wszystkie "pordukty" w miejscu gdzie je wyswietlam i filtrowac (bedzie to czesto, za kazdym raem keidy user musi cos wybrac), wiec co chwile call do remota odpada.
Albo zaciagac z bazy zdalnej tylko te "produkty" ktore odpowiadaja zapytaniu z search,
albo sciagnac calosc raz kieyd apka sie uruchamia (max 1-2k rekordow) i trzymac w List<Product> juz lokalnie w pamieci
Albo najlepiej zaciagac z lokalnej bazy (ktora jest odbiciem remote) odpowiadajace produkty co by bylo najlepsze.

0

Zobacz ile zajmuje skompresowana baza danych i policz ile czasu zajmie pobranie jej całej, jeśli baza jest mała, nie będzie rosnąć i rzadko się zmienia, rozwiązanie 1 będzie najprostsze w implementacji i utrzymaniu.

Rozwiązanie drugie przez porównywanie baz, poleganie na czasie, obsługa kasowania, obsługa błędów sieci, implementacja tego będzie ciężka.

Jest jeszcze rozwiązanie trzecie, czyli zamiast synchronizować snapshoty, synchronizauj zmiany czyli: event sourcing znany też jako log shipping w świecie baz danych.
Polega to na zapisywaniu poszczególnych zmian w logu trzymanym obok zdalnej bazy. Wtedy lokalna baza odpytuje zdalny log, pobiera ostatnie zmiany, i aplikuje je na lokalnej bazie. To rozwiązanie jest fajne bo nie polega kompletnie na czasie, można pobierać i aplikować zmiany stopniowo, w przypadku błędu sieciowego wznawiasz pracę od ostatnio zaaplikowanej zmiany.

0

Chyba bede sciagal cala tabele jezeli timestamp sie nie zgadza.
Jest to max 1-2k rekordow ktore tylko sie czasami zmienia albo czasami cos bedzie dodane (na poczatku duzo pozniej to sie ustatkuje ze prawie w ogóle w czasie calej appki a nie klienta),
kazdy rekord to kilka stringow i intow wiec duzo nie zajmie.
Do tego client-app nie bedzie w ogóle zmienial tych danych.
ES nie bede robil przy tak malej apce.

  1. porownam timestampy lastupdate'u po obu stronach, jezeli roznica -> sciagne cala tabele remote, zrobie dumpa lokalnej i wgram na jej miejsce remote.
    Appka i tak bedzie dzialac jedynie w trybie online.
    Chyba ze z czasem cos sie zmieni w rozmiaze / uzytkowaniu to przerobie.
    Chce to zrobic bez zbednego kombinowania ale zeby tez nie bylo syfem.
    @somedev przez "leniwie" masz na mysli "lejzi lołding" ? :]
0

Leniwe - czyli aktualizujemy tylko te dane których potrzebujemy i dopiero wtedy kiedy ich potrzebujemy a nie wszystkie na starcie apki. Misę być tak, ze nie użyjesz danych w ogóle wiec po co je ściągać? A jeśli użyjesz to czy wszystkich? To jest podejście leniwe ale faktycznie trzeba się zastanowić czy słuszne tutaj. Jeśli to rzędy tysięcy rekordów to może nie istotne. Ja pracuje na danych rzędu dziesiątek milionów. Pamiętaj „premature optimization is the root of all evil (or at least most of it) in programming.” - Donald Knuth.

0

No wlasnie dlatego sie kieruje w strone sciagania calej tabeli... bo tutaj optymalizacja nie jest potrzebna (przy twoich milionach to juz bym sie kierowal w inna strone).
Opisze w skrocie:
User ma liste "porducts" (jakies tam obiekty okolo 1-2k w bazie) ktore dodaje sobie do glownego "czegos".
Kiedy otworzy boczny panel to pokaze sie lista "productow" ktore ma oznaczone jako favorite + te ktorych uzywal najczesciej. Jezeli chce dodac inny "product" z bazy to musi go "odfiltrowac" wpisujac w "search boxie" o co mu chodzi, dane sa filtrowane na podstawie tego stringa (musi byc substringiem w nazwie produktu), i tak np 20+ razy dziennie / usera.
Czyli bym mial pelno glupich zapytan do backendu o search-criteria i zwracane odfiltrowane produkty. W przypadku local db nie musze tak kombinowac a jedynie uaktualnic tabele jezeli nie zgadza sie timestamp. czyli np raz na tydzien sciagnac te kilka mb danych i uaktualnic.
Chyba najbardziej sensownie bedzie sciagnac cala tabele i nie bede bardziej kombinowal. chyba ze w "dalekiej" przyszlosci cos sie zmieni.

0

Przy takim zastosowaniu też bym nie kombinował za bardzo. Przy czym ściąganie raz w tygodniu nie wiem czy jest ok. Może jestem zwolennikiem lenistwa, ale nie spóźniania ;) Może warto by co jakiś czas sprawdzać, czy coś nowego w backendzie jest lub w ogóle trzymać jakiegoś wss i reagować na push, że dane się zmieniły? Wtedy wszystkie instancje aktywne zaciągną dane, to co sie włączą to z definicji zaciągną dane. W przypadku tego ściągania raz na tydzień to przez tydzień będziesz miał n aplikacji w różnym stanie, bo każda mogła być włączona w innym czasie. Co więcej może to być n stanów większe od 2, jeśli zrobisz więcej aktualizacji.

0

Na chwile obecna klient przy kazdym uruchomieniu sprawdzi czy jest nowa wersja. (to ze raz na tydzien to dlatego ze raz na tydzien sie baza zmieni a moze i zadziej :D) Myslalme zeby dodac real-time z SignalR ale niewiem czy jeszce do czegos wykorzystam wiec na razie sie wstrzymalem.
Nie zalezy mi na jakies real-time synchronizacji, nikt za to punktow nie bedzie dostawal, po prostu moze sie zmienic np description tego "czegos" a to nie jest cos waznego, albo czasami dodana zostanie nowa pozycja, z tym ze te wystepujace najczesciej beda dodane na poczatku a z czasem dodawane nowe ktore nie sa czesto wybierane.
Nie sa to wiec jakies strategiczne dane ktore musza byc u kazdego takie same w tym samym czasie.
A ze klient zamiast slowa "zielony samochod" przy nastepnym uruchomieniu bedzie mial "zielonkawy samochod" to nie jest wielkie halo.
No to do pisania.... :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1