内容来源:2017年2月25日,讯联数据高级软件工程师马艳云在“New version, New vision”进行《基于Go的MongoDB实时同步工具及Docker化实践》演讲分享。IT 大咖说(ID:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。
阅读字数:1772 | 4分钟阅读
获取嘉宾演讲视频回放及PPT,请点击:http://t.cn/E7JofKR
摘要
讯联数据高级软件工程师马艳云分享了基于Go的MongoDB实时同步工具Magisync及 Docker化实践。
Magisync是什么
Magisync是用Go语言开发的MongoDB到MongoDB或其他多种数据库之间的实时同步工具。
为什么选择 Go
在我们的生产应用当中,对Go语言有比较成熟的应用。我们的核心交易系统就是 Go 语言开发的。从开发到运行,Go 语言相对来说语法比较简单,使用方便。还有一个原因就是在 GitHub 上有一个用 Go 语言开发的同步的程序可以供我们参考。
为什么开发 Magisync
交易量日益增多,从2015年8月到2016年8月,我们的交易量整整增长了100倍,原有的系统架构不能满足业务需求。我们要通过数据库拆分实现冷热数据分离,灾备系统的搭建要跨机房同步,这一系列需求导致我们需要找到一个工具能够支持MongoDB的数据,而当时市面上并没有适合我们的MongoDB实时同步工具。
于是我们不得不自己开发这样一款工具,但当时对于我们来说这也是非常具有挑战性的一件事,因为我们做金融支付对数据的实时一致性要求非常高。
Magisync 同步特性
支持从特定时间点开始同步,支持选择同步特定表的特定类型的操作,支持断点续传式同步,QPS目前在3000左右,支持限流。
Magisync 同步原理
简单来说,Magisync一直监听MongoDB的日志集合oplog ,如果源数据库有新的操作产生,oplog集合中会生成有新的记录,这时,Magisync会立刻拿到oplog中新的日志记录,并将其实时的同步至目标数据库。Magisync同步的核心就是oplog。
Oplog
Oplog是MongoDB的复制集存储写操作的一个日志,它的存储位置是在local库的oplog.rs表中。这张表是Capped Collection类型,是MongoDB特有的一种类型,可以用类似于Unix中的tail -f命令来获取oplog。
Oplog 的格式
不同版本的 oplog 的格式稍有不同,我们生产环境使用的 MongoDB的版本是3.0.3, oplog 示例如下:
{
"ts" : Timestamp(1477194593, 1),
"t" : NumberLong(12),
"h" : NumberLong(8657529515144482533),
"v" : NumberInt(2),
"op" : "i",
"ns" : "caroldb.user",
"o" : {
"_id" : ObjectId("580c333e7afa56085f89a00d"),
"name" : "mike",
"age" : NumberInt(20)
}
}
Magisync 特性说明
1、Magisync如果重启,如何知道该从哪个时间点同步?
Magisync各个协程去往目标数据同步之后,会将同步的状态写入oplogMonitor表中,每个协程在oplogMonitor表中都有一条对应的记录。等到Magisync重启时,则会读取oplogMonitor中最小的ts ,然后去源数据库拉取oplog。
2、Magisync用多协程去执行oplog,如何保证oplog执行不会错序?
主线程读取到oplog后,会解析出ObjectId,取模后将其放入各个worker对应的chan中。同一条数据,插入,更新等操作会进去到同一个worker中。
3、Magisync的故障处理机制?
如果读取oplog失败,Magisync会重连,重新读取oplog ; 如果操作目标数据库失败,Magisync会根据情况判断是否需要重连,或者重试。
4、Magisync如何限流?
限流采用的是令牌桶的算法,会有一个协程定时的(比如每秒)向一个桶里放一定数量的令牌。主线程每读取一条oplog,计算oplog的大小,从桶里消费对应的令牌数,然后对比桶里剩下的令牌数,如果小于0,则阻塞,直到下一秒桶里被放入令牌,阻塞解除。
Docker化实践
我们为什么要使用Docker?首先是因为它真的很火,很多大型互联网公司都支持Docker,比如腾讯、京东、美团等等。并且Docker可以快速构建应用环境,可移植性高。
Magisync 代码示例
1、读取oplog代码
2、向目标数据库写数据
我今天的分享就到这里,谢谢大家!