2.1. 复制简介¶
CouchDB 的优势之一是能够同步同一个数据库的两个副本。这使用户能够将数据分布到多个节点或数据中心,但也能够将数据更靠近客户端。
复制涉及源数据库和目标数据库,它们可以位于同一个 CouchDB 实例上,也可以位于不同的 CouchDB 实例上。复制的目的是,在过程结束时,源数据库中的所有活动文档也都在目标数据库中,并且源数据库中删除的所有文档也都在目标数据库中删除(如果它们存在)。
2.1.1. 瞬时复制和持久复制¶
设置复制有两种不同的方法。CouchDB 中引入的第一种方法会导致一种可以称为 瞬时 的复制。瞬时意味着没有文档备份复制。因此,在 CouchDB 服务器重启后,复制将消失。后来,引入了 _replicator 数据库,它保存包含复制参数的文档。这种复制可以称为 持久。为了向后兼容,保留了瞬时复制。两种复制都可以具有不同的 复制状态。
2.1.2. 触发、停止和监控复制¶
持久复制通过 _replicator 数据库中的一个文档进行控制,其中每个文档描述一个复制过程(参见 复制设置)。为了设置瞬时复制,可以使用 api 端点 /_replicate。通过将 JSON 对象发送到 _replicate
端点或将其存储为 _replicator
数据库中的文档来触发复制。
如果复制当前正在运行,可以通过活动任务 API 检查其状态(参见 /_active_tasks、复制状态 和 /_scheduler/jobs)。
对于基于文档的复制,可以使用 /_scheduler/docs 获取完整的状态摘要。此 API 优先使用,因为它将显示复制文档在成为复制作业之前的状态。
对于瞬时复制,没有办法在作业完成后查询其状态。
可以通过删除文档或通过将其 cancel
属性设置为 true
来停止复制。
2.1.3. 复制过程¶
在复制过程中,CouchDB 将比较源数据库和目标数据库,以确定源数据库和目标数据库之间哪些文档不同。它通过遵循源上的 更改馈送 并将文档与目标进行比较来实现。更改以批处理的形式提交到目标,这些批处理可能会引入冲突。目标上已经存在的相同修订版本的文档不会被传输。由于文档的删除由新的修订版本表示,因此在源上删除的文档也会在目标上删除。
复制任务将在到达更改馈送的末尾时完成。如果其 continuous
属性设置为 true,它将等待新的更改出现,直到任务被取消。复制任务还会在目标上创建检查点文档,以确保重新启动的任务可以从停止的地方继续,例如在崩溃后。
当在发送节点上启动复制任务时,它被称为 *推送* 复制,如果由接收节点启动,则被称为 *拉取* 复制。
2.1.4. 主 - 主复制¶
一个复制任务只会将更改传输到一个方向。为了实现主 - 主复制,可以设置两个相反方向的复制任务。当第一个任务将更改从数据库 A 复制到 B 时,第二个任务从 B 到 A 将发现 B 上的新更改已经存在于 A 中,并将等待进一步的更改。
2.1.5. 控制要复制的文档¶
有三种选项可以控制复制哪些文档,以及跳过哪些文档
本地文档永远不会被复制(参见 本地(非复制)文档)。
选择器对象 可以包含在复制文档中(参见 复制设置)。选择器对象包含一个查询表达式,用于测试是否应该复制文档。
过滤器函数 可以用于复制(参见 复制设置)。复制任务会针对更改馈送中的每个文档评估过滤器函数。只有当过滤器返回 true
时,才会复制文档。
注意
当使用依赖于文档内容的复制过滤器时,已删除的文档可能会出现问题,因为传递给过滤器的文档将不包含任何文档内容。这可以通过向文档添加 _deleted:true
字段来解决,而不是使用 DELETE HTTP 方法,并结合使用 验证文档更新 处理程序来确保复制过滤器所需的字段始终存在。请注意,已删除的文档仍将包含其所有数据(包括附件)!
2.1.6. 将数据迁移到客户端¶
复制对于将数据更靠近客户端特别有用。 PouchDB 在 JavaScript 中实现了 CouchDB 的复制算法,使 CouchDB 数据库中的数据可以在脱机浏览器应用程序中使用,并将更改同步回 CouchDB。