以下按照节点加入流程一起分析视图变化,仅仅涉及视图相关,略去了其他流程:
一、基本数据结构与变量:
struct zk_event {
uint64_t id;
enum zk_event_typetype;
struct zk_node sender;
size_t msg_len;
size_t nr_nodes;
size_t buf_len;
uint8_tbuf[ZK_MAX_BUF_SIZE];
};
struct zk_event ev;
二、新节点new_node加入:
1、读取本地epoch文件初始化cluster info结构sys->cinfo;
2、节点加入流程将sys->cinfo放入ev->buf中,推送给zk server,放在/queue/event_id里面;接口调用关系
zk_join()ß send_join_request()ßadd_join_event()ß zk_queue_push()
三、master节点的处理:
其收到join事件后:
1、在master本身和新节点推送的cluster info两者之间选择一个最新的放入ev->buf中;
zk_handle_join()ß sd_join_handler() ß cluster_wait_check()
2、将本地的sd_node_root放在ev->buf的偏移sizeof(cinfo)处,并推送到zkserver。
zk_handle_join()ß push_join_response()
这样ev->buf中就包含了两个视图:一个是sys->cinfo中的,另一个是sd_node_root;若master的cluster info最新,则此时两者一样,否则不同;两个视图是为了对比节点加入前后视图是否变更,以判断是否需要recovery。
四、各个节点处理accept事件:
1、新加入的节点:用ev->buf中的sd_node_root来初始化本地sd_node_root(即从buf的偏移sizeof(cinfo)处取获取;
zk_handle_accept()ß init_node_list()
2、所有节点(包含新加入节点):
1)将new_node加入到本地节点列表sd_node_root;
zk_handle_accept()ß zk_tree_add()
2)拷贝ev->buf中的cluster info到本地sys->cinfo(此时sys->cinfo与sd_node_root视图不一致);
zk_handle_accept()ß sd_accept_handler()
3)比较sys->cinfo与sd_node_root,判断视图是否变更;
update_cluster_info()ß membership_changed()
4)用sd_node_root生成新的vinfo,并用vinfo重新初始化sys->cinfo(此时sys->cinfo与sd_node_root视图再次一致);
update_cluster_info()ß inc_and_log_epoch()