启动主从复制
由于我们只有一台机器,所以我们只能在机器上开多个redis程序来演示不同的机器
因为一个端口号只能被一个进程绑定,所以我们需要修改配置,绑定不同的端口号,并且还要修改工作目录(数据持久化的位置)
规划从节点
redis的配置文件在/etc/redis/redis.conf中,我们决定在这里创建一个redis-slave-conf目录,用来存放从节点的配置文件。
然后通过cp命令把原配置文件拷贝到redis-slave-conf目录中
然后创建再在/etc/redis/中创建第二个目录redis-slave-db,再在里面创建slave1和slave2目录,
配置从节点
进入第一个从节点配置文件
修改第一个从节点工作目录,并配置端口号为6380
进入第二个从节点配置文件
修改第二个从节点工作目录,并配置端口号为6381
另外,也可以配置daemonize 为 yes,意思是按照后台进程的方式运行
建立主从关系
到现在,我们就有了三个redis,但是这三个redis并没有构成主从关系。
我们三种方式建立主从关系
1.配置文件
2.在redis-server启动命令时加入 --slaveof {主节点地址} {主节点端口}
3.使用redis命令:slaveof {主节点地址} {主节点端口}
这里第二种方法和第三种方法都是临时设置,如果redis重启,是会还原的
为了让主从关系持久生效,我们需要修改配置文件
在文件末尾加上一行 slaveof 127.0.0.1 6379
(后面两个参数是指定主节点IP地址和redis端口,因为主节点就在本机,所以指定本地环回)
两个文件都添加
启动redis
启动主节点
启动从节点
使用netstat观察进程启动情况
这里前三个代表三个redis进程(6379,6380,6381)处于监听状态
后四个
tcp 0 0 127.0.0.1:6379 127.0.0.1:42527 ESTABLISHED 13620/redis-server
tcp 0 0 127.0.0.1:42711 127.0.0.1:6379 ESTABLISHED 13760/redis-server
tcp 0 0 127.0.0.1:6379 127.0.0.1:42711 ESTABLISHED 13620/redis-server
tcp 0 0 127.0.0.1:42527 127.0.0.1:6379 ESTABLISHED 13785/redis-server
两个一组,可以分为两组
一组表示一个从节点和主节点建立的tcp连接,主节点相当于服务器,从节点相当于客户端
端口 42527 和 42711 是从节点连接主节点的客户端端口
作用在于:
- 数据同步:从节点连接到主节点以获取最新的数据。这包括数据快照(RDB)和追加文件(AOF)。
- 命令传播:主节点将写命令传播到从节点,以确保所有节点数据一致。
- 心跳机制:从节点发送定期 PING 请求,以确保连接的健康状态,并检测主节点是否存活。
测试主从
首先我们在主节点插入一个数据key1
在从节点立刻就能get到
主从复制测试成功
从节点是不能写入数据的
查询主从信息
使用info replication命令查询
主节点:
解释输出:
- role: 当前节点的角色是主节点 (master)
- connected_slaves: 当前连接的从节点数量是
2
。- slave0: 第一个从节点的信息,IP 地址为
127.0.0.1
,端口为6380
,状态为online
,当前复制偏移量为2565
,延迟为1
。- slave1: 第二个从节点的信息,IP 地址为
127.0.0.1
,端口为6381
,状态为online
,当前复制偏移量为2565
,延迟为1
。- master_replid: 主节点的复制 ID,用于标识主节点的唯一标识。
- master_replid2: 备用的主节点复制 ID。
- master_repl_offset: 主节点的复制偏移量是
2565
,表示主节点当前的复制进度。- second_repl_offset: 第二个复制偏移量。
- repl_backlog_active: 复制回放是否处于活动状态 (
1
表示活动)。- repl_backlog_size: 复制回放缓冲区大小为
1048576
字节。- repl_backlog_first_byte_offset: 复制回放缓冲区的第一个字节偏移量。
- repl_backlog_histlen: 复制回放缓冲区历史长度为
2565
,表示历史记录中包含了多少条复制信息。
从节点:
解释输出:
- role: 当前节点的角色是从节点 (slave)
- master_host: 连接的主节点的 IP 地址是
127.0.0.1
。- master_port: 连接的主节点的端口是
6379
。- master_link_status: 与主节点的连接状态是
up
,表示连接正常。- master_last_io_seconds_ago: 距离上次与主节点通信的时间是
1
秒。- master_sync_in_progress: 没有进行数据同步操作。
- slave_repl_offset: 从节点当前的复制偏移量是
2257
。- slave_priority: 从节点的优先级为
100
。在故障转移时,优先级较高的从节点可能会被选为新的主节点。- slave_read_only: 从节点设置为只读模式 (
1
)。- connected_slaves: 当前连接的从节点数量是
0
。- master_replid: 主节点的复制 ID,用于标识主节点的唯一标识。
- master_replid2: 备用的主节点复制 ID。
- master_repl_offset: 主节点的复制偏移量是
2257
,与主节点的数据同步的偏移量。- second_repl_offset: 第二个复制偏移量。
- repl_backlog_active: 复制回放是否处于活动状态 (
1
表示活动)。- repl_backlog_size: 复制回放缓冲区大小为
1048576
字节。- repl_backlog_first_byte_offset: 复制回放缓冲区的第一个字节偏移量。
- repl_backlog_histlen: 复制回放缓冲区历史长度为
2257
,表示历史记录中包含了多少条复制信息。
断开主从复制关系
使用redis命令 slaveof no one断开现有的主从复制关系
从节点使用这个命令后,就不再属于其他节点了,里面的数据也不会抛弃,但是不会再同步主节点的数据了。
从节点断开后,变成主节点
建立主从复制关系流程
1)保存主节点(master)的信息
2)建立tcp连接
从节点会通过定时任务每秒检查主节点的连接状态,并尝试建立基于 TCP 的网络连接。如果连接失败,定时任务会无限重试,直到连接成功或用户停止主从复制。
3)发送ping命令
一旦 TCP 连接建立成功,从节点会发送一个ping 命令到主节点,确认主节点在应用层上是否工作正常。如果从主节点未能及时回复pong,从节点会断开连接,等待下次定时任务重新建立连接。
4)权限验证
如果主节点配置了requirepass参数来启用密码验证,从节点需要通过masterauth参数来设置密码进行验证。如果验证失败,从节点将停止复制。
5)同步数据集
全量同步和部分同步(后面讲)
6)命令持续复制
一旦从节点完成了初始数据同步,主节点会持续地将所有写操作命令发送给从节点。从节点执行这些命令,以确保数据与主节点保持一致。这些命令是通过主节点的复制缓冲区传递的,从节点会实时应用这些命令。
同步数据集
再建立主从关系时,会进行数据同步,也就是把主节点已有的数据同步给从节点
redis提供了psync命令来完成数据同步,这个命令不需要手动执行,在建立主从复制关系时会自动调用,是从节点调用psync,从主节点拉取数据
psync replicationid offset
其中,replicationid用来唯一标识主节点,建立主从关系时主节点自动生成
(可以通过info replication 命令查看,是master_replid项)
(还有一个master_replid2 项,一般没用,如果主节点挂了,从节点就会生成一个自己的id,然后把原来主节点的id存放在master_replid2中,等后续恢复)
offset 偏移量
主节点和从节点都会维护一个偏移量,表示数据流中的位置
主节点维护一个全局的复制偏移量,每当有新的写操作发生时,这个偏移量会增加。从节点也会维护自己的复制偏移量,表示它已经接收到并处理的数据位置。
所以,当从节点的偏移量和主节点的偏移量相同时,认为从节点的数据与主节点的数据是一致的。
从节点每秒种上报自身的复制偏移量给主节点
这里replicationid和offset两个变量标识了一个数据集合,比如从A时刻之前的主节点上的数据
当从节点发送psync命令给主节点后,主节点会决定如何给从节点同步数据
根据情况不同,分为全量复制和部分复制
全量复制的情况:
1.从节点首次和主节点进行数据同步
2.需要同步的数据超出主节点的复制积压缓冲区
部分复制的情况:
1.对于已经进行过一次全量同步的从节点,如果复制过程中连接中断了,从节点会尝试部分同步。
2.大部分数据都是一致的
全量复制
1)从节点发送 psync 命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的运行 ID 和复制偏移量,所以发送 psync ? -1
2)主节点根据命令,解析出要进行全量复制,回复 +FULLRESYNC 响应。
3)从节点接收主节点的运行信息进行保存。
4)主节点执行 bgsave 进行 RDB 文件的持久化。
5)主节点发送 RDB 文件给从节点,从节点保存 RDB 数据到本地硬盘。
6)主节点将从生成 RDB 到接收完成期间执行的写命令,写入缓冲区中,等从节点保存完 RDB 文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照 rdb 的二进制格式追加写入到收到的 rdb 文件中,保持主从一致性。
7)从节点清空自身原有旧数据。
8)从节点加载 RDB 文件得到与主节点一致的数据。
9)如果从节点加载 RDB 完成之后,并且开启了 AOF 持久化功能,它会进行 bgrewrite 操作,得到最近的 AOF 文件。
如果开启了AOF,可能会产生很多AOF日志,所以还会对AOF日志进行整理
部分复制
全量复制因为要网络传输所有数据,开销太大,但有时候只需要复制部分数据,比如当网络抖动的时候,可能从节点只有几秒钟和主节点断开连接,也就是说从节点只缺少几秒钟的数据,这时候就不需要全量复制
1)当主从节点之间出现网络中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并终端复制连接。
2)主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
3)当主从节点网络恢复后,从节点再次连上主节点。
4)从节点将之前保存的 replicationId 和 复制偏移量作为 psync 的参数发送给主节点,请求进行部分复制。
5)主节点接到 psync 请求后,进行必要的验证。随后根据 offset 去复制积压缓冲区查找合适的数据, 并响应 +CONTINUE 给从节点。
6)主节点将需要从节点同步的数据发送给从节点,最终完成一致性。
复制积压缓冲区
复制积压缓冲区是保存在主节点上的一个固定长度的队列,默认大小为 1MB,当主节点有连接的从节点(slave)时被创建,这时主节点(master)响应写命令时,不但会把命令发送给从节点,还会写入复制积压缓冲区,
这个相当于一个基于数组实现的环形队列,队列满后,新数据会覆盖最老的数据
如果当前从节点需要的数据, 已经超出了主节点的积压缓冲区的范围, 则无法进行部分复制, 只能全量复制了.
实时复制(命令传播)
当从节点和主节点已经同步好数据了,后续,主节点还会源源不断收到写操作,也需要把后续的操作都同步给从节点。
主节点会和从节点建立tcp连接,也就是上面我们查到的。主节点把自己收到的修改数据的请求,通过tcp连接发给从节点,从节点再根据发来的修改请求,修改内存中的数据。
心跳机制
在进行实时复制的时候,需要保证连接处于可用状态
主节点:默认每10秒给从节点发送一个ping命令,从节点收到就返回pong
从节点:默认每隔1秒就给主节点发送一个特定的请求,上报复制数据的进度(偏移量)
(以上数字都可以在配置文件中修改)