一、复制SLAVEOF
-
旧版本复制功能:sync同步、command propagate命令传播
-
同步:当客户端像从服务器发送SLAVEOF
-
从服务器向主服务器发送SYNC命令
-
主服务器收到SYNC命令,执行BGSAVE,并使用一个缓冲区缓存从现在开始的命令
-
BGSAVE完成,将文件发送给从服务器
-
主服务器将缓冲区的命令发送到从服务器执行
-
-
命令传播
-
主服务器将执行的写命令发送到从服务器执行
-
-
-
旧版本复制功能缺陷
-
初次复制:旧版本没有问题
-
断线后重新复制:虽然旧版本可以完成,但效率很低。SYNC命令是非常消耗资源
-
SYNC会导致主服务器执行BGSAVE,消耗CPU、内存、磁盘I/O
-
主服务器将RDB发送从服务器消耗网络资源
-
从服务器加载RDB文件期间,不能处理请求
-
-
-
新版本复制功能:PSYNC命令
-
完整重同步,与SYNC基本一样
-
部分重同步,主服务器将断线期间的写明令发给从服务器
-
复制偏移量:主服务器、从服务器都维护了一个偏移量
-
复制积压缓冲区:固定长度FIFO队列,默认1MB
-
服务器运行ID
-
-
部分同步
-
从服务器重连上主服务器,发送PSYNC 自己偏移量
-
主服务器判断该ID的从服务器偏移量数据是否在复制积压缓冲区,不在则进行全量同步;在缓冲区,则回复+CONTINUE
-
发送复制缓冲区偏移量之后的数据到从服务器
-
-
-
复制的实现
-
设置主服务器的地址、端口:SLAVEOF ip port
-
建立套接字连接
-
发送PING命令
-
身份验证
-
发送端口信息:REPLCONF listening-port 22222
-
同步:从服务器发送PSYNC命令到主服务器
-
命令传播:主服务器每次执行完写命令,将其发送到从服务器
-
-
心跳检测
-
检测主从服务器的网络连接状态:REPLCONF ACK检测连接
-
辅助实现min-slaves配置:min-slaves-to-write 从服务器至少几个,min-slaves-max-lag 从服务器的延迟大于该数值
-
例如min-slaves-to-write 1 min-slaves-max-lag 5,从服务器数量少于1或者有1个从服务器的延迟大于5s,则主服务器拒绝请求。
-
-

二、Sentinel
-
启动并初始化Sentinel
-
初始化服务器:不需要载入RDB或AOF文件
-
将普通的Redis服务器代码替换成Sentinel专用:服务器端口、redisCommandTable替换为sentinelcmds
-
初始化Sentinel状态
-
根据配置文件,初始化Sentinel的监视主服务器列表
-
创建连想主服务器的网络连接
-

sentinel选举:
-
S1向S2、S3发送选举,S2与S3接收到后,发现均没有记录自己的选择,则将自己的选择设置为S1,并返回S1,然后S1判断返回是不是自己,记录选票数2,判断过半,则将自己选择为主sentinel;
-
S2向S1与S3发送选举,S1发现自己未选举,则将自己的选举设置成S2,并返回S2,S3发现自己已经选了S1,则返回S1,S2收到回复,得1票,未过半。
-
S3同理,得0票。
-
最差的情况,均同时发出选举请求,S1选S2,S2选S3,S3选S1,则判断选举失败;等下下次重新选举;选举时,每个sentinel中都会有个计数器,每次选举完(无论成功还是失败)均自增1,用来判断是否为同一轮选举。

redis master选举:
-
将所有slave保存到一个列表中
-
删除下线、断线的slave
-
删除近5秒没有回复sentinel的slave
-
删除与master断开超过down-after-milliseconds*10毫秒的slave
-
选出优先级最高的slave
-
优先级一样,则选择复制偏移量大的slave
-
偏移量也一致,则选取ID小的slave
三、集群
-
节点
-
CLUSTER MEET ip port将节点加入到集群
-
节点运行在集群模式参数cluster-enabled
-
CLUSTER MEET命令:客户端连接A,发送CLUSTER MEET B.ip port
-
节点A为节点B创建clusterNode结构,并将该结构添加到自己的clusterState.nodes中
-
向B发送MEET
-
B为A节点创建clusterNOde,并添加到自己的clusterState.nodes中
-
B向A发送PONG
-
A向B回复PING
-
-
-
槽:整个集群被分为16384(2的14次方)
-
每个节点会向其他节点通知自己负责的槽
-
集群执行命令
-
客户端向节点发送命令
-
节点判断该key是否为自己所处理的槽,是则直接执行命令
-
不是自己处理的槽,则向客户端返回MOVED错误
-
客户端根据MOVED的信息,转向正确的节点
-
-
判断槽的方法:利用key计算出所在的槽X(CRC16(key) & 16383),然后判断clusterState.slots数组的X项是否为clusterState.myself,是则为自己负责,不是则取出存储的clusterNode的ip与port,返回MODVED错误。
-
重新分片:redis-trib
-
让目标节点准备好从源节点导入槽的键值对
-
让源节点准备好将槽的键值对迁移到目标节点
-
获取定量个键值对
-
将键值对迁移到目标节点,循环3-4步骤,直到槽的键值对都迁移完成
-
像集群广播迁移信息(槽迁移到了哪)
-
-
ASK错误:槽迁移过程中的错误
-
客户端发送命令
-
源服务端接收到key,判断key是否还在,若key存在,则执行命令
-
key不存在,判断源节点是否正在迁移,不是正在迁移,返回key不存在
-
若源节点正在迁移,则向客户端返回ASK错误,带上迁移信息(目标节点)
-
客户端先像目标节点发送ASKING,然后将命令发送到目标节点
-
-
-
复制与故障处理
-
故障检测
-
集群中的每个节点都会定期向其他节点发送PING,如果规定时间内没有回复PONG,则标记该节点PFAIL疑似下线
-
然后会与集群其他节点交换节点信息状态,并将其他节点疑似下线的信息添加到自己维护的clusterState.nodes中该疑似下线节点的clusterNode的下线报告中
-
一个节点被认为疑似下线的主节点过半,则向所有其他节点发布节点下线通知FAIL
-
-
故障转移
-
slave得知自己的master下线了,则会从多个slave中选择一个slave(该主节点有多个从节点时)
-
slave执行SLAVEOF no one,变为master
-
该master撤销所有原master的槽指派,并将这些槽指派给自己
-
该master向集群广播PONG消息,通知自己升级为了master,并接管了原有的槽处理
-
-
主节点选举
-
FAIL的主节点的所有从节点向其他主节点发起投票请求
-
每个主节点可以投一票,每个从节点会收到投票结果
-
从节点判断超过半数,胜出,若没有选择出来,则继续下一轮,重新投票(每个节点里维护了一个计数器,类似于版本号或者那一轮,同一轮的票才可生效)
-
-
-
消息
-
MEET消息:将一个节点加入到集群中。
-
PING消息:每隔一定时间,节点就会随机选取5个节点发送PING消息,来检测选中的节点是否在线。
-
PONG消息:用来回复PING消息或者MEET消息。
-
FAIL消息:新的主节点判断老的主节点已经进入FAIL状态,会向集群广播旧节点FAIL消息。
-
PUBLISH消息:一个节点接收到PUBLISH命令,会广播该消息,其他节点执行PUBLISH。
-