- 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。