Redis的主从复制
1.主从复制
Redis配置成主从模式,主库(Master)只负责写数据,从库(Slave)只负责读数据。
注意:
一个主库可以拥有多个从库,但一个从库只能隶属于一个主库。
将选为Slave的机器上配置:
# REPLICATION
slave of <master ip> <port>
masterauth <password>
开启主从关系后,数据会自动进行复制。
2.全量复制和部分复制
Redis的复制方式包括全量复制和部分复制。
2.1 全量复制
流程如下:
- Slave发出一个同步命令,要求Master同步数据;
- Master向Salve发送runid和offset;当Slave上没有offset记录时,执行全量复制;
- Slave执行save masterinfo,保存Master的基本信息;
- Master执行bgsave生成快照;
- Master执行send RDB将快照发送到Slave的缓冲区;
- Slave更新旧的RDB文件,并加载新的RDB;
由上述流程可以看到,全量复制的开销主要在:
- 生成RDB文件,即bgsave;
- RDB服务器间传输;
- 如果有AOF设置,达到重写阈值,会进行AOF重写;
2.2 部分复制
部分复制在Redis 2.8之后开始支持,可以减少全量复制的开销。
部分复制的原理:
- 每台机器启动后都会有一个与当前进程相关的
runid
; - 每个机器在写入数据后会有一个偏移量
master_repl_offset
; - 通过偏移量来判断Slave与Master直接的数据差多少;
部分复制常用在主从连接断开、Master抖动时。
流程如下:
- 主从连接断开;
- Slave尝试连接主机;Master写入复制缓冲区
repl_back_buffer
; - 恢复连接后,Slave将自己当前runid和偏移量传输给Master,并请求同步数据;
- Master检查偏移量是否在缓冲区范围内,如果是,则进行部分复制;如果不是,则进行全量复制;
优点:
部分复制直接使用缓冲区的数据进行RDB同步,相比全量复制,减少了RDB的生成和传输开销;同时,也减少了AOF重写阈值达到的几率。
3.主从复制中的问题
3.1 读写分离的问题
-
复制数据延迟:Slave 延迟导致读写不一致。
- 监控偏移量 offset,如果超出范围就将读节点切换到 Master 上,并重新全量复制Slave节点。
-
读到过期数据:Redis 采用懒惰性策略和采样式策略。
- 懒惰性策略指 Redis 只有当操作 key时才去看数据是否过期;采样式策略指定期会去采样,如果是过期的,就自动删除。当过期数量非常多的时候,采样速度比不上逻辑数据变化的速度,Slave 没有写权限,只有 Master 可以删除,就会出现过期数据。
- Redis 3.2 以上版本修复此问题。
-
Slave 节点故障
- Slave 节点通过持久化数据与主节点进行部分复制同步;Redis2.8 实现 Slave 恢复后部分复制同步;
-
Master 节点故障
- 需要手动切换主从关系;
- 使用 Redis哨兵模式自动完成主从切换;
3.2 复制风暴
Master 重启,多个 Slave 会需要复制。这个时候需要更换复制拓扑,通过在 Slave 下再分从机,减少主机 Master 的压力。
4. 配置文件说明
################################# REPLICATION #################################
# 复制选项,slave复制对应的master。
slaveof <masterip> <masterport>
# 如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。
# masterauth就是用来配置master的密码,这样可以在连上master后进行认证。
# masterauth <master-password>
# 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
# 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。
# 2) 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”。
slave-serve-stale-data yes
# 作为从服务器,默认情况下是只读的(yes)
slave-read-only yes
# 是否使用socket方式复制数据。
# 目前redis复制提供两种方式,disk和socket。
# 如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。
# 有2种方式:
# 1.disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。
# 2.socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。
# disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。
# socket的方式就的一个个slave顺序复制。
# 在磁盘速度缓慢,网速快的情况下推荐用socket方式。
repl-diskless-sync no
# diskless复制的延迟时间,防止设置为0。
# 一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。
# 所以最好等待一段时间,等更多的slave连上来。
repl-diskless-sync-delay 5
# slave根据指定的时间间隔向服务器发送ping请求。
# 时间间隔可以通过 repl_ping_slave_period 来设置,默认10秒。
# repl-ping-slave-period 10
# 复制连接超时时间。
# master和slave都有超时时间的设置。
# master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。
# slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。
# 需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时。
# repl-timeout 60
# 是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。
# 默认是no,即使用tcp nodelay。
# 如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。
# 但是这也可能带来数据的延迟。
# 默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。
repl-disable-tcp-nodelay no
# 复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。
# 这样在slave离线的时候,不需要完全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。
# 缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。
# 没有slave的一段时间,内存会被释放出来,默认1m。
# repl-backlog-size 5mb
# master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。
# 单位为秒。
# repl-backlog-ttl 3600
# 当master不可用,Sentinel会根据slave的优先级选举一个master。
# 最低的优先级的slave,当选master。
# 而配置成0,永远不会被选举。
# 注意:要实现Sentinel自动选举,至少需要2台slave。
slave-priority 100
# redis提供了可以让master停止写入的方式,如果配置了min-slaves-to-write,健康的slave的个数小于N,mater就禁止写入。
# master最少得有多少个健康的slave存活才能执行写命令。
# 这个配置虽然不能保证N个slave都一定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。
# 设置为0是关闭该功能,默认也是0。
# min-slaves-to-write 3
# 延迟小于min-slaves-max-lag秒的slave才认为是健康的slave。
# min-slaves-max-lag 10
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。