从源码分析 MGR 的新主选举算法( 二 )

这个函数里面,比较关键的地方有三个:

  1. 调用 sort_and_get_lowest_version_member_position 。
    这个函数会基于 member_version (节点版本)选择候选节点 。
    只有候选节点才有资格被选为主节点。
  2. 调用 sort_members_for_election 。
    这个函数会基于节点权重和 server_uuid,对候选节点进行排序 。
  3. 基于排序后的候选节点选择 Primary 节点 。
    因为候选节点是从头开始遍历,所以基本上,只要第一个节点是 ONLINE 状态,就会把这个节点作为 Primary 节点 。
sort_and_get_lowest_version_member_position接下来我们看看 sort_and_get_lowest_version_member_position 函数的实现逻辑 。
sort_and_get_lowest_version_member_position(    std::vector<Group_member_info *> *all_members_info) {  std::vector<Group_member_info *>::iterator it;  // 按照版本对 all_members_info 从小到大排序  std::sort(all_members_info->begin(), all_members_info->end(),            Group_member_info::comparator_group_member_version);  // std::vector::end 会返回一个迭代器,该迭代器引用 vector (向量容器)中的末尾元素 。  // 注意,这个元素指向的是 vector 最后一个元素的下一个位置,不是最后一个元素 。  std::vector<Group_member_info *>::iterator lowest_version_end =      all_members_info->end();  // 获取排序后的第一个节点 , 这个节点版本最低 。  it = all_members_info->begin();  Group_member_info *first_member = *it;  // 获取第一个节点的 major_version  // 对于 MySQL 5.7,major_version 是 5;对于 MySQL 8.0,major_version 是 8  uint32 lowest_major_version =      first_member->get_member_version().get_major_version();    /* to avoid read compatibility issue leader should be picked only from lowest     version members so save position where member version differs.     From 8.0.17 patch version will be considered during version comparison.     set lowest_version_end when major version changes     eg: for a list: 5.7.18, 5.7.18, 5.7.19, 5.7.20, 5.7.21, 8.0.2         the members to be considered for election will be:            5.7.18, 5.7.18, 5.7.19, 5.7.20, 5.7.21         and server_uuid based algorithm will be used to elect primary     eg: for a list: 5.7.20, 5.7.21, 8.0.2, 8.0.2         the members to be considered for election will be:            5.7.20, 5.7.21         and member weight based algorithm will be used to elect primary     eg: for a list: 8.0.17, 8.0.18, 8.0.19         the members to be considered for election will be:            8.0.17     eg: for a list: 8.0.13, 8.0.17, 8.0.18         the members to be considered for election will be:            8.0.13, 8.0.17, 8.0.18         and member weight based algorithm will be used to elect primary  */    // 遍历剩下的节点,注意 it 是从 all_members_info->begin() + 1 开始的  for (it = all_members_info->begin() + 1; it != all_members_info->end();       it++) {   // 如果第一个节点的版本号大于 MySQL 8.0.17,且节点的版本号不等于第一个节点的版本号 , 则将该节点赋值给 lowest_version_end,并退出循环 。    if (first_member->get_member_version() >=            PRIMARY_ELECTION_PATCH_CONSIDERATION &&        (first_member->get_member_version() != (*it)->get_member_version())) {      lowest_version_end = it;      break;    }    // 如果节点的 major_version 不等于第一个节点的 major_version,则将该节点赋值给 lowest_version_end,并退出循环 。    if (lowest_major_version !=        (*it)->get_member_version().get_major_version()) {      lowest_version_end = it;      break;    }  }  return lowest_version_end;}

推荐阅读