共计 4018 个字符,预计需要花费 11 分钟才能阅读完成。
redis 高可用
redis 主从
CAP 原理
- C: 一致性
- A: 可用性
- P: 分区容忍性
分布式系统的节点往往都是散布在不同的机器上进行网络隔离开的,这意味着必然会有网络断开的危险,这个网络断开的场景的业余词汇叫网络分区。
当网络分区产生时,两个分布式节点之间无奈进行通信,咱们对一个节点的批改操作无奈同步到另一个节点,所以数据的一致性将无奈满足。除非咱们就义可用性,也就是暂停分布式服务,在网络分区产生时不再提供批改数据的性能,直到网络情况齐全恢复正常再持续对外提供服务。
CAP:当网络分区产生时,一致性和可用性两难全。
最终统一
redis 的主从数据都是异步同步的,所以分布式 redis 不满足一致性的要求。当客户端在 redis 的主节点批改了数据后立刻返回,即便在主从网络断开的状况下,主节点仍旧能够失常对外提供批改服务,所以 redis 满足可用性。
redis 保障最终一致性,从节点会致力追赶主节点,最终从节点的状态会和主节点的状态保持一致。如果网络断开了,主从节点的数据会呈现大量不统一,但一旦网络复原,从节点会采纳多种策略致力追赶,持续尽力放弃和主节点统一。
主从同步
如何进行主从同步
须要留神,主从复制的开启,齐全是在从节点发动的;不须要咱们在主节点做任何事件。
从节点开启主从复制,有 3 种形式:
- 配置文件
在从服务器的配置文件中退出:slaveof <masterip> <masterport>
- 启动命令
redis-server 启动命令后退出 —slaveof <masterip> <masterport>
- 客户端命令
Redis 服务器启动后,间接通过客户端执行命令:slaveof <masterip> <masterport>
,则该 Redis 实例成为从节点。
断开复制:
通过 slaveof <masterip> <masterport>
命令建设主从复制关系当前,能够通过 slaveof no one
断开。须要留神的是,从节点断开复制后,不会删除已有的数据,只是不再承受主节点新的数据变动。
从节点执行 slaveof no one
后,打印日志如下所示;能够看出断开复制后,从节点又变回为主节点:
[image:78C4F792-4EEB-4F44-9DAF-96837A296B27-1128-000018F29E3D7E5F/493BD180-F46A-48EF-A661-95A2643B9EF2.png]
主节点打印日志如下:
[image:AD5036CA-AE6F-45C4-8E8D-F82BCD908CA5-1128-000018F724596E6C/C280DF44-8820-41AE-A4C9-1D4D0261101E.png]
主从同步的步骤
须要留神的是,在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及当前,主从节点互为客户端。起因在于:在此之前,主节点只须要响应从节点的申请即可,不须要被动发申请,而在数据同步阶段和前面的命令流传阶段,主节点须要被动向从节点发送申请(如推送缓冲区中的写命令),能力实现复制。
主从同步分为 2 个步骤:同步和命令流传
- 同步:将从服务器的数据库状态更新成主服务器以后的数据库状态。
- 命令流传:当主服务器数据库状态被批改后,导致主从服务器数据库状态不统一,此时须要让主从数据同步到统一的过程。
这里须要提前阐明一下:在 Redis 2.8 版本之前,进行主从复制时肯定会程序执行上述两个步骤,而从 2.8 开始则可能只须要执行命令流传即可
同步阶段
- 全量复制
- 从服务器向主服务器发送 sync 命令
- 收到 sync 命令后,主服务器执行 bgsave 命令,用来生成 rdb 文件,并在一个缓冲区中记录从当初开始执行的写命令。
- bgsave 执行实现后,将生成的 rdb 文件发送给从服务器,用来给从服务器更新数据
- 主服务器再将缓冲区记录的写命令发送给从服务器,从服务器执行完这些写命令后,此时的数据库状态便和主服务器统一了。
全量复制是十分重型的操作:
- 主服务器须要执行 bgsave 命令来生成 RDB 文件,这个生成操作会消耗主服务器大量的 cpu,内存和磁盘 io 资源。
- 主服务器须要将本人生成的 RDB 文件发送给从服务器,这个发送操作会消耗主服务器大量的网络资源(带宽和流量),并对主服务器响应命令申请的工夫产生影响。
- 接管到 RDB 文件的从服务器须要清空老数据,载入主服务器发来的 RDB 文件,并且在载入期间从服务器会因为阻塞而没方法解决命令申请。
- 局部复制
局部复制的实现,依赖于三个重要的概念:
- 主从服务器的复制偏移量
- 主服务器的复制积压缓冲区
- 服务器的运行 id(run id)
- 复制偏移量
执行复制的主从服务器都会别离保护各自的复制偏移量:
主服务器每次向从服务器流传 n 个字节数据时,都会将本人的复制偏移量加 n。
从服务器承受主服务器传来的数据时,也会将本人的复制偏移量加 n
举个例子:
若以后主服务器的复制偏移量为 10000,此时向从服务器流传 30 个字节数据,完结后复制偏移量为 10030。
这时,从服务器还没接管这 30 个字节数据就断线了,而后从新连贯上之后,该从服务器的复制偏移量仍旧为 10000,阐明主从数据不统一,此时会向主服务器发送 psync 命令。
那么主服务器应该对从服务器执行残缺重同步还是局部重同步呢?如果执行局部重同步的话,主服务器又如何晓得同步哪些数据给从服务器呢?
以下答案都和复制积压缓冲区无关
- 复制积压缓冲区
复制积压缓冲区是由主节点保护的、固定长度的、先进先出 (FIFO) 队列,默认大小 1MB;当主节点开始有从节点时创立,其作用是备份主节点最近发送给从节点的数据。留神,无论主节点有一个还是多个从节点,都只须要一个复制积压缓冲区。
在命令流传阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset)。因为复制积压缓冲区定长且是先进先出,所以它保留的是主节点最近执行的写命令;工夫较早的写命令会被挤出缓冲区 。
因为该缓冲区长度固定且无限,因而能够备份的写命令也无限,当主从节点 offset 的差距过大超过缓冲区长度时,将无奈执行局部复制,只能执行全量复制。反过来说,为了进步网络中断时局部复制执行的概率,能够依据须要增大复制积压缓冲区的大小 (通过配置 repl-backlog-size);例如如果网络中断的均匀工夫是 60s,而主节点均匀每秒产生的写命令(特定协定格局) 所占的字节数为 100KB,则复制积压缓冲区的均匀需要为 6MB,保险起见,能够设置为 12MB,来保障绝大多数断线状况都能够应用局部复制。
从节点将 offset 发送给主节点后,主节点依据 offset 和缓冲区大小决定是否执行
局部复制:
* 如果 offset 偏移量之后的数据,依然都在复制积压缓冲区里,则执行局部复制;* 如果 offset 偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。
- run id
运行 id 是在进行首次复制时,主服务器将会将本人的运行 id 发送给从服务器,让其保存起来。
当从服务器断线重连后,从服务器会将这个运行 id 发送给刚连贯上的主服务器。
若以后服务器的运行 id 与之雷同,阐明从服务器断线前复制的服务器就是以后服务器,主服务器能够尝试执行局部同步;若不同则阐明从服务器断线前复制的服务器不是以后服务器,主服务器间接执行残缺重同步。
psync 命令的执行过程能够参见下图(图片起源:《Redis 设计与实现》):
命令流传
在命令流传阶段,除了发送写命令,主从节点还维持着心跳机制:PING 和 REPLCONF ACK。心跳机制对于主从复制的超时判断、数据安全等有作用
通过同步操作,此时主从的数据库状态其实曾经统一了,但这种统一的状态的并不是变化无穷的。
在实现同步之后,兴许主服务器马上就承受到了新的写命令,执行完该命令后,主从的数据库状态又不统一。
为了再次让主从数据库状态统一,主服务器就须要向从服务器执行命令流传操作,即把方才造成不统一的写命令,发送给从服务器去执行。从服务器执行实现之后,主从数据库状态就又复原统一了。
PING(主 -> 从)
每隔指定的工夫,主节点会向从节点发送 PING 命令,这个 PING 命令的作用,次要是为了让从节点进行超时判断。
PING 发送的频率由 repl-ping-slave-period 参数管制,单位是秒,默认值是 10s。
REPLCONF ACK(从 -> 主)
当实现了同步之后,主从服务器就会进入命令流传阶段,此时从服务器会以每秒 1 次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset>
其中 replication_offset
是从服务器以后的复制偏移量
发送这个命令次要有三个作用:
- 检测主从服务器的网络状态,在主节点中应用 info Replication,能够看到其从节点的状态中的 lag 值,代表的是主节点上次收到该 REPLCONF ACK 命令的工夫距离,在失常状况下,该值应该是 0 或 1
- 检测命令失落(若失落,主服务器会将失落的写命令从新发给从服务器)
- 辅助保障从节点的数量和提早:Redis 主节点中应用 min-slaves-to-write 和 min-slaves-max-lag 参数,来保障主节点在不平安的状况下不会执行写命令;所谓不平安,是指从节点数量太少,或提早过高。例如 min-slaves-to-write 和 min-slaves-max-lag 别离是 3 和 10,含意是如果从节点数量小于 3 个,或所有从节点的提早值都大于 10s,则主节点拒绝执行写命令。而这里从节点提早值的获取,就是通过主节点接管到 REPLCONF ACK 命令的工夫来判断的,即后面所说的 info Replication 中的 lag 值。
参考文章
https://zhuanlan.zhihu.com/p/…
https://www.cnblogs.com/kisme…