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. 控制要复制的文档

有三种选项可以控制复制哪些文档,以及跳过哪些文档

  1. 将文档定义为本地文档。

  2. 使用 选择器对象

  3. 使用 过滤器函数

本地文档永远不会被复制(参见 本地(非复制)文档)。

选择器对象 可以包含在复制文档中(参见 复制设置)。选择器对象包含一个查询表达式,用于测试是否应该复制文档。

过滤器函数 可以用于复制(参见 复制设置)。复制任务会针对更改馈送中的每个文档评估过滤器函数。只有当过滤器返回 true 时,才会复制文档。

注意

与使用 过滤器函数 相比,使用选择器可以提高性能。应尽可能使用 选择器对象

注意

当使用依赖于文档内容的复制过滤器时,已删除的文档可能会出现问题,因为传递给过滤器的文档将不包含任何文档内容。这可以通过向文档添加 _deleted:true 字段来解决,而不是使用 DELETE HTTP 方法,并结合使用 验证文档更新 处理程序来确保复制过滤器所需的字段始终存在。请注意,已删除的文档仍将包含其所有数据(包括附件)!

2.1.6. 将数据迁移到客户端

复制对于将数据更靠近客户端特别有用。 PouchDB 在 JavaScript 中实现了 CouchDB 的复制算法,使 CouchDB 数据库中的数据可以在脱机浏览器应用程序中使用,并将更改同步回 CouchDB。