MySQL binlog心跳

我们部署在线上的fake slave(用于同步数据或者是采集数据供业务订阅)经常会遇到某些特殊情况下,比如网络异常导致无法收到对端fin包导致无法走正常的连接关闭流程,这就导致了该slave连接处于假死状态。

之前实现binlog协议解析的时候,由于发送了dump命令后,该连接基本就处于只读模式,假设连接在此时异常,那么要么依赖tcp底层的keepalive,该连接基本就处于僵死状态了,会导致新的数据无法被fake slave获取到。

今天主要是把异常自恢复的场景先实现了,一个是主挂了之后自动切到从机来继续拉binlog数据,还有一个就是异常连接的检测了。在业务上,该场景最简单也最直接的解决办法就是加入业务层的心跳包,于是大概搜了下MySQL的document,查了下heartbeat的关键字,发现真有这个特性,是以前自己忽略了,该特性在MySQL 5.5被添加。

实现方式非常简单,直接使用以下语句打开心跳,心跳只有在binlog被全部读完后,一段时间间隔下无新数据后才会被发送,用于让从来知道master是否还活着:

SET @master_heartbeat_period =  <interval>

interval的但是是纳秒。

对应的binlog事件也非常简单,大概格式为:

                    Header
Timestamp 4
EventType 1
ServerID  4
EventSize 4
LogPos    4
Flags     2
                    Payload
LogIdent  eof string

最开头就是19字节的binlog头,剩下的payload是一个eof string,也就是剩余的字节组成的字符串,一般就是当前binlog的文件名。

slave处理心跳也很简单,假设在读包堵塞了Heartbeat interval的时间后,断开连接然后重连即可,当然我这儿是设置了1.5倍的时间。

该binlog结构对应的结构体为:

class Heartbeat_event: public Binary_log_event
{
public:

  /**
    Sent by a master to a slave to let the slave know that the master is
    still alive. Events of this type do not appear in the binary or relay logs.
    They are generated on a master server by the thread that dumps events and
    sent straight to the slave without ever being written to the binary log.

    @param buf                Contains the serialized event.
    @param event_len          Length of the serialized event.
    @param description_event  An FDE event, used to get the
                              following information
                              -binlog_version
                              -server_version
                              -post_header_len
                              -common_header_len
                              The content of this object
                              depends on the binlog-version currently in use.
  */
  Heartbeat_event(const char* buf, unsigned int event_len,
                  const Format_description_event *description_event);

  const char* get_log_ident() { return log_ident; }
  unsigned int get_ident_len() { return ident_len; }

protected:
  const char* log_ident;
  unsigned int ident_len;                      /** filename length */
};
共 0 条回复
暂时没有人回复哦,赶紧抢沙发
发表新回复

作者

sryan
today is a good day