代码之家  ›  专栏  ›  技术社区  ›  Scott Saunders

同步客户端服务器数据库

  •  73
  • Scott Saunders  · 技术社区  · 14 年前

    我正在寻找一些通用策略,用于将中央服务器上的数据与不总是在线的客户端应用程序同步。

    用户可以在手机应用程序和网络应用程序上添加和编辑信息。我需要确保一个地方所做的更改在任何地方都得到反映,即使手机无法立即与服务器通信。

    我不关心如何将数据从手机传输到服务器,反之亦然。我之所以提到我的特定技术,只是因为我不能使用MySQL的复制功能。

    5 回复  |  直到 13 年前
        1
  •  99
  •   p.marino    8 年前

    第一件事你必须决定的是一个总的政策,哪一方被认为是“权威”的情况下,冲突的变化。

    例如:假设服务器上的记录#125在1月5日晚上10点更改,而其中一部手机(我们称之为客户端A)上的记录在1月5日晚上11点更改。 上次同步是在1月3日,然后用户在1月8日重新连接。

    从客户机和服务器都知道最后一次同步的日期的意义上说,识别需要更改的内容是“容易”的,所以什么都可以 创建或更新

    因此,假设唯一更改的记录是#125。 您要么决定两个版本中的一个自动“获胜”并覆盖另一个,要么需要支持协调阶段,用户可以在该阶段决定哪个版本(服务器或客户机)是正确的,覆盖另一个版本。

    这个决定非常重要,你必须权衡客户的“角色”。尤其是当客户机和服务器之间存在潜在冲突,而且不同的客户机可以更改相同的记录时。

    [假设#125可以由第二个客户机(客户机B)修改,则尚未同步的客户机B有可能会提供同一记录的另一个版本,从而使以前的冲突解决变得毫无意义]

    “关于” 创建或更新 假设您的应用程序管理一个业务联系人列表。如果客户机A说您必须添加一个新创建的John Smith,而服务器有一个客户机D昨天创建的John Smith。。。你创建两个记录是因为你不能确定他们不是不同的人吗?您是否也会要求用户协调此冲突?

    客户是否拥有数据子集的“所有权”?例如,如果客户B被设置为区域5数据的“权威机构”,客户A是否可以修改/创建区域5的记录(这将使一些冲突的解决更容易,但可能会证明不可行的情况)。

    概括起来,主要问题是:

    • 以前的情况,无论解决方案多么复杂,都可能导致数据重复,因此您必须预见如何定期解决这些问题,以及如何通知客户,他们认为的“记录#675”实际上已与记录#543合并/被其取代
    • 菲亚特 (例如,“如果服务器版本自上次同步后已更新,则服务器版本始终优于客户端版本”)或通过手动干预
    • 万一 ,特别是如果您决定客户机优先,您还必须注意如何处理其他尚未同步的客户机,这些客户机可能会有更多的更改。

    参考文献:

    (最后三个来自ACM数字图书馆,不知道你是不是会员,也不知道你是否可以通过其他渠道获得这些信息)。

    Dr.Dobbs 地点:

    • 2004年5月19日,Bill Wagner用SQL Server CE和SQL RDA创建应用程序(为台式机和移动PC设计应用程序的最佳实践-Windows/.NET)

        2
  •  10
  •   Bizhan    9 年前

    我建议你有一个 时间戳

    观察1:注意物理删除,因为行是从源数据库中删除的,您必须在服务器数据库中执行同样的操作。您可以解决这个问题,避免物理删除或在带有时间戳的表中记录每次删除。像这样: DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp)

    观察2:请注意FK,因为在与另一个表相关的表中插入数据可能会失败。您应该在数据同步之前停用每个FK。

        3
  •  6
  •   jogo    10 年前

    如果有人正在处理类似的设计问题,需要在多个Android设备上同步更改,我建议检查一下 Google Cloud Messaging for Android (GCM)。

    基本上,每个客户机都向服务器发送增量更改。例如,资源id ABCD1234已从值100更改为99。

    服务器根据其数据库验证这些增量更改,并批准更改(客户端同步)并更新其数据库,或拒绝更改(客户端不同步)。

    请记住,如果设备脱机时间过长,并且GCM队列中等待传递的消息超过100条,GCM将丢弃这些消息,并在设备重新联机时发送一条特殊消息。在这种情况下,客户端必须与服务器进行完全同步。

    同时检查 this tutorial 开始使用CGM客户机实现。

        4
  •  5
  •   Community CDub    7 年前

    这回答了使用Xamarin框架的开发人员(请参见 https://stackoverflow.com/questions/40156342/sync-online-offline-data

    使用xamarin框架实现这一点的一个非常简单的方法是使用Azures离线数据同步,因为它允许按需从服务器推送和拉取数据。读操作在本地完成,写操作按需推送;如果网络连接中断,写入操作将排队,直到连接恢复,然后执行。

    实现相当简单:

    https://tryappservice.azure.com/ )

    2) 将客户端连接到移动应用程序。 https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

    3) 设置本地存储库的代码:

    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>();
    

    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/

        5
  •  0
  •   Hossein Shahdoost    6 年前

    我建议你也看看 Symmetricds . 它是android系统可用的SQLite复制库。您可以使用它来同步您的客户机和服务器数据库,我还建议在服务器上为每个客户机设置单独的数据库。尝试将所有用户的数据保存在一个mysql数据库中并不总是最好的主意。特别是如果用户数据增长很快。

        6
  •  0
  •   DragonFire    5 年前

    我们称之为 问题(我不喜欢CRUD-因为Create/Update/Delete是写操作,应该成对出现)

    这个问题也可以从 先注销行 先在线写作

    我个人认为“在线写作优先”的方法更容易管理(因此它将是唯一的真相来源——其他一切都是同步的)。在线写的方法将不需要让用户先离线写-他们将通过在线写得到ok响应来离线写。

    他可以先离线阅读,一旦网络可用,就从在线获取数据,更新本地数据库,然后更新用户界面。。。。

    避免唯一标识符冲突的一种方法是使用唯一用户id+表名或表id+行id(由sqlite生成)的组合。。。然后使用synced boolean flag列。。但注册仍然必须先在线完成,以获得唯一的id,所有其他id将在其上生成。。。这里的问题也将是如果时钟不同步-有人提到上述。。。