Replication进阶(五) 复制中的ACK详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_ashe/article/details/83347085
  • ack是什么?
  • 什么时候slave会返回ack给master
  • 带有ack请求的binlog和不带ack的有区别吗?

首先来解释第一个问题,什么是ack

ack全称为Acknowledgement,中文翻译为确认字符,应用在网络通信中的很多地方,比如TCP/IP协议中。MySQL复制中的ACK指的是,master发送binlog给slave后,slave发送消息给master,通知master已经收到了相应的binlog信息。那这个信息到底包含哪些东西呢,可以参看如下代码

int ReplSemiSyncSlave::slaveReply(MYSQL *mysql,
                                 const char *binlog_filename,
                                 my_off_t binlog_filepos)
{
     uchar reply_buffer[REPLY_MAGIC_NUM_LEN
                     + REPLY_BINLOG_POS_LEN
                     + REPLY_BINLOG_NAME_LEN];
     /* Prepare the buffer of the reply. */
  reply_buffer[REPLY_MAGIC_NUM_OFFSET] = kPacketMagicNum;
  int8store(reply_buffer + REPLY_BINLOG_POS_OFFSET, binlog_filepos);
  memcpy(reply_buffer + REPLY_BINLOG_NAME_OFFSET,
         binlog_filename,
         name_len + 1 /* including trailing '\0' */);
    
}

可以看出,整个ack的数据包包含三部分内容

1 2 3
1个字节的kPacketMagicNum 8个字节的binlog_filepos 最大513个字节的binlog_filename

为什么会是这样的呢?这和半同步复制的工作原理相关,简单来说,slave在事务提交时,等待slave的ack信息,这个等待的过程就是在等待binlog的位置信息。只要slave返回的ack大于等于事务自身等待的值,则可以进行提交操作。

什么时候slave会返回ack给master

为什么slave知道这个事务要返回ack给master呢?是建立复制的开始约定好的吗?在复制的进行过程中,binlog以event为单位进行发送,然而slave并不是在接收到每一个binlog event后,都进行binlog的发送。master必须在binlog中的某个地方标示出来,明确的告知slave,需要进行ack。

在master 安装rpl_semi_sync_master插件后,其对半同步复制的slave发送的binlog多出了一部分内容,在每一个event的头部多出了两个字节,见如下:

1 2
1字节表示kPacketMagicNum 1字节表示kPacketFlagSync,此event是否需要ack

slave的判断过程如下


int ReplSemiSyncSlave::slaveReadSyncHeader(const char *header,
                                      unsigned long total_len,
                                      bool  *need_reply,
                                      const char **payload,
                                      unsigned long *payload_len)
{
  const char *kWho = "ReplSemiSyncSlave::slaveReadSyncHeader";
  int read_res = 0;
  function_enter(kWho);

  if ((unsigned char)(header[0]) == kPacketMagicNum)
  {
    *need_reply  = (header[1] & kPacketFlagSync); //如果此类型的event需要slave ack,master会把header[1]设置为kPacketFlagSync : const unsigned char ReplSemiSyncBase::kPacketFlagSync = 0x01;
    *payload_len = total_len - 2;
    *payload     = header + 2;

    if (trace_level_ & kTraceDetail)
      sql_print_information("%s: reply - %d", kWho, *need_reply);
  }
  else
  {
    sql_print_error("Missing magic number for semi-sync packet, packet "
                    "len: %lu", total_len);
    read_res = -1;
  }

  return function_exit(kWho, read_res);
}

带有ack请求的binlog和不带ack的有区别吗?

就binlog本身而言,是一致的,只是在每一个binlog event的头部加了两个字节,来表示此event是否需要判别是否要返回ack。

猜你喜欢

转载自blog.csdn.net/sun_ashe/article/details/83347085