MongoDB学习【五】Change Streams

Change Streams

一、Change Stream是什么?

Change Stream是MongoDB从3.6开始支持的新特性。

Change Stream即变更流,是MongoDB向应用发布数据变更的一种方式。即当数据库中有任何数据发生变化,应用端都可以得到通知。我们可以将其理解为在应用中执行的触发器。至于应用想得到什么数据,以什么形式得到数据,则可以通过聚合框架加以过滤和转换。

参考地址:https://mongoing.com/change-stream

官方文档地址:https://docs.mongodb.com/manual/changeStreams/

二、Change Stream的原理

我们先来看一下MongoDB复制集大致是如何工作的:

  1. 应用通过驱动向数据库发起写入请求;
  2. 在同一个事务中,MongoDB完成oplog和集合的修改;
  3. oplog被其他从节点拉走;
  4. 从节点应用得到的oplog,同样在一个事务中完成对oplog和集合的修改;

至此,复制集同步完成。可以发现,整个同步过程是依赖于oplog来进行的。如果观测oplog的变化,就能够得到所有变更的数据。change stream正是基于这个原理实现的。

三、Change Stream的使用

启动复制集,打开一个shell,订阅你需要关注的集合,并在这个shell中不断遍历这个游标以获取新数据:

rs_test:SECONDARY> var cursor = db.score.watch()
rs_test:SECONDARY> while(true){if(cursor.hasNext()){print(JSON.stringify(cursor.next()))}}

接下来打开另一个shell做CRUD的基本操作,以测试不同的Change Events输出的变更内容:

1、insert Event

rs_test:PRIMARY> db.score.insert({uid:"uid20001",grade:5,class:1,subject:"math",score:90,createTime:Date()})

插入数据时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02F125000000012B022C0100296E5A10044B22BC6860404A9C96301E8CEC60899E46645F696400645F02F125E7BA0AAA65B2E6F90004"
    },
    "operationType":"insert",
    "clusterTime":{
        "$timestamp":{
            "t":1594028325,
            "i":1
        }
    },
    "fullDocument":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        },
        "uid":"uid20001",
        "grade":5,
        "class":1,
        "subject":"math",
        "score":90,
        "createTime":"Mon Jul 06 2020 17:38:45 GMT+0800"
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    },
    "documentKey":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        }
    }
}

2、update Event

rs_test:PRIMARY> db.score.update({uid:"uid20001"},{$set:{class:3,updateTime:Date()}})

更新数据时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02F615000000012B022C0100296E5A10044B22BC6860404A9C96301E8CEC60899E46645F696400645F02F125E7BA0AAA65B2E6F90004"
    },
    "operationType":"update",
    "clusterTime":{
        "$timestamp":{
            "t":1594029589,
            "i":1
        }
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    },
    "documentKey":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        }
    },
    "updateDescription":{
        "updatedFields":{
            "class":3,
            "updateTime":"Mon Jul 06 2020 17:59:49 GMT+0800"
        },
        "removedFields":[
        ]
    }
}

3、replace Event

rs_test:PRIMARY> db.score.replaceOne({uid:"uid20001"},{uid:"uid20002",grade:6,class:6,subject:"chinese",score:98,createTime:Date(),updateTime:Date()})

替换文档时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02F828000000012B022C0100296E5A10044B22BC6860404A9C96301E8CEC60899E46645F696400645F02F125E7BA0AAA65B2E6F90004"
    },
    "operationType":"replace",
    "clusterTime":{
        "$timestamp":{
            "t":1594030120,
            "i":1
        }
    },
    "fullDocument":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        },
        "uid":"uid20002",
        "grade":6,
        "class":6,
        "subject":"chinese",
        "score":98,
        "createTime":"Mon Jul 06 2020 18:08:40 GMT+0800",
        "updateTime":"Mon Jul 06 2020 18:08:40 GMT+0800"
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    },
    "documentKey":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        }
    }
}

4、delete Event

rs_test:PRIMARY> db.score.deleteOne({uid:"uid20002"})

删除文档时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02F8EB000000012B022C0100296E5A10044B22BC6860404A9C96301E8CEC60899E46645F696400645F02F125E7BA0AAA65B2E6F90004"
    },
    "operationType":"delete",
    "clusterTime":{
        "$timestamp":{
            "t":1594030315,
            "i":1
        }
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    },
    "documentKey":{
        "_id":{
            "$oid":"5f02f125e7ba0aaa65b2e6f9"
        }
    }
}

5、drop Event

rs_test:PRIMARY> db.score.drop()

删除集合时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02FA07000000012B022C0100296E5A10044B22BC6860404A9C96301E8CEC60899E04"
    },
    "operationType":"drop",
    "clusterTime":{
        "$timestamp":{
            "t":1594030599,
            "i":1
        }
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    }
}


//invalidate Event
{
    "_id":{
        "_data":"825F02FA07000000012B022C0100296F5A10044B22BC6860404A9C96301E8CEC60899E04"
    },
    "operationType":"invalidate",
    "clusterTime":{
        "$timestamp":{
            "t":1594030599,
            "i":1
        }
    }
}

6、rename Event

rs_test:PRIMARY> db.score.renameCollection("score_new")

集合重命名时,输出变更数据如下:

{
    "to":{
        "db":"aggtest",
        "coll":"score_new"
    },
    "_id":{
        "_data":"825F02FC74000000012B022C0100296E5A1004377F141A69914F99ACDDFB9D89863EAE04"
    },
    "operationType":"rename",
    "clusterTime":{
        "$timestamp":{
            "t":1594031220,
            "i":1
        }
    },
    "ns":{
        "db":"aggtest",
        "coll":"score"
    }
}


//invalidate Event
{
    "_id":{
        "_data":"825F02FC74000000012B022C0100296F5A1004377F141A69914F99ACDDFB9D89863EAE04"
    },
    "operationType":"invalidate",
    "clusterTime":{
        "$timestamp":{
            "t":1594031220,
            "i":1
        }
    }
}

7、dropDatabase Event

rs_test:PRIMARY> db.dropDatabase()

删除当前数据库时,输出变更数据如下:

{
    "_id":{
        "_data":"825F02FE76000000012B022C0100296E5A1004377F141A69914F99ACDDFB9D89863EAE04"
    },
    "operationType":"drop",
    "clusterTime":{
        "$timestamp":{
            "t":1594031734,
            "i":1
        }
    },
    "ns":{
        "db":"aggtest",
        "coll":"score_new"
    }
}


//invalidate Event
{
    "_id":{
        "_data":"825F02FE76000000012B022C0100296F5A1004377F141A69914F99ACDDFB9D89863EAE04"
    },
    "operationType":"invalidate",
    "clusterTime":{
        "$timestamp":{
            "t":1594031734,
            "i":1
        }
    }
}

8、invalidate Event

对于针对集合打开的变更流,影响监视的集合的 drop eventrename event 或者 dropDatabase event 将导致  invalidate event 

对于针对数据库打开的变更流,影响监视数据库的 dropDatabase event 将导致  invalidate event 

invalidate event 将关闭更改流游标 。

resumeAfter在 invalidate event (例如,集合删除或重命名)关闭流之后,不能用来恢复更改流。从MongoDB 4.2开始,您可以使用 startAfter 在 invalidate event 之后启动新的更改流 。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章