当前位置: 首页 > news >正文

手机网站模板 html5 下载工具做网站设计需要学什么

手机网站模板 html5 下载工具,做网站设计需要学什么,化妆品网站建设报告,项目计划书怎么写1. ReplSet源码结构 rs_config.h replSet间同步设置的工具类 rs_member.h 心跳检测类和replSet成员状态的定义 rs_sync.h 同步数据类 rs.h 定义了几乎所有replSet相关的类#xff08;Member:replSet中的节点成员#xff0c; GhostSync#xff1a;备份同步类#xff0c;Rep… 1. ReplSet源码结构 rs_config.h replSet间同步设置的工具类 rs_member.h 心跳检测类和replSet成员状态的定义 rs_sync.h 同步数据类 rs.h 定义了几乎所有replSet相关的类Member:replSet中的节点成员 GhostSync备份同步类ReplSet管理所有Member的核心类 2. ReplSet的结构分析 RSBase定义了线程锁。 ReplSetImpl完成了大部分Replication Set的操作心跳检测选举设置主节点查询节点信息。 Member记录其他节点的信息Manager查询节点信息ReplSetHealthPoolTask心跳检测ReplSetConfig同步设置Consensus选举主节点StateBox设置主节点。 ReplSet封装了很多方便的操作。 3. 创建并设置ReplSet 在mongod开始运行后(mongoDBMain)会启动监听程序同时根据运行参数中是否标明了”--replSet”调用startReplication来创建ReplSet。void startReplication() {        /* if we are going to be a replica set, we arent doing other forms of replication. */        if( !cmdLine._replSet.empty() ) {  //看看参数里面有没有--replSet            if( replSettings.slave || replSettings.master ) {   //这个参数不能与—slave与—master共存                log()  ***  endl;                log()  ERROR: cant use --slave or --master replication options with --replSet  endl;                log()  ***  endl;            }            newRepl(); //将自己标示成为一个新的Replication节点            replSet  true;            ReplSetCmdline *replSetCmdline  new ReplSetCmdline(cmdLine._replSet);            boost::thread t( boost::bind( startReplSets, replSetCmdline) );  //启动线程完成真正的ReplSet创建            return;        }        //……   }    void startReplSets(ReplSetCmdline *replSetCmdline) {  //线程中执行的函数        Client::initThread(rsStart);        try {            verify( theReplSet  0 );            if( replSetCmdline  0 ) {                verify(!replSet);                return;            }            replLocalAuth();            (theReplSet  new ReplSet(*replSetCmdline))-go(); //创建一个ReplSet赋值到一个全局的指针中随即调用go启动        }        catch(std::exception e) {            log()  replSet caught exception in startReplSets thread:   e.what()  rsLog;            if( theReplSet )                theReplSet-fatal();        }        cc().shutdown();    }  在构造ReplSetImpl时会调用ReplSetImpl::loadConfig去设置ReplSet。 void ReplSetImpl::loadConfig() {        startupStatus  LOADINGCONFIG; //标注状态为读取config        startupStatusMsg.set(loading   rsConfigNs   config (LOADINGCONFIG));        LOG(1)  loadConfig()   rsConfigNs  endl;        while( 1 ) {   //循环获取配置            try {                vectorReplSetConfig configs;                try {                    configs.push_back( ReplSetConfig(HostAndPort::me()) );  //尝试从本机端口获取配置                }                catch(DBException e) {                    log()  replSet exception loading our local replset configuration object :   e.toString()  rsLog;                }                //这里的种子是用户配置的                for( vectorHostAndPort::const_iterator i  _seeds-begin(); i ! _seeds-end(); i ) {                       try {                        configs.push_back( ReplSetConfig(*i) );   //尝试从其他设备上获取配置                    }                    catch( DBException e ) {                        log()  replSet exception trying to load config from   *i   :   e.toString()  rsLog;                    }                }                {                    scoped_lock lck( replSettings.discoveredSeeds_mx );                    if( replSettings.discoveredSeeds.size()  0 ) {    //其他线程搜索的其他设备心跳检测中提供的节点                        for (setstring::iterator i  replSettings.discoveredSeeds.begin();                              i ! replSettings.discoveredSeeds.end();                              i) {                            try {                                configs.push_back( ReplSetConfig(HostAndPort(*i)) );   //从新搜索的设备中获取配置                            }                            catch( DBException ) {                                log(1)  replSet exception trying to load config from discovered seed   *i  rsLog;                                replSettings.discoveredSeeds.erase(*i);                            }                        }                    }                }                if (!replSettings.reconfig.isEmpty()) {                    try {                        configs.push_back(ReplSetConfig(replSettings.reconfig, true)); //从shell获取配置                    }                    catch( DBException re) {                        log()  replSet couldnt load reconfig:   re.what()  rsLog;                        replSettings.reconfig  BSONObj();                    }                }                int nok  0;                int nempty  0;                for( vectorReplSetConfig::iterator i  configs.begin(); i ! configs.end(); i ) {                    if( i-ok() )   //判断得到的设置是否可用                        nok;                    if( i-empty() )   //判断得到配置是否为空                        nempty;                    }                if( nok  0 ) {                    if( nempty  (int) configs.size() ) {   //如果没有获取到配置信息                        startupStatus  EMPTYCONFIG;   //标注状态                        startupStatusMsg.set(cant get   rsConfigNs   config from self or any seed (EMPTYCONFIG));                        log()  replSet cant get   rsConfigNs   config from self or any seed (EMPTYCONFIG)  rsLog;                        static unsigned once;                        if( once  1 ) {                            log()  replSet info you may need to run replSetInitiate -- rs.initiate() in the shell -- if that is not already done  rsLog;                        }                        if( _seeds-size()  0 ) {                            LOG(1)  replSet info no seed hosts were specified on the --replSet command line  rsLog;                        }                    }                    else {                        startupStatus  EMPTYUNREACHABLE;                        startupStatusMsg.set(cant currently get   rsConfigNs   config from self or any seed (EMPTYUNREACHABLE));                        log()  replSet cant get   rsConfigNs   config from self or any seed (yet)  rsLog;                    }                    sleepsecs(10);  //十秒后重试                    continue;                }                if( !_loadConfigFinish(configs) ) {     //找到了配置信息但是配置失败                    log()  replSet info Couldnt load config yet. Sleeping 20sec and will try again.  rsLog;                    sleepsecs(20);  //二十秒后重试                    continue;                }            }            catch(DBException e) {                startupStatus  BADCONFIG;                startupStatusMsg.set(replSet error loading set config (BADCONFIG));                log()  replSet error loading configurations   e.toString()  rsLog;                log()  replSet error replication will not start  rsLog;                sethbmsg(error loading set config);                _fatal();                throw;            }            break;   //设置成功跳出循环        }        startupStatusMsg.set(? started);        startupStatus  STARTED;   //标注状态为开始运行    } 从代码上看设置过程为先去各个地方找到可用的配置。之后统计其中可用的配置如果没有可用的配置也没有不为空的配置则输出log提示用户设置。当找到了可用的配置之后将其数组发送到_loadConfigFinish函数进行设置。 ReplSet的设置工作// Our own config must be the first one.    bool ReplSetImpl::_loadConfigFinish(vectorReplSetConfig cfgs) {        int v  -1;    //当前版本号        ReplSetConfig *highest  0;            int myVersion  -2000;            int n  0;        for( vectorReplSetConfig::iterator i  cfgs.begin(); i ! cfgs.end(); i ) {   //循环取出配置对象            ReplSetConfig cfg  *i;            DEV log(1)  n1   config shows version   cfg.version  rsLog;             if( n  1 ) myVersion  cfg.version;            if( cfg.ok()  cfg.version  v ) {    //如果可用并且配置版本比当前高则存储起来                highest  cfg;                v  cfg.version;            }        }        verify( highest );        if( !initFromConfig(*highest) )   //将最高配置对象进行初始化            return false;        if( highest-version  myVersion  highest-version  0 ) {            log()  replSet got config version   highest-version   from a remote, saving locally  rsLog;            highest-saveConfigLocally(BSONObj());        }        return true;    }  4. ReplSet间的心跳检测 在配置ReplSet的过程中通过调用initFromConfig来更新配置。这个函数中会先去找到新添加的节点如果有新的节点为新的节点添加心跳检测的task如果没有新的节点则认为是更新配置这样停掉之前所有的心跳检测task开启新的task for health。 心跳检测过程的示意图//开启一个心跳检测task    void ReplSetImpl::startHealthTaskFor(Member *m) {        DEV log()  starting rsHealthPoll for   m-fullName()  endl;        ReplSetHealthPollTask *task  new ReplSetHealthPollTask(m-h(), m-hbinfo());   //建立心跳检测task        healthTasks.insert(task);     //插入心跳检测task集合        task::repeat(task, 2000);     //每隔两秒心跳检测一次 在一次检测完成以后等待两秒后再次检测    }  以发送请求方说明 心跳检测的目是查看其他Repl上的节点是不是存活。 存活的话调用up函数如下 void ReplSetHealthPollTask::up(const BSONObj info, HeartbeatInfo mem) {            HeartbeatInfo::numPings;            mem.authIssue  false;            if( mem.upSince  0 ) {                log()  replSet member   h.toString()   is up  rsLog;                mem.upSince  mem.lastHeartbeat;            }            mem.health  1.0;            mem.lastHeartbeatMsg  info[hbmsg].String();            if( info.hasElement(opTime) )                mem.opTime  info[opTime].Date();            // see if this member is in the electable set            //如果返回的心跳包含投票信息做下面的操作            if( info[e].eoo() ) {                    // for backwards compatibility                const Member *member  theReplSet-findById(mem.id());                if (member  member-config().potentiallyHot()) {   //对方是否为活着的节点                    theReplSet-addToElectable(mem.id());     //目标节点获得投票权                }                else {                    theReplSet-rmFromElectable(mem.id());    //目标节点失去投票权                }            }            // add this server to the electable set if it is within 10            // seconds of the latest optime we know of            else if( info[e].trueValue()                      mem.opTime  theReplSet-lastOpTimeWritten.getSecs() - 10) {                unsigned lastOp  theReplSet-lastOtherOpTime().getSecs();                if (lastOp  0  mem.opTime  lastOp - 10) {                    theReplSet-addToElectable(mem.id());                }            }            else {                theReplSet-rmFromElectable(mem.id());            }            //如果返回的信息中包含设置信息做同步设置的工作            be cfg  info[config];            if( cfg.ok() ) {                // received a new config                boost::functionvoid() f                     boost::bind(Manager::msgReceivedNewConfig, theReplSet-mgr, cfg.Obj().copy());                theReplSet-mgr-send(f);            }        }    }; 连接失败时表示目标节点离线。 void ReplSetHealthPollTask::down(HeartbeatInfo mem, string msg) {            //设置各种健康状态            mem.authIssue  false;            mem.health  0.0;            mem.ping  0;            //打印log信息            if( mem.upSince || mem.downSince  0 ) {                mem.upSince  0;                mem.downSince  jsTime();                mem.hbstate  MemberState::RS_DOWN;                log()  replSet info   h.toString()   is down (or slow to respond):   msg  rsLog;            }            //剥夺节点投票权            mem.lastHeartbeatMsg  msg;            theReplSet-rmFromElectable(mem.id());        } 如果在配置阶段接收到了不是自己列表中节点发出的心跳检测请求可以检测新节点的配置信息。具体代码在heartbeat.cpp中的CmdReplSetHeartbeatline:104中实现。 5. ReplSet间的投票过程 投票过程是伴随在心跳检测和消息传递的过程中的下面的代码阅读都本着只关心头片相关过程的代码阅读其他枝节部分就略去了。 投票过程的序列图 a) 消息传递 消息传递的过程是由心跳检测来完成的在心跳检测时单个节点既是发送方也是接收方。 作为发送方向其他节点发出 //heartbeat.cpp line 134    bool requestHeartbeat(string setName, string from, string memberFullName, BSONObj result,                          int myCfgVersion, int theirCfgVersion, bool checkEmpty) {        if( replSetBlind ) {            return false;        }        //从这段代码中看出节点向外传出的是节点名称、节点的设置版本号和路径        BSONObj cmd  BSON( replSetHeartbeat  setName                             v  myCfgVersion                             pv  1                             checkEmpty  checkEmpty                             from  from );        // generally not a great idea to do outbound waiting calls in a        // write lock. heartbeats can be slow (multisecond to respond), so        // generally we dont want to be locked, at least not without        // thinking acarefully about it first.        massert(15900, cant heartbeat: too much lock,                !Lock::somethingWriteLocked() || theReplSet  0 || !theReplSet-lockedByMe() );        ScopedConn conn(memberFullName);        return conn.runCommand(admin,                               cmd,                               result,                               0,                               AuthenticationTable::getInternalSecurityAuthenticationTable());    } //消息返回后        bool ReplSetHealthPollTask::_requestHeartbeat(HeartbeatInfo mem, BSONObj info, int theirConfigVersion) {            if (tries % threshold  (threshold - 1)) {                ScopedConn conn(h.toString());                conn.reconnect();            }            Timer timer;            time_t before  curTimeMicros64() / 1000000;            //调用函数传出消息            bool ok  requestHeartbeat(theReplSet-name(), theReplSet-selfFullName(),                                       h.toString(), info, theReplSet-config().version, theirConfigVersion);        //info是传出心跳检测后的返回值       //根据返回值同步记录同步的偏差时间            mem.ping  (unsigned int)timer.millis();            // we set this on any response - we dont get this far if            // couldnt connect because exception is thrown            time_t after  mem.lastHeartbeat  before  (mem.ping / 1000);            if ( info[time].isNumber() ) {                long long t  info[time].numberLong();                if( t  after )                    mem.skew  (int) (t - after);                else if( t  before )                    mem.skew  (int) (t - before); // negative            }            else {                // it wont be there if remote hasnt initialized yet                if( info.hasElement(time) )                    warning()  heatbeat.time isnt a number:   info  endl;                mem.skew  INT_MIN;            }            {                //记录下其他节点的状态                be state  info[state];                if( state.ok() )                    mem.hbstate  MemberState(state.Int());            }            return ok;        }  //消息返回后的另一部分状态处理        void ReplSetHealthPollTask::doWork() {            if ( !theReplSet ) {                LOG(2)  replSet not initialized yet, skipping health poll this round  rsLog;                return;            }            HeartbeatInfo mem  m;            HeartbeatInfo old  mem;            try {                BSONObj info;                int theirConfigVersion  -10000;                bool ok  _requestHeartbeat(mem, info, theirConfigVersion);                // weight new ping with old pings                // on the first ping, just use the ping value                if (old.ping ! 0) {                    mem.ping  (unsigned int)((old.ping * .8)  (mem.ping * .2));                }                //……            }            catch(...) {                //……            }            m  mem;            //通知更新节点信息            theReplSet-mgr-send( boost::bind(ReplSet::msgUpdateHBInfo, theReplSet, mem) );            static time_t last  0;            time_t now  time(0);            //判断节点信息是否被改变            bool changed  mem.changed(old);            if( changed ) {                if( old.hbstate ! mem.hbstate )                    log()  replSet member   h.toString()   is now in state   mem.hbstate.toString()  rsLog;            }            //当其他节点信息信息改变或者前后两次连接服务器的时间大于4秒则更新一下自己节点的状态在函数中发出投票请求            if( changed || now-last4 ) {                last  now;                theReplSet-mgr-send( boost::bind(Manager::msgCheckNewState, theReplSet-mgr) );            }        }作为接收方//接收到数据后会调用这个函数        virtual bool CmdReplSetHeartbeat::run(const string , BSONObj cmdObj, int, string errmsg, BSONObjBuilder result, bool fromRepl) {            //略过鉴权等工作            //……            result.append(set, theReplSet-name());       //名称            result.append(state, theReplSet-state().s);     //节点状态            result.append(e, theReplSet-iAmElectable());  //是否可以参加投票            result.append(hbmsg, theReplSet-hbmsg());   //心跳的一些信息具体还没看太明白            result.append(time, (long long) time(0));       //当前的服务器时间            result.appendDate(opTime, theReplSet-lastOpTimeWritten.asDate()); //最后一次写操作的时间            int v  theReplSet-config().version;    //设置的版本信息            result.append(v, v);            if( v  cmdObj[v].Int() )                result  config  theReplSet-config().asBson();            return true;        }  b) 检测那些节点可以投票 结合之前的心跳检测和后面的消息传递ReplSet会根据心跳检测的结果调用addToElectable和rmFromElectable来添加和删除投票节点。 值得一提的是在Manager::msgCheckNewState()被调用时会去判断当前节点是否可以参与投票void Manager::checkElectableSet() {        unsigned otherOp  rs-lastOtherOpTime().getSecs();                // make sure the electable set is up-to-date        if (rs-elect.aMajoritySeemsToBeUp()           //看看是否有选上的可能            rs-iAmPotentiallyHot()                   //看看自己是不是活跃节点            (otherOp  0 || rs-lastOpTimeWritten.getSecs()  otherOp - 10)) {       //上次写操作是否在10秒以内            theReplSet-addToElectable(rs-selfId());        }        else {            theReplSet-rmFromElectable(rs-selfId());        }//……} c) 确定是不是要发起投票 当确定了那些节点可以投票以后就要判断是不是要发起投票了。/** called as the health threads get new results */    void Manager::msgCheckNewState() {        {            //判断之前的节点状态            //……            const Member *p  rs-box.getPrimary();         //            if( p  p ! rs-_self ) {                if( !p-hbinfo().up() ||                        !p-hbinfo().hbstate.primary() ) {                    p  0;                    rs-box.setOtherPrimary(0);                }            }            const Member *p2;            {                bool two;                //判断一下是不是还有别的主节点                //如果有两个主节点说明就等待其他节点自己解决谁是主节点的问题                //返回的节点是确定的主节点                p2  findOtherPrimary(two);                if( two ) {                    /* two other nodes think they are primary (asynchronously polled) -- wait for things to settle down. */                    log()  replSet info two primaries (transiently)  rsLog;                    return;                }            }            if( p2 ) {                noteARemoteIsPrimary(p2);                return;            }            /* didnt find anyone who wants to be primary */           //如果包含一个主节点            if( p ) {                /* we are already primary */                //主节点不是自己说明有人能做主                if( p ! rs-_self ) {                    rs-sethbmsg(error p ! rs-self in checkNewState);                    log()  replSet   p-fullName()  rsLog;                    log()  replSet   rs-_self-fullName()  rsLog;                    return;                }                                //如果自己是主节点需要将自己降级                if( rs-elect.shouldRelinquish() ) {                    log()  cant see a majority of the set, relinquishing primary  rsLog;                    rs-relinquish();                }                return;            }            if( !rs-iAmPotentiallyHot() ) { // if not we never try to be primary                OCCASIONALLY log()  replSet I dont see a primary and I cant elect myself  endl;                return;            }            //看自己有没有可能成为主节点             /* no one seems to be primary.  shall we try to elect ourself? */            if( !rs-elect.aMajoritySeemsToBeUp() ) {                static time_t last;                static int n;                int ll  0;                if( n  5 ) ll;                if( last  60  time(0 ) ) ll;                log(ll)  replSet cant see a majority, will not try to elect self  rsLog;                last  time(0);                return;            }            if( !rs-iAmElectable() ) {                return;            }            busyWithElectSelf  true; // dont try to do further elections  such while we are already working on one.        }        try {            //开始投票            rs-elect.electSelf();        }        catch(RetryAfterSleepException) {            /* we want to process new inbounds before trying this again.  so we just put a checkNewstate in the queue for eval later. */            requeue();        }        catch(...) {            log()  replSet error unexpected assertion in rs manager  rsLog;        }        busyWithElectSelf  false;    }  d) 投票 作为心跳检测的接收方当其他节点信息做了改变或者对某个节点前后连接时差大于4秒就有可能调用Manager::msgCheckNewState更改自己状态并且发出投票请求。 与其说是投票不如说是就是一次询问的过程就是节点向其他节点询问自己的状态是否符合当主机的条件。//询问其他节点    bool Consensus::weAreFreshest(bool allUp, int nTies) {        const OpTime ord  theReplSet-lastOpTimeWritten;        nTies  0;        verify( !ord.isNull() );        //组织请求数据        BSONObj cmd  BSON(                          replSetFresh  1                                     set  rs.name()                  //当前节点名称                          opTime  Date_t(ord.asDate())     //最后一次写入的时间                          who  rs._self-fullName()        //当前节点路径                          cfgver  rs._cfg-version          //当前节点设置的版本号                          id  rs._self-id());                 //当前节点的id        listTarget L;        int ver;        /* the following queries arbiters, even though they are never fresh.  wonder if that makes sense.           it doesnt, but it could, if they know what freshness it one day.  so consider removing           arbiters from getTargets() here.  although getTargets is used elsewhere for elections; there           arbiters are certainly targets - so a includeArbs bool would be necessary if we want to make           not fetching them herein happen.           */        //获得投票列表        rs.getTargets(L, ver);        //发出请求        multiCommand(cmd, L);        int nok  0;        allUp  true;        //处理请求稍后分析        //……    }//收到请求后的处理忽略了验证处理和比较版本配置版本号的代码        bool CmdReplSetFresh::shouldVeto(const BSONObj cmdObj, string errmsg) {            // dont veto older versions            if (cmdObj[id].eoo()) {                // they wont be looking for the veto field                return false;            }            unsigned id  cmdObj[id].Int();            const Member* primary  theReplSet-box.getPrimary();           //当前的主服务器            const Member* hopeful  theReplSet-findById(id);               //希望成为主机的服务器从上面的代码看是发送请求方服务器            const Member *highestPriority  theReplSet-getMostElectable();    //当前节点心目中的主机            //以下判断发现不符合条件的就否决投票            if( !hopeful ) {  //没有目标服务器                errmsg  str::stream()  replSet couldnt find member with id   id;                return true;            }            //如果当前的服务器是主机而自己刚刚进行级别的调整            else if( theReplSet-isPrimary()  theReplSet-lastOpTimeWritten  hopeful-hbinfo().opTime ) {                  // hbinfo is not updated, so we have to check the primarys last optime separately                errmsg  str::stream()  I am already primary,   hopeful-fullName()                      can try again once Ive stepped down;                return true;            }            //如果主服务器刚刚进行级别调整            else if( primary  primary-hbinfo().opTime  hopeful-hbinfo().opTime ) {                // other members might be aware of more up-to-date nodes                errmsg  str::stream()  hopeful-fullName()   is trying to elect itself but                      primary-fullName()   is already primary and more up-to-date;                return true;            }            //当前节点记录的最高优先级节点的优先级比目标节点高            else if( highestPriority  highestPriority-config().priority  hopeful-config().priority) {                errmsg  str::stream()  hopeful-fullName()   has lower priority than   highestPriority-fullName();                return true;            }            //当前节点不允许投票或者当前节点记录的最高优先级节点的优先级比目标节点高不明白为什么又判断一遍            if ( !theReplSet-isElectable(id) ||                (highestPriority  highestPriority-config().priority  hopeful-config().priority)) {                return true;            }            return false;        }//得到投票数据以后解析bool Consensus::weAreFreshest(bool allUp, int nTies) {       //省略发送请求的部分       //请求返回后存储在listTarget中        int nok  0;        allUp  true;        for( listTarget::iterator i  L.begin(); i ! L.end(); i ) {        //i存储这其他节点返回的结果            if( i-ok ) {                nok;                if( i-result[fresher].trueValue() ) {      //当前服务器不是最新的                    log()  not electing self, we are not freshest  rsLog;                    return false;                }                //根据返回的操作时间统计与自己时间相同的节点这部分从代码上是这个意思不过后面的解析没有太懂从其他地方的注释看是个正在开发的功能                OpTime remoteOrd( i-result[opTime].Date() );                if( remoteOrd  ord )                    nTies;                     verify( remoteOrd  ord );                //查看是当前节点是否否决自己成为主节点                if( i-result[veto].trueValue() ) {                    BSONElement msg  i-result[errmsg];                    if (!msg.eoo()) {                        log()  not electing self,   i-toHost   would veto with                              msg.String()    rsLog;                    }                    else {                        log()  not electing self,   i-toHost   would veto  rsLog;                    }                    return false;                }            }            else {                DEV log()  replSet freshest returns   i-result.toString()  rsLog;                allUp  false;            }        }        LOG(1)  replSet dev we are freshest of up nodes, nok:  nok   nTies:  nTies  rsLog;        verify( ord  theReplSet-lastOpTimeWritten ); //  as this may change while we are working...        return true;     } 如果没有其他服务器投反对票那么就向其他服务器发送设置自己为主节点的信息。之后会向其他节点发送消息通知自己当选的消息其他节点返回是否赞成当赞成票过半的时候自己当选。void Consensus::_electSelf() {           //略去投票部分            //……             //分发投票结果的确认部分            BSONObj electCmd  BSON(                                   replSetElect  1                                    set  rs.name()               //节点名称                                   who  me.fullName()         //节点路径                                   whoid  me.hbinfo().id()       //节点的id                                   cfgver  rs._cfg-version       //节点的配置信息                                   round  OID::gen() /* this is just for diagnostics */                               );            int configVersion;            listTarget L;            rs.getTargets(L, configVersion);            multiCommand(electCmd, L);    //请求发送 //处理确认请求    void Consensus::electCmdReceived(BSONObj cmd, BSONObjBuilder* _b) {        BSONObjBuilder b  *_b;        DEV log()  replSet received elect msg   cmd.toString()  rsLog;        else LOG(2)  replSet received elect msg   cmd.toString()  rsLog;        string set  cmd[set].String();        unsigned whoid  cmd[whoid].Int();        int cfgver  cmd[cfgver].Int();        OID round  cmd[round].OID();        int myver  rs.config().version;        const Member* primary  rs.box.getPrimary();        const Member* hopeful  rs.findById(whoid);        const Member* highestPriority  rs.getMostElectable();        int vote  0;        if( set ! rs.name() ) {            log()  replSet error received an elect request for   set   but our set name is   rs.name()    rsLog;        }        else if( myver  cfgver ) {    //如果接收方的版本号小于目标节点的版本号            // we are stale.  dont vote  不做其他处理        }        else if( myver  cfgver ) {    //如果接收方的版本号大于目标节点版本号对方版本号过期不赞成            // they are stale!            log()  replSet electCmdReceived info got stale version # during election  rsLog;            vote  -10000;        }        else if( !hopeful ) {    //目标节点id没有在接收方节点中挂名不赞成            log()  replSet electCmdReceived couldnt find member with id   whoid  rsLog;            vote  -10000;        }        //如果主节点是自己并且自己的最后写入时间比目标节点新不赞成        else if( primary  primary  rs._self  rs.lastOpTimeWritten  hopeful-hbinfo().opTime ) {            // hbinfo is not updated, so we have to check the primarys last optime separately            log()  I am already primary,   hopeful-fullName()                    can try again once Ive stepped down  rsLog;            vote  -10000;        }        //如果接收方认为的主节点的写入时间比目标节点的写入时间新不赞成        else if( primary  primary-hbinfo().opTime  hopeful-hbinfo().opTime ) {            // other members might be aware of more up-to-date nodes            log()  hopeful-fullName()   is trying to elect itself but                    primary-fullName()   is already primary and more up-to-date  rsLog;            vote  -10000;        }        //接收方认为当选呼声最高的节点比目标节点的当选呼声高不赞成        else if( highestPriority  highestPriority-config().priority  hopeful-config().priority) {            log()  hopeful-fullName()   has lower priority than   highestPriority-fullName();            vote  -10000;        }        else {            //如果满足上面的所有条件            try {                vote  yea(whoid);     //算出赞成度                dassert( hopeful-id()  whoid );                rs.relinquish();                log()  replSet info voting yea for    hopeful-fullName()   (  whoid  )  rsLog;            }            catch(VoteException) {                log()  replSet voting no for   hopeful-fullName()   already voted for another  rsLog;            }        }        //组织返回数据        b.append(vote, vote);          b.append(round, round);    } //处理返回结果            {                for( listTarget::iterator i  L.begin(); i ! L.end(); i ) {                    DEV log()  replSet elect res:   i-result.toString()  rsLog;                    if( i-ok ) {                        int v  i-result[vote].Int();                        tally  v;   //统计赞成结果                    }                }                if( tally*2  totalVotes() ) {  //赞成结果小于投票总数的一半终止成为主节点                    log()  replSet couldnt elect self, only received   tally   votes  rsLog;                }                else if( time(0) - start  30 ) {  //投票时间大于三十秒终止成为主节点                    // defensive; should never happen as we have timeouts on connection and operation for our conn                    log()  replSet too much time passed during our election, ignoring result  rsLog;                }                else if( configVersion ! rs.config().version ) {   //传出的版本号与返回的版本号不一致说明投票过程中有版本修改终止成为主节点                    log()  replSet config version changed during our election, ignoring result  rsLog;                }                else {                    /* succeeded. */                    log(1)  replSet election succeeded, assuming primary role  rsLog;                    success  true;                    rs.assumePrimary();  //当选为主节点                }            } e) 总结投票过程 在心跳检测中节点间互相传递着信息。通过这些信息节点能了解到其他节点的情况配置版本是否能连接上等等。单个节点统计着这些信息当某个节点设置发生改变或者网络连接出现异常的时候开始发送投票事件。 投票时首先根据心跳检测记录的信息判断哪些节点可以被连接到即有投票权。之后向所有可以连接到的节点发出自己能否成为主节点的请求。其他节点投是否否决票如果一致通过该节点进行下一步操作向其他节点发出自己当选的请求其他节点根据情况确定请求如果返回的赞成数大于投票总数的一半该节点当选。 转载于:https://www.cnblogs.com/biosli/archive/2012/10/19/2730776.html
http://www.sadfv.cn/news/172626/

相关文章:

  • 杭州网站建设网页制作房县建设局网站
  • 有没有像一起做网店做男装的网站厦门建设局人员名单
  • 网站建设企业站模板有哪些熟悉的网站是jsp做的
  • jsp网站开发实例.百度网盘wordpress 原创模板
  • 网站产品管理模块网站的结构设计
  • 西安建站网站wordpress 文章h标签美化
  • 桂林建设信息网站网站设置密码进入
  • 电视台网站建设网站 锚点链接怎么做
  • 自己做网站买东西如何开公司做网站
  • 成都网站设计报告书广州装修公司口碑最好的是哪家
  • 泰安网站建设哪家专业目录 首页 wordpress
  • 书店网站建设规划书网站建设得花多钱
  • 工业设计参考网站成都百度推广和seo优化
  • 网站建设各个模块的功能古镇企业网站建设定制
  • 多语种外贸网站建设ps做网站的时候分辨率是
  • 房产网站方案网站设计的逻辑结构
  • 用源码怎么做网站重庆市工程建设标准化网站
  • app网站开发价格手机网站制作教程视频教程
  • 获得网站管理员密码建站合同模板
  • 以个人名义可以做网站吗网站风格分类
  • 网站建设数据库做服装搭配的流行趋势网站
  • 贵阳市建设局地址网站建站公司网站论坛
  • 专注徐州网站开发再网站里做商家店铺
  • 模板网站的域名是什么意思wordpress 后台文章
  • 做推广哪个食品网站好wordpress菜单导入导出
  • 网站的友情连接怎么做企业建站系统信息
  • 免费做文字图网站贵州省建设厅住房和城乡建设官网
  • 南同网站建设软件下载网络营销顾问
  • 做网站到底怎么赚钱哪些网站是营销型网站
  • 照片分享网站开发费用用笔记本电脑能建设网站吗