一、原理与作用
原理:
1.副本库通过slaveof 10.0.0.51 6380命令,连接主库,并发送psync给主库
2.主库收到psync,会立即触发BGSAVE,后台保存RDB,发送给副本库
3.副本库接收后会应用RDB快照
4.主库会陆续将中间产生的新的操作,保存并发送给副本库
5.到此,我们主从复制集就正常工作了
6.再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库
7.所有复制相关信息,从info信息中都可以查到,即使重启任何节点,他的主从关系依然都在
8.如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9.主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的
作用:
1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2.实现读写分离(主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性)
3.故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
4.高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
二、主从数据一致性保证
min-slaves-to-write 1 #最少1台从库写入,或应用了操作
min-slaves-max-lag 3 #从库与主库延迟超过3s,也会被认为是失败的
三、主库是否要开启持久化?
如果不开有可能,主库重启操作,造成所有主从数据丢失
四、主从复制实现
从节点建议用只读模式slave-read-only=yes, 若从节点修改数据,主从数据不一致。默认从节点就是模式
传输延迟:主从一般部署在不同机器上,复制时存在网络延时问题,redis提供repl-disable-tcp-nodelay参数决定是否关闭TCP_NODELAY,默认为关闭
参数关闭时:无论大小都会及时发布到从节点,占带宽,适用于主从网络好的场景
参数启用时:主节点合并所有数据成TCP包节省带宽,默认为40毫秒发一次,取决于内核,主从的同步延迟40毫秒,适用于网络环境复杂或带宽紧张,如跨机房
环境: 准备两个或两个以上redis实例 mkdir /data/638{0..2} 配置文件示例: cat >> /data/6380/redis.conf <<EOF port 6380 daemonize yes bind 0.0.0.0 pidfile /data/6380/redis.pid loglevel notice logfile "/data/6380/redis.log" dbfilename dump.rdb dir /data/6380 requirepass 123456 masterauth 123456 EOF cat >> /data/6381/redis.conf <<EOF port 6381 daemonize yes bind 0.0.0.0 pidfile /data/6381/redis.pid loglevel notice logfile "/data/6381/redis.log" dbfilename dump.rdb dir /data/6381 requirepass 123456 masterauth 123456 EOF cat >> /data/6382/redis.conf <<EOF port 6382 daemonize yes bind 0.0.0.0 pidfile /data/6382/redis.pid loglevel notice logfile "/data/6382/redis.log" dbfilename dump.rdb dir /data/6382 requirepass 123456 masterauth 123456 EOF 启动 redis-server /data/6380/redis.conf redis-server /data/6381/redis.conf redis-server /data/6382/redis.conf 主节点:6380 从节点:6381、6382 开启主从: 6381/6382命令行: redis-cli -p 6381 -a 123456 SLAVEOF 127.0.0.1 6380 redis-cli -p 6382 -a 123456 SLAVEOF 127.0.0.1 6380 查询主从状态 redis-cli -p 6380 -a 123456 info replication redis-cli -p 6381 -a 123456 info replication redis-cli -p 6382 -a 123456 info replication
五、相关命令
查看状态:info replication
断开主从复制:在slave节点,执行6381:>slaveof no one
断开后再变成主从复制:6381:> slaveof 10.0.0.250 6380
六、主从的缺点
a)主从复制,若主节点出现问题,则不能提供服务,需要人工修改配置将从变主
b)主从复制主节点的写能力单机,能力有限
c)单机节点的存储能力也有限
七、全量复制和部分复制
在Redis2.8以前,从节点向主节点发送sync命令请求同步数据,此时的同步方式是全量复制;
在Redis2.8以后,从节点可以发送psync命令请求同步数据,此时根据主从节点当前状态的不同,同步方式可能是全量复制或部分复制。
全量复制:用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。
部分复制:用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
全量复制
Redis通过psync命令进行全量复制的过程如下:
(1)从节点判断无法进行部分复制,向主节点发送全量复制的请求;或从节点发送部分复制的请求,但主节点判断无法进行全量复制;
(2)主节点收到全量复制的命令后,执行bgsave,在后台生成RDB文件,并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令
(3)主节点的bgsave执行完成后,将RDB文件发送给从节点;从节点首先清除自己的旧数据,然后载入接收的RDB文件,将数据库状态更新至主节点执行bgsave时的数据库状态
(4)主节点将前述复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据库状态更新至主节点的最新状态
(5)如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的最新状态
通过全量复制的过程可以看出,全量复制是非常重型的操作:
(1)主节点通过bgsave命令fork子进程进行RDB持久化,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的;
(2)主节点通过网络将RDB文件发送给从节点,对主从节点的带宽都会带来很大的消耗
(3)从节点清空老数据、载入新RDB文件的过程是阻塞的,无法响应客户端的命令;如果从节点执行bgrewriteaof,也会带来额外的消耗
部分复制
由于全量复制在主节点数据量较大时效率太低,因此Redis2.8开始提供部分复制,用于处理网络中断时的数据同步。
部分复制的实现,依赖于三个重要的概念:复制偏移量,复制积压缓冲区,服务器运行ID
复制偏移量
主节点和从节点分别维护一个复制偏移量(offset),代表的是主节点向从节点传递的字节数;主节点每次向从节点传播N个字节数据时,主节点的offset增加N;从节点每次收到主节点传来的N个字节数据时,从节点的offset增加N。
offset用于判断主从节点的数据库状态是否一致:如果二者offset相同,则一致;如果offset不同,则不一致,此时可以根据两个offset找出从节点缺少的那部分数据。例如,如果主节点的offset是1000,而从节点的offset是500,那么部分复制就需要将offset为501-1000的数据传递给从节点。而offset为501-1000的数据存储的位置,就是下面要介绍的复制积压缓冲区。
复制积压缓冲区
复制积压缓冲区是由主节点维护的、固定长度的、先进先出(FIFO)队列,默认大小1MB;当主节点开始有从节点时创建,其作用是备份主节点最近发送给从节点的数据。注意,无论主节点有一个还是多个从节点,都只需要一个复制积压缓冲区。
在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset)。由于复制积压缓冲区定长且是先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。
由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size);例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。
从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:
如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。
服务器运行ID(runid)
每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都不一样),由40个随机的十六进制字符组成;
runid用来唯一识别一个Redis节点。通过info Server命令,可以查看节点的runid。
主从节点初次复制时,主节点将自己的runid发送给从节点,从节点将这个runid保存起来;当断线重连时,从节点会将这个runid发送给主节点;主节点根据runid判断能否进行部分复制:
如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。
八、主节点宕机
当主节点宕机的时候,这时候我们需要手动将从节点设置成主节点
命令:
redis-cli -h <从节点ip> -p <从节点端口号> slaveof no one
或者在从节点redis进入命令行,输入slaveof no one
恢复数据后重新搭建主从节点。