《Redis设计与实现》—— Redis底层原理与实现(下)

本文详细探讨了Redis的复制功能,包括旧版与新版复制的区别,重点介绍了PSYNC命令及其优化的同步模式。此外,文章还深入讲解了Sentinel哨兵系统的启动、监控、故障转移流程,以及如何通过心跳检测确保主从服务器的连接稳定性。最后,文中提到了Redis集群的分片、故障转移和节点间的通信机制。
摘要由CSDN通过智能技术生成

多机数据库的实现

十四、复制

​ 用户可以通过执行SLAVEOF命令以及设置slaveof选项,让一个服务器去复制另一个服务器。

在这里插入图片描述

14.1 旧版复制功能

Redis的复制功能分为同步与命令传播两个操作;

1、同步

客户端向从服务器发送SLAVEOF命令,则从服务器需要先执行同步操作,,从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下为SYNC的执行步骤:

在这里插入图片描述

1、从向主发送SYNC命令;
2、主收到后执行BGSAVE命令,后台生成一个RDB文件,使用缓冲区记录从现在开始执行的所有写命令;
3、BGSAVE执行完,主发送RDB文件给从,从接收并载入RDB;
4、主发送缓冲区保存的所有写命令,藏执行这些写命令;

2、命令传播

执行完同步后,客户端对主服务器的所有后续操作,主服务器都会向从发送执行的命令来保证后续的一致性;

14.2 旧版复制缺陷

复制分为初次复制和断线后重复制,对于初次复制,旧版实现可以很好完成,但对于断线后重复制,会出现下面的例子:

在这里插入图片描述

问题即是为了让从服务器不足一部分缺失的数据,却得让主从服务器重新执行一次SYNC命令,这样的效率分成低;

14.3 新版复制功能

新版使用PSYNC命令替换SYNC命令,而PSYNC命令具有完整同步和部分同步两种模式;部分同步就解决了旧版的低效问题;

在这里插入图片描述

1、部分重同步实现

  • 主服务器的复制偏移量和从服务器的复制偏移量;
  • 主服务器的复制积压缓冲区;
  • 服务器运行的ID;

复制偏移量

主从都分别维护一个复制偏移量;主每次发送N个字节数据,自己的复制偏移量就+N;从收到主的N个字节数据,自己的复制偏移量也+N。通过复制偏移量可以知道主从的一致性;

复制积压缓冲区

由主服务器维护的一个固定长度先进先出队列,默认为1MB(固定长度先进先出队列执行时,当入队元素数量>队列长度时,最先入队元素会被弹出,新元素放入);
主进行命令传播时,不仅发送命令给从,还会将写命令入队到复制积压缓冲区。
当从重新连上主时,从会通过PSYNC命令将自己的复制偏移量offset发给主,主根据offset来决定执行何种同步:
若offset偏移后的数据存在于复制积压缓冲区,则进行部分同步;不在则进行完整重同步;

在这里插入图片描述

服务器运行ID

每个Redis服务器都有自己的运行ID,从对主进行初次复制时,主会发送自己的ID给从,从会保存下来,之后断线重连时,从会发送保存的ID给主,若ID相同,则主可以尝试执行部分重同步,不同则需要执行完整重同步;

14.4 PSYNC命令实现

在这里插入图片描述

14.5 复制实现

通过命令SLAVEOF <master_ip> <master_port>;

1、步骤1:设置主服务器的地址和端口

struct redisServer {
   
    //....
    //主服务器地址
    char *masterhost;
    //主服务器端口
    int masterport;
    //...
};

2、步骤2:建立套接字

3、步骤3:发送PING命令

在这里插入图片描述

4、步骤4:身份验证

在这里插入图片描述

5、步骤5:发送端口信息

步骤四之后,从将执行REPLCONF listening-port ,向主发送从的监听端口号。主会将端口号记录在从对应的客户端状态的slave_listening_port属性中:

typedef struct redisClient {
   
    //...
    //从的监听端口号
    int slave_listening_port;
    //...
}redisClient;

6、步骤6:同步

7、步骤7:命令传播

14.6 心跳检测

命令传播阶段,从会默认每秒一次向主发送命令:REPLCONF ACK <replication_offset>,其中replication_offset就是从服务器当前的复制偏移量;

该命令作用:

1、检测主从服务器的网络连接状态

若主服务器发送INFO replication命令,在列出的从服务器列表的lag一栏中,可看到相应从最后一次向主发送REPLCONF ACK 命令距离现在过了多少秒:(lag一般在0或1之间跳动,超过1,说明主从连接出现故障)

127.0.0.1:6379> INFO replication
role:master
....
slave0:ip=.....,lag=0 # 刚刚发送过REPLCONF ACK 命令
slave1:ip=.....,lag=15 # 15秒前发送过REPLCONF ACK 命令

2、辅助实现min-slaves配置选项

Redis的min-slaves-to-write和min-slaves-max-lag可放置主服务器在不安全情况下执行写命令;

举个例子:

min-slaves-to-write 3
min-slaves-max-lag 10
# 从服务器数量<3个或三个从服务器的延迟(lag)都>=10s,则主服务器拒绝执行写命令

3、检测命令丢失

若由于网络故障,主给从发送的命令丢失,则从给主发送REPLCONF ACK 时,主会发现replication_offset不一致,所以会去找复制积压缓冲区里对应的指令进行命令的补发

注意:补发缺失数据操作在主从没有断线情况下执行;而部分重同步时主从断线并重连后执行。

十五、Sentinel

​ 由一个或多个Sentinel(哨兵、哨岗)组成的Sentinel系统可监视多台主从服务器,主服务器下线时,可进行故障转移,将从服务器升级为主服务器。

在这里插入图片描述

在这里插入图片描述

15.1 启动并初始化Sentinel

# 启动一个Sentinel可以使用的命令
$ redis-sentinel /path..../sentinel.conf
或 $ redis-server /path.../sentinel.conf --sentinel

启动一个Sentinel时执行的步骤:

1、初始化服务器

Sentinel本质是一个特殊模式下的Redis服务器,所以初始化步骤与13章类似。不过略有不同,主要功能使用情况如下:

在这里插入图片描述

2、使用Sentinel专用代码

例如使用sentinel.c/sentinelcmds作为服务器的命令表,使用sentinel.c/REDIS_SENTINEL_PORT常量值作为服务器端口;

3、初始化Sentinel状态

保存服务器中所有和Sentinel功能相关的状态:

struct sentinelState {
   
    //当前纪元,用于实现故障转移
    uint64_t current_epoch;
    
    //保存所有被这个sentinel监视的主服务器
    //字典的键为主服务器名,值为指向sentinelRedisInstance结构的指针
    dict *masters;
    
    //是否进入TILT模式
    i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值