MySQL Group Replication(MGR)组复制在5.1.17版本中开始引入,基于”paxos”协议实现的数据一致性和高可用的集群方案,用于解决异步或者半同步复制可能产生的不一致性。它是mysql自带的插件(group_replication.so),支持节点的故障自动检测、弹性扩展等功能,同时还支持单主或多主写,自动检测冲突,保证数据的最终一致性。
与MHA相比,MGR通过“paxos”协议进行自动选举主节点,保证多数派原则集群就可以正常服务,自动切换,减少了人工介入成本;在选举前,MGR会一直感知节点的状态,对于异常节点不会参与选举过程。
在MGR中,每一个组会有多个节点,彼此之间进行状态和数据交互;组内每个节点的状态有:ONLINE,OFFLINE,IN_RECOVER,ERROR和UNREACHABL;ONLINE状态代表节点正常服务。
节点状态定义头文件在
plugin/group_replication/include/member_info.h中,使用枚举类型,列出了组内成员的状态。
节点的角色包括PRIMARY和SECONDARY两种;PRIMARY为主节点,SECONDARY为从节点,在单主模式下,只有主节点提供写请求,多主模式下,没有此限制。
typedef enum {
MEMBER_ROLE_PRIMARY = 1,
MEMBER_ROLE_SECONDARY,
MEMBER_ROLE_END
} Group_member_role;
节点本身自带的属性信息有:HOSTNAME,PORT,UUID,GCSID,STATUS,VERSION,WRITE_SET_EXTRACTION_ALGORITHMEXECUTED_GTID,RETRIEVED_GTID,GTID_ASSIGNMENT_BLOCK_SIZE,MEMBER_ROLE,CONFIGURATION_FLAGS,CONFLICT_DETECTION_ENABLE,MEMBER_WEIGHT,LOWER_CASE_TABLE_NAME,GROUP_ACTION_RUNNING,PRIMARY_ELECTION_RUNNING,DEFAULT_TABLE_ENCRYPTION,PURGED_GTID,RECOVERY_ENDPOINTS。节点信息会在组内传播,从节点信息内容看mgr必须开启GTID,它是基于GTID进行一致性保证。
查看组内成员角色、状态、id等信息,可通过执行sql语句select * from performance_schema.replication_group_members 查看

节点之间通信通过GCS模块进行数据和信息交换,该模块承载着节点所有的通信内容,设计复杂;节点信息交换会有产生一个视图(gcs_view),主要记录此刻的节点信息,新加入组节点信息,离开组节点信息,以当前视图版本号;视图变化会引起组内节点状态的变化。
Gcs_view(const std::vector<Gcs_member_identifier> &members,
const Gcs_view_identifier &view_id,
const std::vector<Gcs_member_identifier> &leaving,
const std::vector<Gcs_member_identifier> &joined,
const Gcs_group_identifier &group_id,
Gcs_view::Gcs_view_error_code error_code);
视图版本信息号可以通过sql语句查看
select * from replication_group_member_stats \G

除了节点之间交换状态信息外,GCS还有其他十几种信息交换类型,如数据恢复、数据交易等,从头文件gcs_plugin_messages.h中可找到定义
enum enum_cargo_type {
// This type should not be used anywhere.
CT_UNKNOWN = 0,
// This cargo type is used for certification events, GTID_EXECUTED
// broadcast.
CT_CERTIFICATION_MESSAGE = 1,
// This cargo type is used for transaction data.
CT_TRANSACTION_MESSAGE = 2,
// This cargo type is used for recovery events, signal when a given member
// becomes online.
CT_RECOVERY_MESSAGE = 3,
// This cargo type is used for messaging related to stage exchanges,
// on which it represents one member.
CT_MEMBER_INFO_MESSAGE = 4,
// This cargo type is used for messaging related to stage exchanges,
// on which it represents a set of members.
CT_MEMBER_INFO_MANAGER_MESSAGE = 5,
// This cargo type is used for messaging related to members pipeline
// stats.
CT_PIPELINE_STATS_MEMBER_MESSAGE = 6,
// This cargo type is used for messaging related to single primary
// mode.
CT_SINGLE_PRIMARY_MESSAGE = 7,
// This cargo type is used for messaging related to group coordinated
// actions.
CT_GROUP_ACTION_MESSAGE = 8,
// This cargo type is used for messaging when checking if a group is valid
// for some task
CT_GROUP_VALIDATION_MESSAGE = 9,
// This cargo type is used for synchronization before executing a
// transation.
CT_SYNC_BEFORE_EXECUTION_MESSAGE = 10,
// This cargo type is used for transaction data with guarantee.
CT_TRANSACTION_WITH_GUARANTEE_MESSAGE = 11,
// This cargo type is used to inform about prepared transactions.
CT_TRANSACTION_PREPARED_MESSAGE = 12,
// This cargo type is used for messages that are for
// senders/consumers outside the GR plugin.
CT_MESSAGE_SERVICE_MESSAGE = 13,
// No valid type codes can appear after this one.
CT_MAX = 14
};
GCS不同消息的处理都按照event类型进行处理,在gcs_event_handlers头文件定义了不同event的事件处理函数,如交易数据消息处理、组内成员信息变化处理等
/*
Individual handling methods for all possible message types
received via on_message_received(...)
*/
void handle_transactional_message(const Gcs_message &message) const;
void handle_transactional_with_guarantee_message(
const Gcs_message &message) const;
void handle_transaction_prepared_message(const Gcs_message &message) const;
void handle_sync_before_execution_message(const Gcs_message &message) const;
void handle_certifier_message(const Gcs_message &message) const;
void handle_recovery_message(Plugin_gcs_message *message) const;
void handle_stats_message(const Gcs_message &message) const;
void handle_single_primary_message(
Plugin_gcs_message *processed_message) const;
void handle_group_action_message(const Gcs_message &message) const;
/**
This method passes the message to message listeners
@param plugin_message A pointer to the processed plugin gcs message
@param message_origin A id of the message originating member
@return true if the message should be skipped, false otherwise
*/
bool pre_process_message(Plugin_gcs_message *plugin_message,
const std::string &message_origin) const;
/*
Methods to act upon members after a on_view_change(...) is called
*/
int update_group_info_manager(const Gcs_view &new_view,
const Exchanged_data &exchanged_data,
bool is_joining, bool is_leaving) const;
void handle_joining_members(const Gcs_view &new_view, bool is_joining,
bool is_leaving) const;
void handle_leaving_members(const Gcs_view &new_view, bool is_joining,
bool is_leaving) const;
GCS消息在发送、传输、接收时,使用了xcom框架sunrpc协议,进行序列化和反序列化;上层各种消息封装后,通过sunrpc传给接收端,在接收端按照协议规定从数据流中读取消息内容,在经过层层传递与解析,调用handler进行相应的消息处理。

MGR根据“paxos”协议自动选主,但ip地址会发生变化,客户端无法自动感知,需要配合 msyql router或者vip等机制配合使用,实现业务零影响。
MGR内部实现机制相当复杂,自己也只是刚开始接触,理解比较片面,后续会继续深入研究节点选举、binlog transaction数据传输、节点数据恢复等比较详细的机制和流程。




