可直接点击上方蓝字
(网易游戏运维平台)
关注我们,获一手游戏运维方案
![b1cc7b77d332859b9e9ac7c49bd3f364.png](https://img-blog.csdnimg.cn/img_convert/b1cc7b77d332859b9e9ac7c49bd3f364.png)
陈小生
网易游戏运维工程师,目前主要负责数据库相关的运维工作。
MongoDB Change streams 与数据订阅同步
经常会有同学过来咨询,能不能有一些办法将 MongoDB 里的数据转储至其它平台,诸如 MySQL、kafaka、ELK 等等,以达到拆分并细化业务,或者分流主库压力等目标。抛开 MongoDB 来看,一般类似需求可能会有以下几种做法:
定期从源系统导出相应数据,并导入目标存储;
伪实时拉取(推送)源系统的日志,并在目标存储进行回放;
在业务代码层面上实现双写或多写;
而这些方案基本上又都会与业务的几个理想需求相悖:
对源业务的影响尽可能的小,监控上有任何的 CPU、负载、IO 突增,我们(业务)都是不想看到的;
尽可能实时,一小时?10 分钟?5 分钟?不,我们(业务)希望的至少是秒级的同步;
不要让我们(业务)改线上的任何代码,出了问题,背锅侠在哪?
MongoDB 在 3.6 版本引入了一个叫 Change streams
的特性,业务可以基于该特性实现对单个 collection 所有数据变更的订阅。MongoDB 4.0 的发布,则带来了对 database,及整个集群(replica sets 或 sharded cluster)的数据变更订阅实现。
Change streams 利用了存储在 oplog 信息,因此并不支持单进程部署的 MongoDB;同时 Change streams 要求使用 WiredTiger 引擎。
Change Events
以下示例来自 Change Events,展示了一个 Change streams 响应中可能包含的所有字段:
{
_id : { Object> },"operationType" : "","fullDocument" : { <document> },"ns" : {
"db" : "","coll" : "
},"documentKey" : { "_id" : },"updateDescription" : {
"updatedFields" : { <document> },"removedFields" : [ "", ... ]
}"clusterTime" : ,"txnNumber" : ,"lsid" : {
"id" : ,"uid" :
}
}
名称 | 说明 |
---|---|
_id |
变更事件的 token,在重启 Change streams 时,可能需要该值 |
operationType | 变更类型,指对文档的操作,insert/update/replace/delete/ invalidate。invalidate 事件将导致 Change streams 订阅游标立即关闭。 |
fullDocument | 被修改的文档内容;当变更类型为 insert/replace 时为新文档的内容;当变更类型为 delete 时,该字段不显示;当操作为 update 时,只有 fullDocument 设置为 updateLookup 时才显示,否则 update 的内容请参考:updateDescription |
ns | 变更事件的属主(谁出现了变更),具体参考 ns.db 和 ns.coll |
ns.db | 发生变更的数据库 |
ns.coll | 发生变更的 database |
documentKey | 变更文档的 OjbectID;如果是 sharded cluster 且 _id 非 shard key 时,则同时显示 shard key |
updateDescription | 变更类型为 update 时的具体变更内容描述 |
updateDescription.updatedFields | 变更事件中文档被更新的字段 |
updateDescription.removedFields | 变更事件中文档被移除的字段 |
clusterTime | 与 oplog 的 ts 完全一致,包含时间戳及序列号 |
txnNumber | 多文档事务的事务编号,因此也只在 4.0 版本才开始出现 |
lsid | 与多文档事务关联的 session 的标识符,因此也只在 4.0 版本才开始出 |