nuraft源码笔记——(4)

nuraft4

关于集群配置文件的处理

config相关管理信息

  • 在server中会存储一个cluster_config的文件,用来记录集群内部各个server的信息
    class cluster_config {
    private:
        ulong log_idx_;//当前config的索引
        ulong prev_log_idx_;//上一个配置文件的索引number
        bool async_replication_;//是否设置异步复制
        std::string user_ctx_;
        std::list<ptr<srv_config>> servers_;//存放集群中的所有servers_文件
    }
    
    • 当有新的server确认加入集群后,servers_将对用server的config添加
      • 获取当前config文件
      • 创建一个new_config文件
        • 更新索引索引等相关信息
      • 插入准备添加的server的配置信息
      • 存入日志,发送同步请求
        //sync_log_to_new_srv(ulong start_idx)
        ptr<cluster_config> cur_conf = get_config();//获取配置文件
        //更新配置文件信息
        ptr<cluster_config> new_conf = cs_new<cluster_config>
                                       ( log_store_->next_slot(),
                                         cur_conf->get_log_idx() );//
        new_conf->get_servers().insert( new_conf->get_servers().end(),
                                        cur_conf->get_servers().begin(),
                                        cur_conf->get_servers().end() );
        //将待加入的server_config信息进行添加
        new_conf->get_servers().push_back(conf_to_add_);
        new_conf->set_user_ctx( cur_conf->get_user_ctx() );
        new_conf->set_async_replication
                  ( cur_conf->is_async_replication() );
        
        ptr<buffer> new_conf_buf(new_conf->serialize());
        ptr<log_entry> entry( cs_new<log_entry>( state_->get_term(),
                                                 new_conf_buf,
                                                 log_val_type::conf,
                                                 timer_helper::get_timeofday_us() ) );
        //存入日志
        store_log_entry(entry);
        config_changing_ = true;
        uncommitted_config_ = new_conf;
        //向F进行同步
        request_append_entries();
        
  • srv_config

    srv_config会记录单个服务器的相关信息

    • srv_config成员变量
    class srv_config {
      private:
        int32 id_;//本机id
        int32 dc_id_;//我理解是L的id
        std::string endpoint_;//本机地址+端口号
        std::string aux_;
        bool learner_;
        int32 priority_; 
    }
    

L手动删除一个F的过程

  • raft_server::remove_srv(const int srv_id)

    指定一个server_id进行删除

    //
    ptr<buffer> buf(buffer::alloc(sz_int));
    buf->put(srv_id);
    buf->pos(0);
    ptr<log_entry> log(cs_new<log_entry>(0, buf, log_val_type::cluster_server));
    ptr<req_msg> req = cs_new<req_msg>
                     ( (ulong)0, msg_type::remove_server_request, 0, 0,
                       (ulong)0, (ulong)0, (ulong)0 );
    req->log_entries().push_back(log);
    
  • handle_rm_srv_req

    L收到这个消息会自己进行处理
    remove_server_request就可以看作是一个内部信息量

    • L收到这个信息,会重新构建一个信息,然后向该server_id进行发送
      ptr<peer> p = pit->second;
      ptr<req_msg> leave_req( cs_new<req_msg>//重新构建信息
                              ( state_->get_term(),
                                msg_type::leave_cluster_request,
                                id_, srv_id, 0,
                                log_store_->next_slot() - 1,
                                quick_commit_index_.load() ) );
      p->set_leave_flag();
      if (p->make_busy()) {
          p->send_req(p, leave_req, ex_resp_handler_);//发送
      }
      

F离开集群信息

  • F收到信息后,会创建响应信息,并进入退出程序
    • L主动让F离开,就需要集群内部发动人数下的人都能够收到信息,其才能够退出
    //ptr<resp_msg> raft_server::handle_leave_cluster_req(req_msg& req)
        ptr<resp_msg> resp
          ( cs_new<resp_msg>( state_->get_term(),
                              msg_type::leave_cluster_response,
                              id_,
                              req.get_src() ) );
      if (!config_changing_) {
          p_db("leave cluster, set steps to down to 2");
          //如果集群内部都已知晓,则做好离开准备
          //因为需要Leader通知到大家,其
          steps_to_down_ = 2;
          resp->accept(log_store_->next_slot());
      }
    
      return resp;
    

L收到F的响应

  • rm_srv_from_cluster
    void raft_server::rm_srv_from_cluster(int32 srv_id)
    
    • 获取当前cluster_config文件,将退出的server_id进行删除
      • 然后进行将日志分发同步
      ptr<cluster_config> cur_conf = get_config();
      if (uncommitted_config_) {
          cur_conf = uncommitted_config_;
      }
      ptr<cluster_config> new_conf = cs_new<cluster_config>
                                     ( log_store_->next_slot(),
                                       cur_conf->get_log_idx() );
      for ( cluster_config::const_srv_itor it = cur_conf->get_servers().begin();
            it != cur_conf->get_servers().end();
            ++it ) {
          if ((*it)->get_id() != srv_id) {
              new_conf->get_servers().push_back(*it);
          }
      }
      new_conf->set_user_ctx( cur_conf->get_user_ctx() );
      new_conf->set_async_replication
                ( cur_conf->is_async_replication() );
      config_changing_ = true;
      uncommitted_config_ = new_conf;
      ptr<buffer> new_conf_buf( new_conf->serialize() );
      ptr<log_entry> entry( cs_new<log_entry>( state_->get_term(),
                                               new_conf_buf,
                                               log_val_type::conf,
                                               timer_helper::get_timeofday_us() ) );
      store_log_entry(entry);
      
    • 同时将该连接设置为srv_to_leave_
      auto p_entry = peers_.find(srv_id);
      if (p_entry != peers_.end()) {
          ptr<peer> pp = p_entry->second;
          srv_to_leave_ = pp;
          srv_to_leave_target_idx_ = new_conf->get_log_idx();
          p_in("set srv_to_leave_, "
               "server %d will be removed from cluster, config %" PRIu64,
               srv_id, srv_to_leave_target_idx_);
      }
      request_append_entries();//通知大家
      

关于F离开集群细节

  • 当选举的时钟超时,触发选举,

    至少等一轮选举后,本node才会正式退出,断开连接(确保集群内部都已确认该node离开)

    • 当step_to_down_被设置,
    • 则重置选举时钟
    if (steps_to_down_ > 0) {//node离开节点的剩余步骤数,一旦集群离开节点,就触发一次(后期注意哪里设置的)
          if (--steps_to_down_ == 0) {//退出
              state_->allow_election_timer(false);
              ctx_->state_mgr_->save_state(*state_);
              cancel_schedulers();
              return;
          }
          restart_election_timer();//重新设置选举时间
          return;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值