DBA MongoDB 变更流
功能概述
Change Stream(3.6新增)与MySQL中的触发器概念很像,但是又有一些区别,且实现原理完全不同:
Change Stream | 触发器 | |
---|---|---|
触发方式 | 异步 | 同步(事务保证) |
触发位置 | 应用回调事件 | 数据库触发器 |
触发次数 | 每个订阅事件的客户端 | 1次 |
故障恢复 | 从上次断点重新触发 | 事务回滚 |
对于触发器来讲,触发器是包含在事务期间的,触发器中进行回滚该事务也会进行回滚,是属于同步操作。
而对于变更流来讲,它的事件是属于异步的,这是两者较大的一个区别。
实现原理
变更流基于oplog实现,它会在oplog上开启一个tailable cursor(尾部游标)来追踪所有复制集上的变更操作,最终调用应用中定义的回调函数。
被追踪的变更时间主要包括:
- insert/update/delete
- collection.drop
- rename
- dropDatabase
- invalidate:以上操作会导致invalidate被处罚,并关闭change stream
使用条件
变更流只推送已经在大多数节点上提交的变更操作,即{ readConcern : {“level” : “majority”}},如果该readConcern的配置项不是majority,则该集群无法使用变更流。
除此之外,对于不是{ writeConcern : {“w” : “majority”}}的变更操作,也不会触发变更流
使用方式
对一个集合进行启动监听订阅,当某些操作发生后执行管道中对应的处理逻辑,如下所示:
> pipeline = [
{'$match': {'fullDocument.username': 'alice'}},
{'$addFields': {'newField': 'this is an added field!'}}
]
> db.collection.watch(pipeline)
在上述示例中,过滤出所有名字为alice的文档,并且在变更操作发生后对其新增字段。
配置变更流时,可提供的管道步骤如下所示:
$addFields
$match
$project
$replaceRoot
$replaceWith - 从MongoDB 4.2开始可用
$redact
$set - 从MongoDB 4.2开始可用
$unset - 从MongoDB 4.2开始可用
如果你想了解更多关于变更流的使用,请参阅官方中文文档
使用场景
变更流的使用场景较为广泛,下面的常见非常适用于使用变更流:
- 跨集群的变更复制:源集群中订阅变更流,如果有变更操作则立即写入目标集群
- 微服务联动,当一个微服务变更数据库时,其他微服务得到通知并作出相应的变更
- 其他需要系统联动的场景