文章目录
环境配置
- 如果要在一台主机上实现主从复制, 需要更改conf文件以下几个内容
- 启动端口
- pid名字
- log名字
- dump.rdb命令
- 随后我们启动一个redis使用 info replication 查看其主从信息
127.0.0.1:6379> info replication#查看当前库的信息#Replication
role :master#角色master
connected_slaves:0 #没有从机
master_replid:b63c90e6c501143759cb0e7f450bd1eb0c70882a
master_replid2:0000000000000000000000000000000Q00000000
master_rep1_offset:o
second_rep1_offset:-1
rep1_backlog_active :o
rep1_back1og_size : 1048576
rep1_back1og_first_byte_offset:o
rep1_backlog_histlen :0
一定要清除几点
- 如果没有在配置文件中配置这个redis节点是从服务器, 那么每次启动他就是一台主服务器(因为没人相当小弟, 都想当大哥), 就是你命令配置了, 但是重启之后他又是主服务器
- 主服务器一旦断开, 从服务器还是连接着主服务器, 不会进行自动的升级到主服务器
- 主服务器可以进行写操作, 从服务器只能进行读操作, 所以在上述主服务器断开后只能进行读数据, 不能进行写数据了, 但是主服务器一旦回来, 这个主从配置还是正常可以使用,写操作可以正常进行
- 从节点一旦断开, 对主服务器也是没有影响, 如果此时主服务器更新数据后, 从服务器再去连接主服务器, 数据使用部分复制还是可以同步的
复制的建立(slaveof )
-
在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复和负载均衡等需求。Redis也是如此,它为我们提供了复制功能,实现了相同数据的多个Redis副本
-
参与复制的Redis实例划分为主节点(master)和从节点(slave)。默认情况下,Redis都是主节点
-
复制的数据流是单向的,只能由主节点复制到从节点
-
配置复制的方式有以下三种:
①在配置文件中加入slaveof {masterHost} {masterPort}随Redis启动生效
②在redis-server启动命令后加入–slaveof {masterHost} {masterPort}生效
③客户端直接使用命令:slaveof {masterHost} {masterPort}生效 -
slaveof本身是异步命令:执行slaveof命令时,节点只保存主节点信息后返回,后续复制流程在节点内部异步执行
演示
- 我们想让127.0.0.1:6380(从节点)去复制127.0.0.1:6379(主节点),那么可以在127.0.0.1:6380端输入下面的命令
slaveof 127.0.0.1 6379
- 现在主节点(左侧)新建一个字符串键值对,然后从服务(右侧)也可以查看到该键值对
- 主从节点复制成功建立后,可以使用info replication命令查看复制相关状态
复制的断开 (slaveof no one)
-
slaveof命令不但可以建立复制,还可以在从节点执行slaveof no one来断开与主节点复制关系
-
断开复制主要流程:
①断开与主节点复制关系
②从节点晋升为主节点 -
从节点断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化
切换复制点
-
通过slaveof命令还可以实现切主操作,所谓切主是指把当前从节点对主节点的复制切换到另一个主节点
-
在一个已经建立复制的从节点上执行slaveof {newMasterIp} {newMasterPort}命令即可
-
切主操作流程如下:
断开与旧主节点复制关系
与新主节点建立复制关系
删除从节点当前所有数据
对新主节点进行复制操作 -
切主后从节点会清空之前所有的数据,线上人工操作时小心slaveof在错误的节点上执行或者指向错误的主节点
复制拓扑
- Redis的复制拓扑结构可以支持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:一主一从、一主多从、树状主从结构
- 一主一从结构是最简单的复制拓扑结构,用于主节点出现宕机时从节点提供故障转移和数据恢复支持
- 一主多从结构(又称为星形拓扑结构)使得应用端可以利用多个从节点实现读写分离
- 树状主从结构(又称为树状拓扑结构)使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主节点继续向下层复制。通过引入复制中间层,可以有效降低主节点负载和需要传送给从节点的数据量
- 当主节点需要挂载多个从节点时为了避免对主节点的性能干扰,可以采用树状主从结构降低主节点压力
复制原理
- 当一个redis节点给另一个redis节点发送 slaveof 命令后从节点只保存主节点的地址信息便直接返回,这时建立复制流程还没有开始
- 从节点内部通过每秒运行的定时任务维护复制相关逻辑, 会发现存在新的主节点后,会尝试与该节点建立网络连接
- 连接建立成功后从节点发送ping请求进行首次通信, 从节点发送的ping命令成功返回,继续后续复制流程
- 如果主节点设置了requirepass参数,则需要密码验证,从节点必须配置masterauth参数保证与主节点相同的密码才能通过验证
- 随后从节点就会发送一个 psync同步命令
- master接收到命令后, 就会启动一个后台线程, 收集自己此时的所有数据命令, master将传送整个数据集文件到slave 完成一次完全同步, 也叫全量复制
- 在后续如果master收到修改数据的命令, 就会给从节点也发送一份, 将从节点的数据也进行更改
- 总之整个过程全是从节点主动进行的, 包括一开始的保存主节点信息, 尝试建立socket连接, 尝试登陆验证, 发送同步密码, 数据一致化
全量复制
- 全量复制是Redis最早支持的复制方式,也是主从第一次建立复制时必须经历的阶段
- 触发全量复制的命令是sync和psync,它们的对应版本如下图所示
部分复制
- 部分复制就是当主从节点网络中断后,从节点再次连上主节点时会发送psync {offset} {runId}命令请求部分复制, 也就是发送过去一个偏移量吗告诉主节点我上次复制在哪了
增量复制
-增量辅助就是在建立连接进行了完全复制之后, 主节点进行修改命令时候, 就会通过socket将这个命令传输给从节点, 进行数据的一致化
心跳检测
- 主从节点在建立复制后,它们之间维护着长连接并彼此发送心跳命令。如下图所示:
- 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信
- 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态。
- 节点在主线程中每隔1秒发送replconf ack {offset}命令,给主节点上报自身当前的复制偏移量
故障处理
读写分离
- 对于读占比较高的场景,可以通过把一部分读流量分摊到从节点来减轻主节点压力,同时需要注意永远只对主节点执行写操作
- 当使用从节点响应读请求时,业务端可能会遇到如下问题:
复制数据延迟
读到过期数据
从节点故障
数据延迟
- Redis复制数据的延迟由于异步复制特性是无法避免的,延迟取决于网络带宽和命令阻塞情况,比如刚在主节点写入数据后立刻在从节点上读取可能获取不到。需要业务场景允许短时间内的数据延迟
- 对于无法容忍大量延迟场景,可以编写外部监控程序监听主从节点的复制偏移量,当延迟较大时触发报警或者通知客户端避免读取延迟过高的从节点
- 当延迟字节量过高时,比如超过10MB。监控程序触发报警并通知客户端从节点延迟过高。可以采用Zookeeper的监听回调机制实现客户端通知
- 客户端接到具体的从节点高延迟通知后,修改读命令路由到其他从节点或主节点上。当延迟恢复后,再次通知客户端,恢复从节点的读命令请求
- 这种方案的成本比较高,需要单独修改适配Redis的客户端类库。如果涉及多种语言成本将会扩大。客户端逻辑需要识别出读写请求并自动路由, 还需要维护故障和恢复的通知。采用此方案视具体的业务而定,如果允许不 一致性或对延迟不敏感的业务可以忽略,也可以采用Redis集群方案做水平扩展降低数据的复制量
读到过期数据
- 当主节点存储大量设置超时的数据时,如缓存数据,Redis内部需要维护过期数据删除策略。删除策略主要有两种:惰性删除和定时删除
- 惰性删除:主节点每次处理读取命令时,都会检查键是否超时,如果超时则执行del命令删除键对象,之后del命令也会异步发送给从节点。需要注意的是为了保证复制的一致性,从节点自身永远不会主动删除超时数据
- 定时删除:Redis主节点在内部定时任务会循环采样一定数量的键,当发现采样的键过期时执行del命令,之后再同步给从节点
- 如果此时数据大量超时,主节点采样速度跟不上过期速度且主节点没有读取过期键的操作,那么从节点将无法收到del命令。这时在从节点上可以读取到已经超时的数据。Redis在3.2版本解决了这个问题,从节点读在复制主节点数据的时候设置的时间也会复制, 所以在从节点取数据之前会检查键的过期时间来决定是否返回数据
从节点或者主节点故障
- 在主从模式下, 从节点或者主节点故障只能开发或者运维人员手动配置, 不然不会自动配置完善, 但是在哨兵模式下就可以实现自动恢复
复制优化
规避全量复制
- 全量复制是一个非常消耗资源的操作,前面做了具体说明。因此如何规避全量复制是需要重点关注的运维点
-
第一次建立复制
由于是第一次建立复制,从节点不包含任何主节点数据,因此必须进行全量复制才能完成数据同步。对于这种情况全量复制无法避免
当对数据量较大且流量较高的主节点添加从节点时,建议在低峰时进行操作,或者尽量规避使用大数据量的Redis节点 -
节点运行ID不匹配
当主从复制关系建立后,从节点会保存主节点的运行ID,如果此时主节点因故障重启,那么它的运行ID会改变,从节点发现主节点运行ID不匹配时,会认为自己复制的是一个新的主节点从而进行全量 复制
对于这种情况应该从架构上规避,比如提供故障转移功能。当主节点发生故障后,手动提升从节点为主节点或者采用支持自动故障转移的哨兵或集群方案。 -
复制积压缓冲区不足
当主从节点网络中断后,从节点再次连上主节点时会发送psync {offset} {runId}命令请求部分复制,如果请求的偏移量不在主节点的积压缓冲区内,则无法提供给从节点数据,因此部分复制会退化为全量复制
针对这种情况需要根据网络中断时长,写命令数据量分析出合理的积压缓冲区大小
规避复制风暴
- **复制风暴是指大量从节点对同一主节点或者对同一台机器的多个主节点短时间内发起全量复制的过程。**复制风暴对发起复制的主节点或者机器造成大量开销,导致CPU、内存、带宽消耗。
- 解决方案有:可以减少主节点挂载从节点的数量, 或者采用树状复制结构,加入中间层从节点用来保护主节点
- 使用集群并且应该把主节点尽量分散在多台机器上,避免在单台机器上部署过多的主节点