
本文共 3656 字,大约阅读时间需要 12 分钟。
redis 复制的原理与优化
1. 什么是主从复制
是在一个交换节点设立一高精度的基准时钟,通过传输链路把此基准时钟信号送到网中各个从节点,各个从节点利用锁相环技术把本地时钟频率锁定在基准时钟频率上,从而实现网内各节点之间的时钟信号同步 。
简单点来说就是通过网络传输链路将主数据库的数据发送到某一台服务器上。建立一个和主数据库完全一样的数据库环境,称之为从数据库。后续如果主数据库的数据发生变化会及时的通知到从服务器上(从数据库会与主数据库建立连接)。
redis中单机存在的问题:机器故障、容量瓶颈、QPS瓶颈——则采用RDB和AOF解决
redis中复杂环境中的高可用问题解决是采用复制的方案——哨兵和集群
主从复制的作用:
- 数据副本
- 扩展读性能
总结:
一个master可以有多个slave
一个slave只能有一个master
数据流向是单向的,master到slave
2. 复制的配置和流程
复制实际划分为主节点(master
)和从节点(slave
)。每个从节点只能有一个主节点,而主节点可以同时具有多个从节点。复制的数据流是单向的,只能由主节点复制到从节点。另外的话开启主从复制完全是在从节点发起的,不需要我们在主节点做任何事情。
三种配置复制方式:
-
slaveof命令启动——异步命令
redis-server`启动命令后添加参数 `--slaveof
slaveof no one 取消复制
【从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。主要流程第一断开与主节点复制关系,第二从节点晋升为主节点。】
-
配置文件
slaveof ip port
slave-read-only yes
主从复制流程:
-
保存配置;2. 建立连接;3. 发送ping命令;4. 权限校验;5. 数据同步;6. 持续监听
1. 保存配置
从节点服务器维护了masterhost
和masterport
两个字段,用于存储主节点的ip
和port
(这个很好理解,应为要建立连接必须要这个字段)。有一点需要注意的是,slaveof
是异步命令,从节点完成对主节点ip
和port
保存后,会向发送slaveof
命令的客户端直接返回OK
,实际的复制操作还没有开始。
2. 建立连接
建立连接的过程是通过轮询主节点配置来建立的。从节点(slave
)内部通过每秒运行的定时任务维护制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接。如果建立成功,则会为该socket
建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如接收RDB
文件、接收命令传播等。如果从节点无法建立连接,定时任务会无限重试直到连接成功或者执行slaveof no one
取消复制。
3. 发送 ping 命令
连接建立成功后从节点会发送ping
请求进行首次通信,ping
请求主要目的是检测当前socket
是否可用和检测主节点当前是否可接受处理命令。如果发送ping
命令后,从节点没有收到主节点的pong
回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次定时任务会发起重连。
4. 权限校验
如果从节点中设置了masterauth
选项,则从节点需要向主节点进行身份验证。没有设置该选项,则不需要验证。从节点进行身份验证是通过向主节点发送auth
命令进行的,auth
命令的参数即为配置文件中的masterauth
的值。 如果主节点设置密码的状态,与从节点masterauth
的状态一致(一致是指都存在,且密码相同,或者都不存在),则身份验证通过,复制过程继续。如果不一致,则从节点断开 socket 连接,等待下次轮询重连。
5. 数据同步
当主从服务器正常通讯后,便可以开始进行数据同步。对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。Redis
在2.8版本
以后采用新复制命令psync
进行数据同步,原来的sync
命令依然支持,保证新旧版本的兼容性。那新版本的同步的话有区分为全量同步和部分同步。
6. 持续监听
命令持续复制。当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来主节点会持续地把写命令发送给从节点,保证主从数据一致性。
3.数据同步—— 全量复制和部分复制
全量复制:
在执行全量复制时,不光要复制之前主节点的数据,还要再复制数据时把正在写的数据复制到从节点。
执行rdb生成到rdb传输过程中新增的命令进行传输,在redis中有一个复制缓存区(repl_back_buffer),可以记录最新写的一个命令,则可以把新的RDB文件重写
全量复制的过程:
- 从节点内部会发出一个同步命令,由于是第一次进行复制,从节点没有复制偏移量和主节点的运行
ID
,所以发送psync-1
。 - 主节点根据
psync-1
解析出当前为全量复制,回复+FULLRESYNC
和自己的runId
和offset
。 - 从节点接收主节点的响应数据保存运行
ID
、偏移量offset
和主机master
的基本信息。 - 主节点收到全量复制的命令后,执行
bgsave
(异步执行),在后台生成RDB
文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令(类似于前面 AOF 重写时的两个缓冲区)。 - 主节点发送
RDB
文件到从节点。 - 对于从节点开始接收
RDB
快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB
文件后,主节点再把缓冲区内的数据发送给从节点,保证主从之间数据一致性。 - 从节点接收完主节点传送来的全部数据后会清空自身旧数据。
- 从节点清空数据后开始加载
RDB
文件,对于较大的RDB
文件,这一步操作依然比较耗时。 - 从节点成功加载完
RDB
后,如果当前节点开启了AOF
持久化功能,它会立刻做bgrewriteaof
操作,保证全量复制后AOF
持久化文件立刻可用。
全量复制的开销:
一般用于初次复制场景,Redis 早期支持的复制功能只有全量复制,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。全量复制的开销的时间主要来自于:
- bgsave时间
- RDB文件网络传输时间
- 从节点清空数据时间
- 从节点加载RDB的时间
- 可能的AOF重写时间
问题:master和slave之间的传输发生抖动,则传输的数据可能会发生丢失,则引入部分复制的概念
部分复制:
部分复制的过程:
-
当主从节点之间出现网络抖动,如果超过
repl-timeout
时间,主节点会认为从节点故障并中断复制连接(connection lost
)。 -
主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内部存在的复制积压缓冲区,依然可以保存最近一段时间的写命令数据,默认最大缓存
1MB
。 -
从节点重试连接主节点,网络恢复后从节点会再次连上主节点。
-
从节点会把自己当前
runId
和偏移量传输给主节点,并且执行pysnc
命令同步。 -
节点接到
psync
命令后首先核对参数runId
是否与自身一致,如果一致,说明之前复制的是当前主节点。然后根据参数offset
在自身复制积压缓冲区查找,如果偏移量之后的数据存在缓冲区中,则对从节点发送+CONTINUE
响应,表示可以进行部分复制。 -
主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。
4. 故障处理
master和slave节点出现故障怎么处理?
- 自动故障转移
主从结构故障分为:master故障、slave故障
slave宕机:去同步别的slave的数据
master宕机:将从节点升级为主节点,其他slave去同步新的master
5. 常见问题的优化
存在问题:
-
读写分离:读流量分摊到从节点,写的话使用主节点
复制数据延迟,发生阻塞如果偏移量太大可能发生读写不一样的情况
读到过期数据,
从节点故障,从节点的数据进行迁移
-
主从配置不一致
maxmemory不一致:丢失数据
数据结构导致内存不一样
-
规避全量复制
第一次全量复制不可避免,但是可以设置小主节点,地峰访问的时候进行处理
节点运行ID不匹配,主节点重启(运行ID变化),故障转移,哨兵和集群
复制积压缓冲区不足,网络中断,部分复制无法满足
-
规避复制风暴
单主节点复制风暴,一般是由于主节点重启,多从节点复制,可以更换复制拓扑
单机器复制风暴,机器宕机后,大量全量复制,主节点分散多机器
总结:
- 主从复制除了解决复杂环境下的高可用问题,还有一个功能就是用来做读写分离。
- 如果使用了主从复制架构,那就必须要考虑一个问题。那就是主从数据不一致的问题。还有就是主从服务器直接配置不一致的问题。
- 在对 Redis 做主从复制时,尽量要避免全量数据复制。前面也有提到过全量复制是一个非常消耗资源的操作。
发表评论
最新留言
关于作者
