6174 / 6174/6174.github.io

数据同步理论

Đang mở
#4 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
HTML
Star
19
Fork
0
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Mô tả

# 数据同步

> 原文: https://www.objc.io/issues/10-syncing-data/data-synchronization/
## 关于

这里的数据同步的问题描述的是-多个不同的端存储相同的数据,并需要保证数据的同步。 这在现实开发中实在是个令人头疼的难题, 参考原文在理解的基础上做了修改和调整
1. **分布式数据库互备**
2. **分布式应用配置同步**
3. **多设备应用数据同步**

本文想借此展开相关的理论和实例来深入研究一下数据同步问题。
## 数据同步理论
### 同步方式

**同步客户端服务器 (Synchronous Client-Server, S-CS)**
应用直接和远程服务通讯,将数据同步

实例:微信发送一条消息,只有消息发送完成过后才会存储在本地消息发送成功列表中,未发送成功会提示重新发送

**异步客户端服务器 (Asynchronous Client-Server, A-CS)**
应用将数据保存在本地,应用保持本地数据和远程数据的同步(后台运行)

实例:Mac QuickTime 录制了一段视频,存储在文件系统中,iCoud 自动将文件系统中的数据同步到云端

**异步对等方式 (Asynchronous Peer-to-Peer, A-P2P)**
应用数据保存在本地,应用保持本地数据和其他端的数据同步, 每个端存储数据的完成备份,服务器端不存在备份。
### 数据同步要素

**识别**
对象识别需要使用全局标识符 `uuids` (universaaly Unique identifiers)

**变化追踪**
描述算法如何确定自上一次数据同步后, 数据发生了哪些变化, 然后本地存储应该如何修改。
1. `颗粒大小`: 当某个属性字段被修改过后,确定追踪这个字段还是追踪整个实例
2. `记录变化`: 是否变化简单情况可以用一个 Boolean 的标示来表示, 也可能需要用日志来记录变化并附加时间戳
3. `软删除`:
**冲突解决**

当多端都在共同修改一个实例的时候,就会出现冲突。
1. 简单情况: 读写被认为是原子操作,解决冲突可以看成选择什么版本的存储。 如 iCloud 出现冲突时,应用提示用户选择文档的什么版本
2. 变化优先级策略:
- 最近一次的同步操作确定级别最高, 所有这一次同步操作的变化覆盖之前存储的数据,
- 最近一次修改时间戳确定优先级别
3. 避免随机策略,总是保证一致的选择策略
### 对等同步通讯(S-P2P)

假设我们有一个像 iTunes 那样的 Mac 应用程序,它可以通过 USB、蓝牙或者 Wi-Fi 和 iPhone 进行同步通讯。(凭借快速的本地网络,我们不用太在意限制数据传输大小)
1. **第一步**: 当 iPhone 第一次同步的时候,两个应用程序通过 Bonjour 发现对方,然后 Mac 应用程序将它的所有存储数据压缩,通过套接字将压缩后的文件传递给 iPhone 应用程序,然后 iPhone 将其解压并安装。
2. **第二步**: 现在假设用户使用 iPhone 对已经存在的对象做了修改 (比如,给一首歌打了星级)。该设备上的应用程序给该对象设置了一个 Boolean 型的标记(比如,changedSinceSync),用来表示该对象是新的还是已经被修改过的。
3. **第三步**:当下一次同步发生的时候,iPhone 应用程序将它的所有数据存储压缩并回发给 Mac。Mac 装载这些数据,寻找被修改的实例,然后更新它自己对应的数据。然后 Mac 又将更新后的数据存储的完整拷贝发送给 iPhone,用来替代 iPhone 已经存在的数据存储,然后整个流程又重新开始。

总结来说,同步操作需要设备能够向其他设备传输数据,并且能够决定哪些被修改、合并,然后回传更新后的数据。 保证了这两个设备同步之后具有相同的数据,所以,有很强的健壮性。
### 客户端-服务器同步通讯(S-CS)

当加入了服务器的时候,服务器是为了能够更加灵活地同步数据,但是它是以数据传输和存储为代价的。 需要尽可能地减少通讯开销,所以来回地拷贝整个数据是不可行的。
1. **前置条件**:假设数据存储在服务器上的数据库中,并且每一个对象都有一个最后更新的时间戳。
2. **第一步**:当客户端程序第一次同步的时候下载所有的数据,然后建立一个本地存储,同时也在本地记录同步的时间戳。
3. **第二步**:当客户端程序发生改变的时候,它会更新对象的最后更新时间戳。
4. **第三步**:当下一次同步发生的时候,客户端会决定自上一次同步后,哪些对象做了修改,然后仅把被修改的对象发送给服务器。服务器会合并这些修改。如果服务器对某一个对象的拷贝被另一个客户端做了修改,那么它会以最近的时间戳为准来保存修改。然后服务器会回传所有比上一次从客户端发来的时间戳新的变化。这需要考虑到合并的问题,删除所有覆盖的变化。

也许有很多不同的方法。比如,你可以为每一个属性引入一个时间戳,然后在属性粒度级去追踪变化。或者你可以在客户端合并所有的数据,然后将合并后的结果发回给服务器,这实际上是互换了角色。但是,基本说来,一个设备发送修改结果给其他设备,然后接收方合并并回发合并后的结果。

删除需要考虑更多。因为一旦删除了一个对象,就不可能跟踪它了。一种选择是使用 软删除 ,也就是对象并不是被真正的删除,而是标记为删除 (比如使用一个 Boolean 属性)。 (这和在 Finder 中删除一个文件类似。只有当你清空的垃圾桶之后,它才被永久地删除。)
### 客户端-服务器异步通讯 (A-CS)

异步的数据同步框架和服务的吸引力在于它们提供了现成的解决方案。 S-CS 模式是要定制的,也就是说得为不同的应用程序以及不同的平台编写不同的代码。

异步服务 (比如, Dropbox Datastore API 和 Wasabi Sync) 通常提供框架,让应用程序开发者用起来好像是本地数据存储。这些框架在本地保存修改,然后在后台控制与服务器的同步。

A-CS 和 S-CS 的一个最主要的区别在于,A-CS 框架额外提供的抽象层,屏蔽了直接参与同步的客户端代码。这也意味着,同一服务可以用于所有的数据模型,而不是特定的一种模型。
## 数据同步实例
1. 数据库互备
2. Evernote
3. workflowy
4. 部落冲突
5. 百度云盘
6. 通讯录备份
7. git
## @todo
1. A-C2S
- [datastore-js](https://github.com/dropbox/datastore-js) 源码分析
- datastore 数据同步策略和冲突解决方案文章阅读
- https://blogs.dropbox.com/developers/2013/07/how-the-datastore-api-handles-conflicts-part-1-basics-of-offline-conflict-handling/
- https://blogs.dropbox.com/developers/2013/08/how-the-dropbox-datastore-api-handles-conflicts-part-two-resolving-collisions/
2. A-P2P
- [gun](https://github.com/amark/gun) 源码分析
3. S-C2S
- [parse-server](https://github.com/6174/parse-server) parse 相关文档和后端 server 实现
- [parse-js-sdk](https://github.com/ParsePlatform/Parse-SDK-JS) parse 前端 javascript sdk
4. 实例研究- Evernote
5. 实例研究- 部落冲突

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.