我正在看Firestore,但是该文档对Android上的持久性数据非常了解。我的问题是关于设备恢复在线状态时将发生的动作。
让我们想象一下我在线上的数据太少了:
MyCollection
| ----------------------- MyDocument (empty)
如果我有两个与此模型同步但处于离线状态的设备,
两者均写入MyDocument中,该设备A创建了一个值为id
的字段A
,而我的设备B也创建了一个值为id
的字段B
。
设备A首先返回联机,然后与Firestore同步,然后设备B返回联机,这是因为问题id
字段已经存在,并带有另一个值。
Firestore知道它是在后台自动完成的,该如何处理?是否有机会抓住冗余来解决问题?
答案 0 :(得分:10)
在这种情况下,Firestore不执行任何冲突解决。这意味着在完成整个流程之后,来自设备B的写入将被存储。在数据库级别,这是正确的,因为它无法知道您是否还需要其他东西。
如果要防止从设备B写入数据,则必须确保做到这一点。您可以做一些事情:
将写入内容放入事务是两者中最简单的。但是,如果客户端脱机,它将失败,因为在这种情况下,客户端无法检查并发更新。
或者,您可以使用安全规则,当客户端数据到达服务器时,这些规则将在Firebase服务器上进行评估。如果可以检测到来自设备B的写入无效/作废的事实,则可以拒绝它。
一个非常简单的例子是在每个写操作中添加一个时间戳,然后拒绝新时间戳在数据库中的时间戳之前的写操作。这样可以确保如果进行了更改,则将存储上一次所做的更改(而不是上一次重新联机)。
如您所见,这两个都是解决问题的重要方法。这就是为什么我的第一个建议是找到一个完全避免冲突的数据模型。通过避免冲突的写操作,可以避免解决冲突。做到这一点的一个很好的例子是,不让客户更新实际文档,而是让客户将更改存储为单独的数据,而又不覆盖任何数据。
MyCollection
| ---- MyDocument (empty)
| -------- Change from device A
| -------- Change from client B
现在,所发生事件的整个踪迹都存储在数据库中,每个客户都可以使用此信息根据您拥有的任何业务规则来构建实际文档。
这实际上是NoSQL数据库中非常普遍的方法,尤其是在需要大量并发写入的项目中。通过防止冲突的写入并使用仅追加的数据模型,可伸缩性得到了极大的提高。它也是许多(关系)数据库的“ op log”文件背后使用的模型。通过保留所有操作的日志,他们可以从头开始重建数据库。
在许多情况下,您还将偶尔存储文档状态的快照,以更快地确定当前文档。这可以由随机客户端来完成,也可以由受信任的过程来完成,例如在您控制的服务器上或Cloud Functions for Firebase上。