IBM Cloud Docs
高级复制

高级复制

您可以了解高级复制概念和任务,例如以下列表中的概念和任务等:

  • 维护复制数据库
  • 调度和监视复制
  • 复制期间认证

您可能还会发现查看底层的详细信息很有用。 复制协议,并查看 API 参考 文档。

复制数据库维护

必须像任何其他数据库一样监视复制数据库。 如果没有常规数据库维护,那么可能会累积因复制过程中断而导致的无效文档。 当复制器进程通过 IBM® Cloudant® for IBM Cloud® 操作重新启动时,具有许多无效文档可能会导致集群上的过量负载。

要维护复制数据库,请除去旧文档。 您可以通过确定旧文档的存在时间并 删除 (如果不再需要旧文档) 来将其除去。

复制调度程序

与先前的 IBM Cloudant 复制机制相比,新的 IBM Cloudant 复制调度程序提供了许多改进和增强功能。

特别是,复制期间的网络使用效率更高。 调度程序在确定复制任务的分配时,会对集群中各个数据库节点的当前负载进行记帐。

最后,复制的状态现在更详细,由七个不同的状态组成:

  1. initializing-复制已添加到调度程序,但尚未初始化或调度运行。 当新的或更新的复制文档存储在 _replicator 数据库 中时,会发生此状态。
  2. error-无法将复制转换为作业。 此错误可能以多种不同方式导致。 例如,必须对复制进行 过滤,但无法从源数据库访存过滤器代码。
  3. pending-复制作业已调度为运行,但尚未运行。
  4. running-复制作业正在运行。
  5. crashing-发生了影响复制作业的临时错误。 稍后将自动重试该作业。
  6. completed-复制作业已完成。 此状态不适用于 连续复制
  7. failed- 复制任务失败。 该故障是永久性的。 此状态表示不再尝试使用此复制任务进行复制。 例如,如果源 URL 或目标 URL 无效,那么可能以多种不同方式导致失败。

下图说明了这些状态之间的转换:

状态之间的转换为 ,, 和 。
Replication Scheduler states

调度程序引入了两个新端点:

您可以使用这些端点更快,更轻松地管理和确定复制状态。

请参阅使用复制调度程序来管理和监视复制的典型过程:

  1. 创建描述所需复制的 复制文档,并将该文档存储在 复制器数据库 中。
  2. 使用 /_scheduler/docs 端点监视复制的状态。

复制期间的认证

在任何生产应用程序中,源数据库和目标数据库的安全性至关重要。 为了继续复制,需要认证才能访问数据库。 缺省情况下, 已启用用于复制的检查点,这意味着复制源数据库需要写访问权。

要在复制期间启用认证,请在数据库 URL 中包含用户名和密码。 复制过程使用为 HTTP 基本认证提供的值。

请参阅以下指定用于在复制期间访问源数据库和目标数据库的用户名和密码值的示例:

{
  "source": {
    "url": "https://example.com/db",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "target": {
    "url": "https://$ACCOUNT.cloudant.com/db",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  }
}

对于 IAM 凭据,请使用下面的示例使用 IAM API 密钥进行身份验证:

{
  "source": {
    "url": "https://example.com/db",
    "auth": {
      "iam": {
        "apikey": "$APIKEY"
      }
    }
  },
  "target": {
    "url": "https://$ACCOUNT.cloudant.com/db",
    "auth": {
      "iam": {
        "apikey": "$APIKEY"
      }
    }
  }
}

过滤复制

有时,您不希望将所有文档从源传输到目标。 要选择要传输的文档,请在源上的设计文档中包含一个或多个过滤器函数。 然后,您可以告诉复制器使用这些过滤函数。

在复制期间过滤文档类似于 过滤 _changes 订阅源

过滤函数采用两个自变量:

  • 要复制的文档。
  • 复制请求。

过滤器函数返回 truefalse 值。 如果结果为 true,那么将复制文档。

要设置过滤,请尽可能使用 selector 字段。 使用 selector 字段时,可以指定过滤器,而不必复制整个数据库。 此方法使过滤速度更快,并使 IBM Cloudant上的负载更少。 有关更多信息,请参阅 selector 字段 文档。

请参阅下面的过滤器函数示例:

function(doc, req) {
	return !!(doc.type && doc.type == "foo");
}

过滤器存储在设计文档的最顶层 filters 键下。

请参阅以下在设计文档中存储过滤器函数的示例:

{
	"_id": "_design/myddoc",
	"filters": {
		"myfilter": "function goes here"
	}
}

已过滤的复制是通过使用标识以下项的 JSON 语句启动的:

  • 源数据库。
  • 目标数据库。
  • 存储在设计文档的 filters 键下的过滤器的名称。

请参阅示例 JSON 以启动已过滤的复制:

{
  "source": {
    "url": "https://example.org/example-database",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "target": {
    "url": "https://$ACCOUNT.cloudant.com/example-database",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "filter": "myddoc/myfilter"
}

可以通过在调用的 query_params 字段中包含“键: 值”对来向过滤器函数提供自变量。

请参阅示例 JSON,以使用提供的参数启动已过滤的复制:

{
  "source": {
    "url": "https://example.org/example-database",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "target": {
    "url": "https://$ACCOUNT.cloudant.com/example-database",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "filter": "myddoc/myfilter",
  "query_params": {
    "key": "value"
  }
}

与使用 filter 选项相比,selector 选项提供了性能优势。 尽可能使用 selector 选项。 有关更多信息,请参阅 selector 文档。

消除使用复制的冲突

使用 winning_revs_only: true 选项仅复制 获胜 文档修订版。 这些修订版是缺省情况下将由 GET $ACCOUNT/$DATABASE/$DOCID API 端点返回的修订版,或者显示在 带有缺省参数的 _changes 订阅源。

{
	"source": {
	  "url": "https://example.org/example-database",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"target": {
	  "url": "https://$ACCOUNT.cloudant.com/example-database",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"winning_revs_only": true
}

使用此方式的复制会废弃有冲突的修订版,因此可以通过复制来除去冲突。

复制标识和检查点标识,由 winning_revs_only: true 生成 复制与缺省情况下生成的复制不同,因此可以先复制获胜的修订版,然后再复制到 使用常规复制作业 回填 其余修订版。

winning_revs_only: true 选项可与过滤器或其他选项 (例如 continuous: truecreate_target: true) 组合使用。

指定文档复制

有时,您不希望复制文档。 对于简单复制,您不需要编写过滤器函数。 相反,要复制特定文档,请在 doc_ids 字段中添加键列表作为数组。

请参阅以下特定文档的示例复制:

{
	"source": {
	  "url": "https://example.org/example-database",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"target": {
	  "url": "https://127.0.0.1:5984/example-database",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"doc_ids": ["foo", "bar", "baz"]
}

user_ctx 属性和授权

复制文档可以具有定制 user_ctx 属性。 此属性定义在其下运行复制的用户上下文。

通过将 POST 设置为 /_replicate/ 端点来触发复制的较旧方法不需要 user_ctx 属性。 原因是在触发复制时,提供了有关已认证用户的所有必需信息。

相比之下,复制器数据库是常规数据库。 只有在将复制文档写入数据库时,才会显示有关已认证用户的信息。 换言之,复制器数据库实现类似于设置了 ?include_docs=true_changes 订阅源使用应用程序。

对于复制,此实现差异意味着对于非管理员用户,必须在复制文档中定义包含用户名称及其角色子集的 user_ctx 属性。 此需求由复制器数据库的缺省设计文档中提供的验证功能解决。 此函数将验证每个文档更新。 此验证功能还确保非管理员用户无法在 user_ctx 属性中设置与正确用户名不对应的用户名属性。 同样的原则也适用于角色。

请参阅以下委托复制文档示例:

{
	"_id": "my_rep",
	"source": {
	  "url": "https://$SERVER.com:5984/foo",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"target": {
	  "url": "https://$ACCOUNT.cloudant.com/bar",
	  "auth": {
	    "basic": {
	      "username": "$USERNAME",
	      "password": "$PASSWORD"
	    }
	  }
	},
	"continuous":  true,
	"user_ctx": {
		"name": "joe",
		"roles": ["erlanger", "researcher"]
	}
}

对于管理员,user_ctx 属性是可选的。 如果缺少该属性,那么该值将缺省为名称为 null 的用户上下文以及角色的空列表。

角色的空列表表示在复制期间不会将设计文档写入本地目标。 如果要将设计文档写入本地目标,那么必须显式设置具有 _admin 角色的用户上下文。

另外,对于管理员,可以使用 user_ctx 属性来触发另一个用户的复制。 此用户上下文将传递到本地目标数据库文档验证函数。

user_ctx 属性仅适用于本地端点。

总之,对于管理员,user_ctx 属性是可选的。 对于常规 (非管理员) 用户,这是必需的。 缺少 user_ctx 的角色属性时,缺省为空列表 [ ]

大附件的影响

在文档上具有大量附件可能会对复制性能产生不利影响。

有关附件对复制性能的影响的更多信息,请参阅 性能注意事项

避免使用 /_replicate 端点

使用 _replicator 调度程序 而不是 /_replicate 端点。

如果在复制期间发生问题 (例如,延迟,超时或应用程序崩溃),那么系统会自动重新启动在 _replicator 数据库中定义的复制。 但是,如果通过向 /_replicate 端点发送请求来定义复制,那么如果由于复制请求未持久存储而发生问题,那么系统无法将其重新启动。 _replicator 数据库中定义的复制更易于监视。