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


bool Group_member_info::comparator_group_member_weight(Group_member_info *m1,                                                       Group_member_info *m2) {  return m1->has_greater_weight(m2);}bool Group_member_info::has_greater_weight(Group_member_info *other) {  MUTEX_LOCK(lock, &update_lock);  if (member_weight > other->get_member_weight()) return true;  // 如果权重一致 , 会按照节点的 server_uuid 来排序 。  if (member_weight == other->get_member_weight())    return has_lower_uuid_internal(other);  return false;}案例分析基于上面代码的逻辑 , 接下来我们分析下 sort_and_get_lowest_version_member_position 函数注释部分列举的四个案例:
案例 1:5.7.18, 5.7.18, 5.7.19, 5.7.20, 5.7.21, 8.0.21. 这几个节点中 , 最小版本号是 5.7.18 , 小于 MySQL 8.0.17 。所以会比较各个节点的 major_version , 因为最后一个节点(8.0.2)的 major_version 和第一个节点不一致 , 所以会将 8.0.2 作为 lowest_version_end 。此时 , 除了 8.0.2 , 其它都是候选节点 。
2. 最小版本号 5.7.18 小于 MySQL 5.7.20 , 所以 5.7.18, 5.7.18, 5.7.19, 5.7.20, 5.7.21 这几个节点会根据 server_uuid 进行排序 。注意 , lowest_version_end 的节点不会参与排序 。
3. 选择 server_uuid 最小的节点作为 Primary 节点 。
案例 2:5.7.20, 5.7.21, 8.0.2, 8.0.21. 同案例 1 一样 , 会将 8.0.2 作为 lowest_version_end 。此时 , 候选节点只有 5.7.20 和 5.7.21 。
2. 最小版本号 5.7.20 等于 MySQL 5.7.20 , 所以 , 5.7.20, 5.7.21 这两个节点会根据节点的权重进行排序 。如果权重一致 , 则会基于 server_uuid 进行进一步的排序 。
3. 选择权重最高 , server_uuid 最小的节点作为 Primary 节点 。
案例 3:8.0.17, 8.0.18, 8.0.191. 最小版本号是 MySQL 8.0.17 , 等于 MySQL 8.0.17 , 所以会判断其它节点的版本号是否与第一个节点相同 。不相同 , 则会将该节点的版本号赋值给 lowest_version_end 。所以 , 会将 8.0.18 作为 lowest_version_end 。此时 , 候选节点只有 8.0.17 。
2. 选择 8.0.17 这个节点作为 Primary 节点 。
案例 4:8.0.13, 8.0.17, 8.0.181. 最小版本号是 MySQL 8.0.13 , 小于 MySQL 8.0.17 , 而且各个节点的 major_version 一致 , 所以最后返回的 lowest_version_end 实际上是 all_members_info->end() 。此时 , 这三个节点都是候选节点 。
2. MySQL 8.0.13 大于 MySQL 5.7.20 , 所以这三个节点会根据权重进行排序 。如果权重一致 , 则会基于 server_uuid 进行进一步的排序 。
3. 选择权重最高 , server_uuid 最小的节点作为 Primary 节点 。
手动选主从 MySQL 8.0.13 开始 , 我们可以通过以下两个函数手动选择新的主节点:

  • group_replication_set_as_primary(server_uuid) :切换单主模式下的 Primary 节点 。
  • group_replication_switch_to_single_primary_mode([server_uuid]) :将多主模式切换为单主模式 。可通过 server_uuid 指定单主模式下的 Primary 节点 。
在使用这两个参数时 , 注意 , 指定的 server_uuid 必须属于候选节点 。
另外 , 这两个函数是 MySQL 8.0.13 引入的 , 所以 , 如果集群中存在 MySQL 8.0.13 之前的节点 , 执行时会报错 。

经验总结扩展阅读