mongodb副本集源码实现-基础

副本集源码实现

1. 启动流程

db.cpp
main
mongoDbMain
initAndListen
_initAndListen
Listen
createServer(options, new MyMessageHandler() );
startReplication

这里主要分析startReplication函数
2.startReplication
boost::thread t( boost::bind( &startReplSets, replSetCmdline) ); 启动一个线程

startReplSets
ReplSet::make(*replSetCmdline))->go();
Make
Init
loadConfig();
此函数主要作用:等待副本集所依赖的成员(端口)的启动,等待初始化
初始化后启动一个线程,定时连接其他节点,作为心跳检测,
_go
loadLastOpTimeWritten    获取oplog.rs 表的最后同步时间
{ ts: Timestamp 1373520206000|1, h: 0, v: 2, op: "n", ns: "", o: { msg: "initiating set" } }
startThreads();           下面重点分析
newReplUp();            为_logOp函数指针绑定 函数,cud操作都会使用该函数先锁local库

startThreads 函数主体部分如下

void  ReplSetImpl::startThreads() {
task::fork(mgr);
mgr->send( boost::bind(&Manager::msgCheckNewState, theReplSet->mgr) );
if (myConfig().arbiterOnly) {
return;
}
boost::thread t(startSyncThread);
replset::BackgroundSync* sync = replset::BackgroundSync::get();
boost::thread producer(boost::bind(&replset::BackgroundSync::producerThread, sync));
boost::thread notifier(boost::bind(&replset::BackgroundSync::notifierThread, sync));
task::fork(ghost);
// member heartbeats are started in ReplSetImpl::initFromConfig
}

这里主要就是3个线程一个函数,startSyncThread,producerThread,notifierThread,msgCheckNewState下面了解一下这3个线程的各自的作用和函数msgCheckNewState的作用

(1)msgCheckNewState    节点状态切换,投票选举等,这里就不详细分析

(2)producerThread  线程分析(只有从节点才起该线程)
_producerThread
Produce
getOplogReader   获取一个同步数据节点
tailingQueryGTE   获取同步节点的oplog数据
{                把同步到的oplog数据存入buffer中
BSONObj o = r.nextSafe().getOwned();
_buffer.push(o);
}

(3) startSyncThread   线程分析

while(1)
_syncThread        下面详见主体部分
void ReplSetImpl::_syncThread() {
       // Check criteria for doing an initial sync:
        // 1. If the oplog is empty, do an initial sync
        // 2. If minValid has _initialSyncFlag set, do an initial sync

if (lastOpTimeWritten.isNull() || getInitialSyncFlag()) {
syncDoInitialSync();
return; // _syncThread will be recalled, starts from top again in case sync failed.
}

  /* we have some data.  continue tailing. */
replset::SyncTail tail(replset::BackgroundSync::get());
tail.oplogApplication();
}
函数加粗部分的说明已经说明了函数的作用,就是从主节点获取oplog
tail.oplogApplication();
multiApply               此函数把前一个producerThread 线程读取的日志写入自身数据库
applyOpsToOplog         更新同步的最新时间戳

(3)notifierThread    (比较不好理解)大概意思就是通知服务端,我们已经成功接同步数据了

总结: 副本集 的实现原理,就是一个线程不停的进行心跳检测及节点状态改变投票选举

一个线程从服务节点(不一定是主节点)获取oplog数据放到自身的buffer中

一个线程从自身的buffer中把数据同步到自身的数据库中

一个线程通知服务节点数据同步完毕

线程之间的配合用到了wait,notify机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值