Change Streams 生产建议

MongoDB

如果您在开启Change Streams的情况下删除或重命名集合或数据库,则Change Streams光标在操作日志 (oplog) 中移到该点时将关闭。使用含有 fullDocument : updateLookup 选项的Change Streams光标可能会为查找文档返回 null 值。

尝试对已删除的集合恢复Change Streams将导致错误。在Change Streams捕捉到的最后一次事件与集合删除事件之间,该集合上发生的任何数据变更都将丢失。

Change Streams响应文档必须遵循 16MB 的 BSON 文档大小限制。根据打开Change Streams集合中的文档大小,若生成的通知文档超出 16MB,则无法发送。例如,对配置为返回完整更新文档的Change Streams更新操作,或对文档大小等于或略低于限制的文档进行插入/替换操作。

副本集

对于带有仲裁器成员的副本集,若没有足够的数据承载成员导致大部分操作无法完成,则Change Streams可能会一直处于空闲状态。

例如,一个带有两个数据承载节点和一个仲裁器的 3 成员副本集。如果次要节点由于故障或升级而不可用,则大部分写入操作无法完成。Change Streams将保持打开的状态,但不会发送任何通知。

在这种情况下,只要应用程序接收到的最后一个操作仍然在副本集的 oplog 里,该应用程序就能同步停机期间的所有操作。

如果预估停机时间会较长(比如升级或重大灾难),则需考虑增加操作日志的大小,从而使操作保留的时间比预计的停机时间更长。可以用 rs.printReplicationInfo()来检索 oplog 的大小以及保存的操作的时间范围等关于操作日志状态的信息。

分片集群

Change Streams通过全局逻辑时钟提供整个分片的变更排序。MongoDB 确保变更顺序得以保留,且Change Streams通知能够按接收时的顺序安全地解释。例如,为 3 个分片集群打开Change Streams光标时会依照这 3 个分片上的变更顺序返回变更通知。

为确保变更的整体排序,mongos会针对每个变更通知检查每个分片,确认该分片是否存在最近的变更。如果分片集群有一或多个分片且分片的集合几乎没有活动或处在“冷”状态,则会给Change Streams的响应时间带来负面影响。这是因为 mongos仍必须检查这些冷分片以确保变更整体排序正确。对于分散的分片或大多数操作发生在集群中分片子集的工作负载来说,这种影响可能会更加明显。

如果分片集合中有高水平活动,mongos可能无法跟上所有分片上的变更。此时应考虑为此类集合使用通知筛选。例如,传递配置为仅筛选插入操作的 $match管道。

对于分片集合,利用 multi : true更新操作可能会导致针对该集合打开的Change Streams为孤立文档发送通知。

从未分片的集合被分片那一刻到Change Streams追上第一批迁移的时间,Change Streams通知文档中的 documentKey 只包含文档的 _id,而不包括完整的分片键。

索引和性能

Change Streams无法使用索引。MongoDB 不支持在 oplog 集合上创建索引。 因此,避免打开大量专门的Change Streams,否则会影响服务器性能。

Change Streams优化

从 MongoDB 5.1 开始,Change Streams会经过优化,实现更高效的资源利用率和加速某些聚合管道阶段的执行。

Change Streams和孤立文档

从 MongoDB 5.3 开始,范围迁移期间,不会生成Change Streams事件来更新孤立文档