İstemci-sunucu veritabanlarını senkronize etme


85

Merkezi bir sunucudaki verileri her zaman çevrimiçi olmayan istemci uygulamalarıyla senkronize etmek için bazı genel stratejiler arıyorum.

Benim özel durumumda, sqlite veri tabanına sahip bir android telefon uygulamam ve MySQL veri tabanına sahip bir PHP web uygulamam var.

Kullanıcılar, telefon uygulamasına ve web uygulamasına bilgi ekleyip düzenleyebilecekler. Telefon sunucuyla hemen iletişim kuramasa bile, bir yerde yapılan değişikliklerin her yere yansıtıldığından emin olmam gerekiyor.

Verilerin telefondan sunucuya veya tam tersi şekilde nasıl aktarılacağıyla ilgilenmiyorum. Belirli teknolojilerimden yalnızca, örneğin MySQL'de mevcut olan çoğaltma özelliklerini kullanamadığım için bahsediyorum.

İstemci-sunucu veri senkronizasyonu sorununun çok uzun zamandır var olduğunu biliyorum ve sorunun üstesinden gelme kalıpları hakkında bilgi (makaleler, kitaplar, tavsiyeler vb.) İstiyorum. Güçlü yönleri, zayıf yönleri ve değiş-tokuşları karşılaştırmak için senkronizasyonla başa çıkmak için genel stratejiler hakkında bilgi edinmek istiyorum.

Yanıtlar:


96

Karar vermeniz gereken ilk şey, çelişkili değişiklikler olması durumunda hangi tarafın "yetkili" kabul edileceğine dair genel bir politikadır.

Yani: 125 Numaralı Kaydın 5 Ocak saat 10: 00'da sunucuda değiştirildiğini ve aynı kayıt telefonlardan birinde (buna İstemci A diyelim) 5 Ocak 23: 00'da değiştirildiğini varsayalım. Son senkronizasyon 3 Ocak'ta yapıldı. Daha sonra kullanıcı, örneğin 8 Ocak'ta yeniden bağlanır.

Neyin değiştirilmesi gerektiğini belirlemek, hem istemcinin hem de sunucunun son senkronizasyon tarihini bilmesi anlamında "kolaydır", bu nedenle , son senkronizasyonun uzlaştırılması gerektiğinden, oluşturulan veya güncellenen her şey (bu konuda daha fazla bilgi için aşağıya bakın).

Öyleyse, değiştirilen tek kaydın # 125 olduğunu varsayalım. Ya ikisinden birinin otomatik olarak "kazandığına" ve diğerinin üzerine yazdığına karar verirsiniz ya da bir kullanıcının hangi sürümün (sunucu veya istemci) doğru sürümün üzerine yazarak karar verebileceği bir uzlaştırma aşamasını desteklemeniz gerekir.

Bu karar son derece önemlidir ve müşterilerin "rolüne" ağırlık vermelisiniz. Özellikle yalnızca istemci ve sunucu arasında olası bir çelişki varsa, farklı istemcilerin aynı kayıtları değiştirebilmesi durumunda.

[# 125'in ikinci bir istemci (İstemci B) tarafından değiştirilebileceğini varsayarsak, henüz senkronize edilmemiş olan Müşteri B'nin aynı kaydın başka bir sürümünü sağlaması ve önceki uyuşmazlık çözümünü tartışmaya açması ihtimali vardır]

Yukarıdaki " oluşturulan veya güncellenen " noktayla ilgili olarak ... istemcilerden birinde oluşturulmuşsa bir kaydı nasıl doğru bir şekilde tanımlayabilirsiniz (bunun sorunlu etki alanınızda mantıklı olduğunu varsayarak)? Uygulamanızın bir iş bağlantıları listesini yönettiğini varsayalım. Müşteri A, yeni oluşturulmuş bir John Smith eklemeniz gerektiğini söylüyorsa ve sunucu dün Müşteri D tarafından oluşturulmuş bir John Smith'e sahipse ... farklı kişiler olmadıklarından emin olamadığınız için iki kayıt mı oluşturuyorsunuz? Kullanıcıdan bu çatışmayı da uzlaştırmasını isteyecek misiniz?

Müşteriler bir veri alt kümesinin "sahipliğine" sahip mi? Yani İstemci B, Alan # 5 için veriler üzerinde "otorite" olarak ayarlanmışsa, Müşteri A Alan # 5 için kayıtları değiştirebilir / oluşturabilir mi? (Bu, bazı uyuşmazlıkları çözmeyi kolaylaştırır, ancak sizin durumunuz için uygun olmayabilir).

Özetlemek gerekirse, ana sorunlar şunlardır:

  • Ayrılmış istemcilerin yeni bir kayıt oluşturmadan önce sunucuya erişmemiş olabileceği dikkate alınarak "kimlik" nasıl tanımlanır.
  • Önceki durum, çözüm ne kadar karmaşık olursa olsun, veri tekrarına neden olabilir, bu nedenle bunları periyodik olarak nasıl çözeceğinizi ve müşterilere "Kayıt # 675" olarak gördükleri şeyin gerçekte nasıl birleştirildiğini / yerine geçtiğini nasıl bildireceğinizi öngörmelisiniz. Kayıt # 543
  • Uyuşmazlıkların fiat ile çözülüp çözülmeyeceğine karar verin (ör. "Sunucu sürümü, önceki senkronizasyondan bu yana güncellendiyse her zaman istemcininkini geçecek ") veya manuel müdahale ile
  • Fiat durumunda , özellikle müşterinin öncelikli olduğuna karar verirseniz, daha fazla değişikliğe sahip olabilecek diğer, henüz senkronize edilmemiş istemcilerle nasıl başa çıkacağınıza da dikkat etmelisiniz.
  • Önceki öğeler, verilerinizin ayrıntı düzeyini hesaba katmaz (işleri açıklamayı daha basit hale getirmek için). Benim örneğimde olduğu gibi, "Kayıt" düzeyinde mantık yürütmek yerine, bunun yerine alan düzeyinde değişikliği kaydetmeyi daha uygun bulabileceğinizi söylemek yeterli. Veya bir dizi kayıt üzerinde çalışmak için (örneğin, Kişi kaydı + Adres kaydı + Kişiler kaydı) bir seferde toplamlarını bir tür "Meta Kayıt" olarak ele alarak.

Kaynakça:

(Son üçü ACM dijital kitaplığındandır, üye olup olmadığınız veya diğer kanallardan edinebileceğiniz hakkında hiçbir fikriniz yok)

Gönderen Dr.Dobbs sitede:

  • Bill Wagner tarafından SQL Server CE ve SQL RDA ile Uygulama Oluşturma 19 Mayıs 2004 (Hem masaüstü hem de mobil PC için bir uygulama tasarlamak için en iyi uygulamalar - Windows / .NET)

Arxiv.org'dan:

  • Çatışmasız Çoğaltılmış JSON Veri Türü - makale bir JSON CRDT uygulamasını açıklamaktadır (Çatışmasız çoğaltılmış veri türleri - CRDT'ler - eşzamanlı değişiklikleri destekleyen ve bu tür eşzamanlı güncellemelerin yakınsamasını garanti eden bir veri yapıları ailesidir).

Cevabınız için teşekkür ederim. Anlattığınız sorunlara yönelik yaygın olarak kullanılan / olası çözümleri (artılar, eksiler, karşılaştırmalar) okumakla çok ilgileniyorum.
Scott Saunders

Sanırım Wikipedia'yı ve bağlantı verdikleri şeyleri zaten kontrol ettiniz, değil mi?
p.marino

3
+1 Bu konu hakkında çok önemli bilgiler içeren harika bir gönderi. Eksik bir nokta: silinen kayıtları senkronize etmek.
Stefan Steinegger

7
"Silindi" yi özel bir "güncellenmiş" durumu olarak görme eğilimindeyim, özellikle de bu tür durumlarda "fiziksel silme" yerine "mantıksal silme" yi tercih ediyorum. Yani benim için ana veya ikincil tarafta "silindi", "özel boole silinmiş bayrağı" her şeyden çok ters çevrildi anlamına geliyor.
p.marino

Teşekkürler. Başka bir makaleye (dr.dobbs) bir bağlantı daha ekledim ve başka bir şey bulabilirsem bibliyografyayı güncelleyeceğim.
p.marino

9

Her tabloda bir zaman damgası sütununuzun olmasını ve her eklediğinizde veya güncellediğinizde, etkilenen her satırın zaman damgası değerini güncellemenizi öneririm . Ardından, zaman damgasının hedef veritabanındakinden daha yeni olup olmadığını kontrol ederek tüm tabloları yinelersiniz. Daha yeniyse, eklemeniz veya güncellemeniz gerekip gerekmediğini kontrol edin.

Gözlem 1: satırlar kaynak veritabanından silindiğinden ve sunucu veritabanında da aynısını yapmanız gerektiğinden fiziksel silmelerin farkında olun. Bunu, fiziksel silmelerden kaçınarak veya zaman damgalarıyla bir tabloda her silmeyi günlüğe kaydederek çözebilirsiniz. Bunun gibi bir şey: DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp)Yani, DeleteRows tablosunun tüm yeni satırlarını okumanız ve table_name, pk_column ve pk_column_value kullanarak sunucuda bir silme işlemi gerçekleştirmeniz gerekir.

Gözlem 2: Başka bir tabloyla ilişkili bir tabloya veri eklemek başarısız olabileceğinden FK'ye dikkat edin. Veri senkronizasyonundan önce her FK'yi devre dışı bırakmalısınız.


3
saatler senkronize olmalıdır
tofutim

6

Herhangi biri benzer tasarım sorunuyla uğraşıyorsa ve değişiklikleri birden çok Android cihazda senkronize etmesi gerekiyorsa, Android için Google Bulut Mesajlaşma'yı (GCM) kontrol etmenizi öneririm .

Bir istemcide yapılan değişikliklerin diğer istemcilere yayılması gereken bir çözüm üzerinde çalışıyorum. Ve ben sadece bir konsept uygulama kanıtı (sunucu ve istemci) ekledim ve bir cazibe gibi çalışıyor.

Temel olarak, her istemci sunucuya delta değişiklikleri gönderir. Örneğin, ABCD1234 kaynak kimliği 100'den 99'a değişmiştir.

Sunucu, bu delta değişikliklerini kendi veritabanına göre doğrular ve değişikliği onaylar (istemci senkronize olur) ve veritabanını günceller veya değişikliği reddeder (istemci senkronize değildir).

Değişiklik sunucu tarafından onaylanırsa, sunucu daha sonra diğer istemcileri (delta değişikliğini gönderenler hariç) GCM aracılığıyla bilgilendirir ve aynı delta değişikliğini taşıyan çok noktaya yayın mesajı gönderir. Müşteriler bu mesajı işler ve veritabanlarını günceller.

Harika olan şey, bu değişikliklerin neredeyse anında yayılmasıdır !!! bu cihazlar çevrimiçiyse. Ve bu istemciler üzerinde herhangi bir sorgulama mekanizması uygulamama gerek yok.

Bir cihaz çok uzun süre çevrimdışıysa ve teslim edilmek üzere GCM kuyruğunda bekleyen 100'den fazla mesaj varsa, GCM'nin bu mesajı atacağını ve cihazlar tekrar çevrimiçi olduğunda özel bir mesaj göndereceğini unutmayın. Bu durumda istemcinin sunucuyla tam bir senkronizasyon yapması gerekir.

CGM istemci uygulamasına başlamak için bu öğreticiye de bakın .


5

bu, Xamarin çerçevesini kullanan geliştiricilere yanıt verir (bkz. /programming/40156342/sync-online-offline-data )

Bunu xamarin çerçevesiyle elde etmenin çok basit bir yolu, Azure'ın Çevrimdışı Veri Eşitleme özelliğini kullanmaktır çünkü isteğe bağlı olarak sunucudan veri aktarmaya ve çekmeye izin verir. Okuma işlemleri yerel olarak yapılır ve yazma işlemleri talep üzerine çalıştırılır; Ağ bağlantısı kesilirse, bağlantı yeniden kurulana kadar yazma işlemleri kuyruğa alınır ve ardından yürütülür.

Uygulama oldukça basittir:

1) Azure portalda bir Mobil uygulama oluşturun ( https://tryappservice.azure.com/ adresinden ücretsiz olarak deneyebilirsiniz )

2) müşterinizi mobil uygulamaya bağlayın. https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

3) yerel deponuzu kurmak için kod:

const string path = "localrepository.db";

//Create our azure mobile app client
this.MobileService = new MobileServiceClient("the api address as setup on Mobile app services in azure");

//setup our local sqlite store and initialize a table
var repository = new MobileServiceSQLiteStore(path);

// initialize a Foo table
store.DefineTable<Foo>();

// init repository synchronisation
await this.MobileService.SyncContext.InitializeAsync(repository);
var fooTable = this.MobileService.GetSyncTable<Foo>();

4) ardından en son değişiklikleri aldığımızdan emin olmak için verilerinizi aktarın ve çekin:

await this.MobileService.SyncContext.PushAsync();
await this.saleItemsTable.PullAsync("allFoos", fooTable.CreateQuery());

https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started-offline-data/


0

Simetriklere de bir göz atmanızı öneririm . Android sistemlerde kullanılabilen bir SQLite çoğaltma kitaplığıdır. istemci ve sunucu veritabanınızı senkronize etmek için kullanabilirsiniz, ayrıca her istemci için sunucuda ayrı veritabanları olmasını öneririm. Tüm kullanıcıların verilerini tek bir mysql veritabanında tutmaya çalışmak her zaman en iyi fikir değildir. Özellikle kullanıcı verileri hızlı büyüyecekse.


0

Buna CUDR Sync problemi diyelim ( CRUD'yi sevmiyorum - çünkü Oluştur / Güncelle / Sil yazmadır ve birlikte eşleştirilmelidir)

Problem aynı zamanda ilk yazma veya çevrim içi ilk yazma perspektifinden de ele alınabilir . Çevrimdışı yazma yaklaşımının, benzersiz tanımlayıcı çakışması ve aynı işlem için riski (veya maliyeti) artıran birden çok ağ çağrısı ile ilgili bir sorunu vardır ...

Ben şahsen çevrimiçi ilk yazma yaklaşımını yönetmeyi daha kolay buluyorum (bu nedenle bu, her şeyin senkronize edildiği tek gerçeğin kaynağı olacak). Çevrimiçi yazma yaklaşımı, kullanıcıların önce çevrimdışı yazmasına izin vermemeyi gerektirecektir - çevrimiçi yazmada ok yanıt formu alarak çevrimdışı yazacaklardır.

Önce çevrimdışı okuyabilir ve ağ kullanılabilir olur olmaz verileri çevrimiçi olarak alabilir ve yerel veritabanını güncelleyebilir ve ardından kullanıcı arayüzünü güncelleyebilir ....

Benzersiz tanımlayıcı çakışmasını önlemenin bir yolu, benzersiz kullanıcı kimliği + tablo adı veya tablo kimliği + satır kimliği (sqlite tarafından oluşturulan) kombinasyonunu kullanmaktır ... ve ardından senkronize edilmiş boole bayrağı sütununu onunla kullanmaktır .. ancak yine de Diğer tüm kimliklerin oluşturulacağı benzersiz kimliği almak için önce kayıt çevrimiçi olarak yapılmalıdır ... Burada sorun, saatler senkronize edilmediğinde de ortaya çıkacaktır - ki bu yukarıda bahsedilen ...


Dahası, çevrimdışı yazma yaklaşımının uygulama kaldırmada bir sorunu olacak, çevrimiçi yüklenmeyen tüm veriler silinecek
DragonFire
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.