redis主从复制过程中,slave端混读PING命令的问题
2016-01-08 12:43
781 查看
最近两日在调试redis代码时遇到两个问题:
1.主从复制过程中,slave端的readSyncBulkPayload会读到错误的信息(主服务器发来的PING命令的一部分),导致slave端一直在向主服务器发送同步请求。
2.主从同步结束后,进入命令传播阶段。主服务器向从服务器传播命令后,如果命令执行成功,从服务器会返回+OK\r\n,主服务器不能识别这个命令,导致失败。
经过两天的调试后发现问题的发生原因如下:
1.如下图:
主服务器在发送PING时,从服务器会有一段时间处于readSyncBulkPayload事件处理阶段,如果这时读到了PING就会出错。
而redis源码是这样避免这个问题的:
redis在这里设计的思想是,slave如果处于END之后的阶段,主服务器的命令对它来说就是新的命令了,而当它处于ONLINE阶段时,才能正式的从主服务器读取命令。
2.从服务器向主服务器发送+PONG时,进入perpareClientToWrite()。结果发现它是主服务器而又没有REDIS_MASTER_FORCE_REPLY,所以不会向主服务器发送PONG。
而之所以从服务器向主服务器发送ACK会成功,原因如下:
因为设置了 REDIS_MASTER_FORCE_REPLY,就会成功绑定sendReplyToClient
1.主从复制过程中,slave端的readSyncBulkPayload会读到错误的信息(主服务器发来的PING命令的一部分),导致slave端一直在向主服务器发送同步请求。
2.主从同步结束后,进入命令传播阶段。主服务器向从服务器传播命令后,如果命令执行成功,从服务器会返回+OK\r\n,主服务器不能识别这个命令,导致失败。
经过两天的调试后发现问题的发生原因如下:
1.如下图:
主服务器在发送PING时,从服务器会有一段时间处于readSyncBulkPayload事件处理阶段,如果这时读到了PING就会出错。
而redis源码是这样避免这个问题的:
int prepareClientToWrite(redisClient *c) { if ((c->flags & REDIS_MASTER) && !(c->flags & REDIS_MASTER_FORCE_REPLY)) return REDIS_ERR; if (c->fd <= 0) return REDIS_ERR; if (c->bufpos == 0 && listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE ||c->replstate == REDIS_REPL_ONLINE) && aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,sendReplyToClient, c) == AE_ERR) return REDIS_ERR; return REDIS_OK; }可以看到它在这才判断client的状态,如果他的状态处于NONE或者ONLINE才会绑定写事件。而它在ONLINE时已完成了同步,进入readQueryFromClient函数处理的阶段了。
redis在这里设计的思想是,slave如果处于END之后的阶段,主服务器的命令对它来说就是新的命令了,而当它处于ONLINE阶段时,才能正式的从主服务器读取命令。
2.从服务器向主服务器发送+PONG时,进入perpareClientToWrite()。结果发现它是主服务器而又没有REDIS_MASTER_FORCE_REPLY,所以不会向主服务器发送PONG。
而之所以从服务器向主服务器发送ACK会成功,原因如下:
void replicationSendAck(void) { redisClient *c = server.master; int optVal = 0; int optLen = sizeof(optVal); getsockopt(c->fd, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen); if (c != NULL) { c->flags |= REDIS_MASTER_FORCE_REPLY; addReplyMultiBulkLen(c, 3); addReplyBulkCString(c, "REPLCONF"); addReplyBulkCString(c, "ACK"); // 发送偏移量 addReplyBulkLongLong(c, c->reploff); c->flags &= ~REDIS_MASTER_FORCE_REPLY; } }
因为设置了 REDIS_MASTER_FORCE_REPLY,就会成功绑定sendReplyToClient
相关文章推荐
- Redis Cluster(Redis 3.X)设计要点
- redis事务的那些事情
- redis在linux上部署,Redis服务器搭建/配置/及Jedis客户端的使用方法(java语言)
- redis
- Java中使用Jedis操作Redis
- 如何在CentOS 7上安装Redis服务器
- redis集群环境搭建以及java中jedis客户端集群代码实现
- Redis主从同步分析
- redis 笔记04 服务器、复制
- spark访问Redis并进行操作
- Ubuntu环境下Redis的安装与JAVA连接测试
- redis的py语法lrem
- Redis学习记录之下载安装(二)
- Redis学习记录之简介(一)
- Redis在Windows上的配置方案
- redis重启失败
- Centos 下编译安装Redis
- redis集群安装
- NodeJS+Redis实现分布式Session方案
- Redis中hash表中的field的value自增可以用hincrby