2. 主从复制
redis server可以部署在多台机器上,我们选择其中一台作为主节点,其他未从节点,通过redis.conf 配置,可以实现从节点 同步 主节点数据,专业名词:“主从复制”。
2.1 主从复制简介 (概念)
高可用
⚫ 高并发 : 描述流量大
⚫ 高性能 : 描述系统性能好
⚫ 高可用
一般企业要求软件服务至少能够达到四个9(99.99%),就可以称之为高可用, 计算如下 :
#年度可用性:90%折合计算,365天x90% =328.5天。全年故障36.5天,取最容易看的单位超过1个月
#年度可用性:99%折合计算,365天x99% =361.35天。全年故障3.65天,取最容易看的单位87.6小时
#年度可用性:99.9%折合计算,365天x99.9% =364.635天。全年故障0.365天,取最容易看的单位8.76小时
#年度可用性:99.99%折合计算,365天x99.99% =364.9635天。全年故障0.0365天,取最容易看的单位52.56分钟
#年度可用性:99.999%折合计算,365天x99.999% =364.99635天。全年故障0.000365天,取最容易看的单位5.256分钟
描述 | 通俗叫法 | 可用性级别 | 年度停机时间 |
---|---|---|---|
基本可用性 | 2个9 | 99% | 87.6小时 |
较高可用性 | 3个9 | 99.9% | 8.8小时 |
具有故障自动恢复能力的可用性 | 4个9 | 99.99% | 53分钟 |
极高可用性 | 5个9 | 99.999% | 5分钟 |
思考:
你的“单机Redis”是否高可用?
-
问题1.机器故障
◼ 现象:硬盘故障、系统崩溃,数据丢失,系统处于不可用状态。
◼ 结论:基本上会放弃使用redis.
-
问题2.容量瓶颈
◼ 现象:内存不足,从16G升级到64G,从64G升级到128G,无限升级内存,停机加内存这段时间,又是不可以用状态。
◼ 结论:放弃使用redis
解决思路
Redis 为了解决这个单一节点的问题,也会把数据复制多个副本部署到其他节点上进行复制,实现 Redis的高可用,实现对数据的冗余备份,从而保证数据和服务的高可用。
主从复制的概念
-
概念:主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。
-
特征:默认情况下,redis是不分主从的,一旦对多个redis配置了主从,一个master可以拥有多个slave也可以没有slave,一个slave只对应一个master
⚫ 职责划分:
方式一:
◆ master:
◼ 只负责写数据
◼ 执行写操作时,将出现变化的数据自动同步到slave
◆ slave:
◼ 只负责读数据
◼ 同时在线时刻备份master同步过来的数据
方式二:
◆ master: 负责读写
◆ slave: 只做数据的备份,当master出现故障时,slave在提供读写服务。
主从复制的作用
⚫ 读写分离:master写、slave读,提高服务器的读写负载能力
⚫ 负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数 量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
⚫ 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
⚫ 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
⚫ 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
2.2 主从复制工作流程
⚫ 建立连接阶段
⚫ 数据同步阶段
⚫ 命令传播阶段
建立连接阶段(动手)
-
步骤如下:
① slave基于连接配置,发送指令给master,确认master是否在线。
②master接收到指令,响应给slave,证明自己在线。
③slave保存master的IP与端口
④slave使用master的IP与端口创建连接socket
⑤slave周期性发送命令:ping,检测master时刻在线。
⑥master每次接收到ping, 都要做出响应pong, 来证明自己活着。
⑦slave发送指令:auth password,请求master验证密码。
⑧master验证授权,响应给salve结果
⑨密码正确,slave发送指令:replconf listening-port <port-number> ,告知master同步数据时用哪个端口。
⑩master保存slave的端口号,需要同步数据给salve时,使用此端口号。
-
slave连接如何建立:
################## 建立连接操作 #方式一:客户端发送命令 slaveof masterip masterport #方式二:启动服务器参数 redis-server --slaveof masterip masterport #方式三(推荐):slave redis.conf配置 #slave启动时,自动跟master建立同步连接 slaveof masterip masterport ################## 断开连接操作 # slave客户端执行命令 slaveof no one ################## 授权访问 # master redis.conf 配置文件设置密码 requirepass password # slave redis.conf 配置文件设置master密码 masterauth password
-
slave系统信息
◆ master_link_down_since_seconds
◆ masterhost & masterport
-
master系统信息
◆ slave_listening_port (多个)
数据同步阶段(概念)
-
步骤如下:
-
同步阶段master说明
1)如果master数据量巨大,数据同步阶段应避开流量高峰期,避免造成master阻塞,影响业务正常执行
2)复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已 经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态。
3)master单机内存占用主机内存的比例不应过大,建议使用50%-70%的内存,留下50%-30%的内存用于执 行bgsave命令和创建复制缓冲区
# master/redis.conf
# 设置同步缓冲区大小, 根据3)中的百分比建议设置即可
repl-backlog-size ?mb
-
同步阶段slave说明
1)为避免slave进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务
# slave/redis.conf
# yes,主从复制中,从服务器可以响应客户端请求
# no,主从复制中,从服务器将阻塞所有请求,有客户端请求时返回“SYNC with master in progress”;
slave-serve-stale-data yes|no
2)数据同步阶段,master已客户端的身份,通过slave告知的同步 端口,主动将数据发送给slave。
3)多个slave同时对master请求数据同步,master发送的RDB文件增多,会对带宽造成巨大冲击,如果 master带宽不足,因此数据同步需要根据业务需求,适量错峰
4)slave过多时,建议调整拓扑结构,由一主多从结构变为树状结构,中间的节点既是master,也是 slave。注意:使用树状结构时,由于层级深度,导致深度越高的slave与最顶层master间数据同步延迟 较大,数据一致性变差,应谨慎选择。
命令传播阶段(概念)
该阶段master每次接收到客户端传来对数据有变更的指令,都会通过“命令传播程序”,分发给所有的从节点来完成数据同步。
offset 偏移量
◆ 概念:master和slave都会维护一个偏移量, 用于标识主从复制的现状;(可使用[info replication]命令查看偏移量)
◆ master端:每次接收到java客户端发来命令(字节数据),记录当前数据offset。
◆ slave端:每次master同步数据时,slave都能收到当前数据offset,并且slave存在心跳机制,每1秒都发送指令给master上报自己当前的offset值,“REPLCONF ACK {offset} ”。
◆ 作用:master会根据salve上报的offset和自己当前记录的offset做比对:
1)先检验,slave的offset在不在master offset范围内
◆ 假如:slave offset=20,master offset范围 [1-10],则slave的offset非当前master提供的,进行全量复制,slave会将之前数据全部清理掉。
一致:则没有数据变更不同步数据
2)通过检验,一致,不同步
3)通过检验,不一致,部分复制
◆ 假如:slave offset=5,master offset范围 [1-10],则slave的offset在当前master offset范围内,进行部分复制,master会将复制缓冲区中的数据发送给slave进行数据的同步。
服务器运行ID(runid)
◆ 每个redis服务每次启动时,都会随机生成一个40的id来代表自己,可通过[info server]命令查询run_id。
◆ 在初次主从同步时 (全量复制) ,master会将自己的runid和offset以及RDB数据文件一起发送给slave,salve记录自己的master [runid]。
◆ 当slave断线重连时,从节点会将这个runid发送给主节点;主节点根据runid判断能否进行部分复制:
1)如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制 (到底能不能部分复制还要看offset和复制积压缓冲区的情况);
2)如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。
复制缓冲区
-
概念:复制缓冲区,又名复制积压缓冲区,是一个固定长度的FIFO的队列,大小由配置参数[repl-backlog]指定,这个缓冲区只存在master,用于备份最近master同步slave的数据。
◆ 默认存储空间大小是1M
◆ 当入队元素的数量大于队列长度时,最先入队的元素会被弹出,而新元素会被放入队列
◆ 命令传播阶段,master除了将命令同步给slave外还会在这个缓冲区中备份,而且还会存储每个命令(实际是每个字节)对用的offset值。
-
作用 :
-
通过offset区分不同的slave当前数据传播的差异
-
master记录已发送的信息对应的offset
-
slave记录已接收的信息对应的offset
-
完整版本 +心跳机制
流程图一
流程图二
心跳机制
-
进入命令传播阶段候,master与slave间需要进行信息交换,使用心跳机制进行维护,实现双方连接保持在线
-
master心跳:
◆ 内部指令:PING
◆ 周期:由repl-ping-slave-period决定,默认10秒
◆ 作用:判断slave是否在线
◆ 查询:INFO replication 获取slave最后一次连接时间间隔,lag项维持在0或1视为正常
-
slave心跳任务
◆ 内部指令:REPLCONF ACK {offset}
◆ 周期:1秒
◆ 作用1:汇报slave自己的复制偏移量,获取最新的数据变更指令
◆ 作用2:判断master是否在线
-
注意事项:
-
当slave多数掉线,或延迟过高时,master为保障数据稳定性,将拒绝所有信息同步操作
#slave数量少于2个 或者 所有slave的延迟都大于等于8秒时,强制关闭master写功能,停止数据同步 min-slaves-to-write 2 min-slaves-max-lag 8
-
slave数量由slave发送REPLCONF ACK {offset} 命令做确认
-
slave延迟由slave发送REPLCONF ACK {offset} 命令做确认
-