暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL MGR源码浅读(一)

民生运维人 2021-07-13
1059

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数据传输、节点数据恢复等比较详细的机制和流程。

文章转载自民生运维人,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论