使用 IBM Cloudant 更改订阅源常见问题解答
IBM Cloudant 数据库的更改订阅源的主要用例是将数据从源复制到目标数据库。 构建 IBM Cloudant 复制器以处理更改订阅源并运行必要的检查,以确保将数据准确复制到其目标。
IBM Cloudant 具有原始 更改订阅源 API ,可用于使用单个数据库的更改,但必须谨慎使用。
可以通过多种方式使用 _changes
API 端点,并且可以输出各种格式的数据。 但在这里,我们关注的是最佳实践以及在针对 _changes
API 进行开发时如何避免一些陷阱。
如何使用更改订阅源?
给定单个数据库 orders
,我可以向数据库请求更改列表,在这种情况下,使用 ?limit=5
将结果集限制为五个更改:
GET /orders/_changes?limit=5
{
"results": [
{
"seq": "1-g1AAAAB5eJzLYWBg",
"id": "00002Sc12XI8HD0YIBJ92n9ozC0Z7TaO",
"changes": [
{
"rev": "1-3ef45fdbb0a5245634dc31be69db35f7"
}
]
},
....
],
"last_seq": "5-g1AAAAB5eJzLYWBg"
}
API 调用将返回以下更改:
results
- 更改数组。
last_seq
- 可以在后续 API 调用中提供给更改端点以获取下一批更改的令牌。
请参阅以下示例中的 "如何访存下一批更改":
GET /orders/_changes?limit=5&since=5-g1AAAAB5eJzLYWBg
{
"results": [ ...],
"last_seq": "10-g1AAAACbeJzLY"
}
since
参数用于定义要从以下内容开始的更改订阅源中的位置:
since=0
- 更改订阅源的开始。
since=now
- 更改订阅源的结束。
since=<a last seq token>
- 从更改订阅源中的已知位置。
在面值上,遵循更改订阅源似乎很简单,就像将 _changes
API 调用链接在一起一样。 然后, IBM Cloudant 将 last_seq
从一个 changes feed
响应传递到下一个请求的 since
参数。 但与变化相关的一些细微问题需要进一步讨论。
为什么更改订阅源至少一次交付每个更改?
IBM Cloudant 标准更改订阅源承诺将返回每个文档 至少一次,这与承诺仅返回每个文档 _一次_不同。 换句话说, changes feed
的使用者可以再次看到相同的更改,也可以看到一组重复的更改。
更改订阅源的使用者必须 _视情况_处理更改。 在实践中,您必须记住在触发来自更改的操作之前是否已处理更改。 天真的更改订阅源使用者可能会在接收到的每个更改时向智能手机发送一条消息。 但是,如果发生重放更改时未对更改进行幂等处理,那么用户可能会接收到重复的文本消息。
通常这些 "倒风" 的变化饲料是短的,只重放少数几个变化。 但在某些情况下,请求可能会看到具有数千个已重放更改的响应-可能是从时间开始的所有更改。 rewinds
的潜力使 changes feed
不适合期望类似队列的行为的应用程序。
要重申, IBM Cloudant的更改订阅源承诺在更改订阅源中 至少一次 交付文档,并且对多个请求中的重复值不作任何保证。
更改订阅源是否以 "实时" 方式运行?
更改订阅源无法保证传入更改对使用更改订阅源的客户机显示的速度。 开发应用程序时不得假定数据插入,更新和删除会立即传播到更改阅读器。
为什么所有个别文档更改都不会显示在更改订阅源中?
如果在更改订阅源调用之间多次更新文档,那么更改订阅源可能仅反映这些更改中的最新更改。 客户机不会接收到对每个文档的每个更改。
IBM Cloudant 更改订阅源不是包含按时间顺序发生的每个事件的 事务日志 。
我能否将过滤后的更改订阅源用于操作查询?
过滤更改订阅源,并通过扩展,运行已过滤的复制有其用途:
- 正在将数据从源复制到目标,但忽略已删除的文档。
- 复制数据但没有索引定义 (设计文档)。
此 博客帖子 描述了在复制期间提供 selector
如何使这些用例的工作顺利运行。
附带 selector
参数的更改订阅源 不是 从数据库中例行抽取数据片的方法。 不得将其用作对数据库运行操作查询的方法。 过滤后的更改很慢 (过滤器将依次应用于每个已更改的文档,而无需索引的帮助)。 此过程比创建辅助索引 (例如 MapReduce 视图) 和查询该视图要慢得多。
feed=continuous
更改订阅源是否继续无限期运行?
否, IBM Cloudant 不保证连续更改订阅源的连接持续时间。 由于各种原因 (包括维护,安全性或网络错误) ,服务器可能会定期将其断开连接。 使用更改订阅源的代码必须设计为使用最近保存的序列标识作为 since
值,以在发生错误或断开连接后发出恢复更改订阅源的新请求。
为什么更改订阅源不保证时间排序?
如果用例基于以下语句,那么无法使用 IBM Cloudant 更改订阅源来实现此结果。
"Fetch me every document that has changed since a known date, in the order they were written."
IBM Cloudant 数据库不会记录写入每个文档更改的时间。 更改订阅源不会保证订阅源中更改的顺序-不保证这些更改的顺序与发送到数据库的顺序相同。
但是,您可以通过在文档主体中存储更改日期来实现此用例:
{
"_id": "2657",
"type": "order",
"customer": "bob@aol.com",
"order_date": "2022-01-05T10:40:00",
"status": "dispatched",
"last_edit_date": "2022-01-14T19:17:20"
}
您可以创建以 last_edit_date
为键的 MapReduce 视图:
function(doc) {
emit(doc.last_edit_date, null)
}
可以查询此视图以返回在提供的日期和时间或之后修改的任何文档:
/orders/_design/query/_view/by_last_edit?startkey="2022-01-13T00:00:00"
此方法将生成一组按时间排序的结果,并且不会以可执行和可重复的方式重复值。 此数据的使用者 不 需要以幂等方式管理数据,从而实现更简单的开发过程。
现在,什么是 IBM Cloudant 更改订阅源?
IBM Cloudant 更改订阅源适用于以下任务:
- 为 IBM Cloudant 复制提供电源, (可选) 使用选择器来过滤某些更改。
- 客户以批处理方式使用更改订阅源,但在不关注排序顺序且期望多次看到某些更改的情况下,以低效方式处理每个更改。
IBM Cloudant 更改订阅源不利于以下组件:
- 消息队列。 有关更多信息,请参阅 IBM Messages for RabbitMQ 以管理队列。
- 消息代理。 有关更多信息,请参阅 IBM Event Streams ,以处理可伸缩的按时间顺序排列的事件流。
- 实时发布和订阅系统。 有关更多信息,请参阅 IBM Databases for Redis 以处理发布和预订主题。
- 事务日志。 某些数据库将每个更改存储在事务日志中,但 IBM Cloudant 的分布式且最终一致的性质表示不存在明确的时间排序事务日志。
- 查询机制。 有关更多信息,请参阅 MapReduce 视图 ,以创建按您选择的键排序的数据视图。