Jak zarządzasz dwukierunkową synchronizacją między „głównym” serwerem bazy danych a wieloma „wtórnymi” serwerami, w szczególności rozwiązywaniem konfliktów, zakładając, że połączenie nie zawsze jest dostępne?
Mam na przykład aplikację mobilną, która używa CoreData jako „bazy danych” na iOS i chciałbym umożliwić użytkownikom edycję treści bez połączenia z Internetem. Jednocześnie informacje te są dostępne na stronie internetowej, z którą połączą się urządzenia. Co mam zrobić, jeśli / kiedy dane na dwóch serwerach DB są w konflikcie?
(Mówię o CoreData jako o serwerze DB, choć wiem, że jest to coś nieco innego).
Czy istnieją jakieś ogólne strategie radzenia sobie z tego rodzaju problemem? Są to opcje, o których mogę myśleć:
1. Zawsze używaj danych po stronie klienta o wyższym priorytecie
2. Tak samo po stronie serwera
3. Spróbuj rozwiązać konflikty, zaznaczając znacznik czasu edycji każdego pola i dokonując ostatniej edycji
Chociaż jestem pewien, że trzecia opcja otworzy miejsce na druzgocące uszkodzenie danych.
Wiem, że twierdzenie CAP dotyczy tego, ale chcę tylko ostatecznej spójności, więc nie wyklucza to całkowicie, prawda?
Powiązane pytanie: wzorce najlepszych praktyk w zakresie dwukierunkowej synchronizacji danych . Druga odpowiedź na to pytanie mówi, że prawdopodobnie nie można tego zrobić.
Odpowiedzi:
Zwykłym rozwiązaniem pozwalającym stwierdzić, „która zmiana jest poprawna”, jest zegar wektorowy . Zasadniczo śledzisz liczniki dla każdego repozytorium, które przechowuje dane, i odrzucasz zmiany, jeśli pogląd konkretnego klienta na stan wszystkich innych osób różni się od poglądu peera, z którym się łączy.
Najważniejsze pytanie, na które musisz odpowiedzieć, brzmi: w jaki sposób rozwiążesz odrzucone zapisy. Ogólnie oznacza to operację scalania.
Pamiętaj, że zegary wektorowe nie używają znaczników czasu w czasie rzeczywistym. Problemy związane z synchronizacją zegarów czasu rzeczywistego są co najmniej tak trudne, jak synchronizacja danych.
źródło
Jest to problem generałów bizantyjskich , którego nie można rozwiązać. Nigdy nie możesz zagwarantować synchronizacji dwóch serwerów, jeśli nie możesz zagwarantować, że w przyszłości będziesz mieć wystarczającą niezawodną przepustowość, aby przeprowadzić synchronizację za jednym razem.
źródło
Myślę, że nie ma standardowego sposobu, aby to zrobić, każdy system stosuje własne zasady rozwiązywania konfliktów.
Przeprowadziłem kilka symulacji przy użyciu dwóch urządzeń: komputera i telefonu oraz arkusza kalkulacyjnego Google, aby sprawdzić, jak Dokumenty Google automatycznie obsługują konflikty. Oto kilka przypadków:
Przypadek 1
Przypadek 2
Tak więc przynajmniej serwer Google Docs wykorzystuje ostatnie otrzymane dane jako wyższy priorytet niezależnie od tego, kiedy zostały utworzone (znacznik czasu klienta). Testowałem też, czy synchronizują się w tle i najwyraźniej nie, więc wynik rozwiązania konfliktu jest przezroczysty dla użytkownika.
Z drugiej strony GIT nie obsługuje automatycznie konfliktów, ale przekazuje dane ostatniemu użytkownikowi, który próbował zmienić repozytorium, jak należy wykonać scalanie.
Wybrałbym podejście do Dokumentów Google, jeśli synchronizacja jest możliwa tylko na pierwszym planie, a użytkownik wizualizuje dane. W przeciwnym razie użytkownik może być zaskoczony, że podczas gdy jego telefon automatycznie łączył się z siecią Wi-Fi, nie zsynchronizowana zmiana spotkania, które po ponownej edycji na komputerze uruchomiła.
Wybrałbym podejście klienta dotyczące znacznika czasu, zastępując konflikty z ostatnio edytowanym, jeśli potrzebujesz synchronizacji w tle, możesz zaufać znacznikowi czasu klienta, a koszt niepożądanego scalenia jest mniejszy niż koszt żądania od użytkownika wyboru, którą wersję chce do zachowania.
W innym przypadku wybrałbym podejście GIT, wyświetlając wyskakujące okienko w następnym kliencie na pierwszym planie, prosząc użytkownika o wybranie wersji do zachowania lub dając szansę cofnięcia scalenia.
źródło