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();
- 当有新的server确认加入集群后,servers_将对用server的config添加
- 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_);//发送 }
- L收到这个信息,会重新构建一个信息,然后向该server_id进行发送
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();//通知大家
- 获取当前cluster_config文件,将退出的server_id进行删除
关于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; }