redis学习(四) 复制
Replication
复制可以让其他服务器拥有一个不断地更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读请求。关系数据库通常会使用一个主服务器(master)向多个从服务器(slave)发送更新,并使用从服务器来处理所有读请求。Redis也采用了同样的方法来实现自己的复制特性,并将其用作扩展性能的一种手段。
尽管Redis的性能非常优秀,但它也会遇上没办法快速地处理请求的情况,特别是在对集合和有序集合进行操作的时候,涉及的元素可能会有上万个甚至上百万个,在这种情况下,执行操作所花费的时间可能需要以秒来进行计算,而不是毫秒或者微秒。但即使一个命令只需要花费10毫秒就能完成,单个Redis实例(instance)1秒也只能处理100个命令。
默认情况下,Redis都是主节点。每个从节点只能有一个主节点,而主节点可以同时具有多个从节点。
复制的数据流是单向的,只能由主节点复制到从节点。
配置复制的方式有以下三种
- 在配置文件中加入
slaveof{masterHost}{masterPort}
随Redis启动生效。 - 在redis-server启动命令后加入
--slaveof{masterHost}{masterPort}
生效。 - 直接使用命令:
slaveof{masterHost}{masterPort}
生效。
主从节点复制成功建立后,可以使用info replication
命令查看复制相关状态
slaveof命令不但可以建立复制,还可以在从节点执行slaveof no one
来断开与主节点复制关系。
安全性
对于数据比较重要的节点,主节点会通过设置requirepass参数进行密码验证,这时所有的客户端访问必须使用auth命令实行校验。
从节点与主节点的复制连接是通过一个特殊标识的客户端来完成,因此需要配置从节点的masterauth参数与主节点密码保持一致。
只读
默认情况下,从节点使用slave-read-only=yes配置为只读模式。
传输延迟
主从节点一般部署在不同机器上,复制时的网络延迟就成为需要考虑的问题,Redis为我们提供了repl-disable-tcp-nodelay参数用于控制是否关闭TCP_NODELAY,默认关闭。
如要求低延迟时,建议同机架或同机房部署并关闭repl-disable-tcp-nodelay;
如果考虑高容灾性,可以同城跨机房部署并开启repl-disable-tcp-nodelay。
拓扑
Redis的复制拓扑结构可以支持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:一主一从、一主多从、树状主从结构。
一主一从
在这种简单的结构下,如果写命令并发量高时,可以考虑关掉主机的AOF重写操作,从机开启aof重写,在主机要脱机后,从机要主动发起slaveof on one命令关掉复制,避免和主机一样清空数据。
一主多从
对于读占比较大的场景,可以把读命令发送到从节点来分担主节点压力。
在日常开发中如果需要执行一些比较耗时的读命令,如:keys、sort等,可以在其中一台从节点上执行,防止慢查询对主节点造成阻塞从而影响线上服务的稳定性。
对于写并发量较高的场景,多个从节点会导致主节点写命令的多次发送从而过度消耗网络带宽,同时也加
重了主节点的负载影响服务稳定性。
树形结构
通过中间层slave1,slave2分担master的复制工作,可以有效降低主节点负载和需要传送给从节点的数据量。
原理
从服务器连接主服务过程,执行全量复制的过程,sync,psync全量复制时相同
主服务器 | 从服务器 | |
---|---|---|
1 | 等待命令进入 | 连接或者重连接,发生SYNC命令 |
2 | 开始执行BGSAVE,并使用缓存区记录BGSAVE之后执行的所有写命令 | 依据配置来决定是继续使用现有二点数据处理客户端请求,还是发生请求的客户端返回错误 |
3 | BGSAVE执行完毕,向从服务器发生快照文件,并在发生期间继续使用缓存区记录被执行的写命令 | 丢弃所以的旧数据,开始载入主服务器发送来的快照文件 |
4 | 快照文件发送完毕,开始向从服务器发送存储在缓存区的写命令 | 完成对快照文件的解释操作,像往常一样开始接受命令请求 |
5 | 缓存区存储的写命令发送完毕;从现在开始,每执行一个写命令,就向从服务器发送相同的写命令 | 执行主服务器发来的所有存储在缓冲区里面的写命令;并从现在开始,接收并执行主服务器传来的每个写命令 |
Redis在复制进行期间也会尽可能地处理接收到的命令请求,但是,如果主从服务器之间的网络带宽不足,或者主服务器没有足够的内存来创建子进程和创建记录写命令的缓冲区,那么Redis处理命令请求的效率就会受到影响。因此,尽管这并不是必须的,但在实际中最好还是让主服务器只使用50%警告:Redis不支持主主复制(master-master replication)~65%的内存,留下30%~45%的内存用于执行BGSAVE命令和创建记录写命令的缓冲区。
redis通信是依据套接字socket进行的,在从服务器与主服务器的第一次交流时,使用ping命令,判断套接字和主服务器是否能进行数据同步,之后进行密码校验,如果有的话,密码成功后,进行数据同步。
数据同步
Redis在2.8及以上版本使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。
部分复制:用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点。因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销。
psync命令运行需要以下组件支持:
- 主从节点各自复制偏移量。主服务器统计信息在info relication中的
master_repl_offset
指标中,从服务器统计信息在info relication中的slave_repl_offset
指标中 - 主节点复制积压缓冲区。
- 主节点运行id。运行ID的主要作用是用来唯一识别Redis节点。可以运行info server命令查看当前节点的运行ID。
部分复制就是采用psync命令执行
offset即偏移量,当前从节点已复制的数据偏移量
全量复制流程
如何在不改变运行ID的情况下重启呢?
当需要调优一些内存相关配置,例如:hash-max-ziplist-value等,这些配置需要Redis重新加载才能优化已存在的数据,这时可以使用debug reload命令重新加载RDB并保持运行ID不变,从而有效避免不必要的全量复制。
Redis3.0之后在输出的日志开头会有M、S、C等标识,对应的含义是:
M=当前为主节点日志,S=当前为从节点日志,C=子进程日志
心跳
维护着长连接并彼此发送心跳命令。
- 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过client list命令查看复制相关客户端信息,主节点的连接状态为flags=M,从节点连接状态为flags=S。
- 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态。可通过参数repl-ping-slave-period控制发送频率。
- 从节点在主线程中每隔1秒发送
replconf ack{offset}
命令,给主节点上报自身当前的复制偏移量。
实际应用
读写分离
数据延迟,监控从服务器和主服务器的偏移量;
读到过期数据,对于缓存数据,redis需要在内部维护过期数据的删除,策略有两种惰性删除和定时删除。注意从节点自身永远不会主动删除超时数据。
主从配置不一致
规避复制风暴
复制风暴是指大量从节点对同一主节点或者对同一台机器的多个主节点短时间内发起全量复制的过程。