前言
Redis 单实例存在单点故障问题,而且为了缓解单实例的压力,生产环境往往都使用哨兵(Sentinel)或集群(Cluster)。Redis 哨兵、集群的基础是复制,而 Redis 提供的复制能够使 master 的数据复制到多个 slave 中,从而获取容错及水平扩展的能力。
复制
启用
-
配置文件
:通过在配置文件中配置 replicaof host port 指定 master,再启动实例。1
2
3
4
5
6# 通过 utils/install_server.sh 脚本创建一个新的 Redis 实例作为 salve $ vi 6380.conf # 指定 master replicaof 127.0.0.1 6379 # 如果 6379 实例设置密码,则需要配置认证 masterauth ***
-
命令
:使用 slaveof <host> <port> 命令,动态地指定 master。1
2
3
4# 指定复制 master redis> slaveof 127.0.0.1 6379 # 取消复制 redis> slaveof no one
信息
可以分别从 master、slave 实例中通过 info replication 命令查看复制信息。
1 |
|
流程
同步机制
-
部分重新同步
slave 通过向 master 发送 (master_replid : master_repl_offset) 进行部分重新同步。当 master 的 master_replid 与之相符,并且 master_repl_offset 在 backlog 缓冲区范围内,master 会将 backlog 中指定偏移量的写命令发送给 slave 来完成增量同步。
-
完全重新同步
master 开启后台进程 BGSAVE(非阻塞)转储 RDB 文件,期间接收到的写命令会放入一个叫作从客户端缓冲区(Slave Client Buffer)的缓冲区中,RDB 文件会发送给 slave,slave 清空内存所有旧数据,再载入 RDB 文件。
详细流程
部分重新同步和完全重新同步流程如图:
slave 连接 master 步骤如表:
步骤 | master | slave |
---|---|---|
1 | 初连(重连)master,发送 SYNC 命令 | |
2 | 接收 SYNC 命令,执行 BGSAVE,使用从客户端缓冲区(Slave Client Buffer)记录之后所执行的写命令 | 根据配置来决定是继续使用先有的数据(如果有的话)来处理客户端的请求,还是向客户端返回错误 |
3 | BGSAVE 执行完,向从服务器发送 RDB 文件,发送期间继续使用缓冲区记录被写命令 | 丢弃所有旧数据(如果有的话),开始载入主服务器发来的 RDB 文件 |
4 | RDB 文件发送完毕,开始向从服务器发送 backlog 中的写命令 | 完成对 RDB 文件的载入,像往常异常接受命令请求 |
5 | 缓冲区中的写命令发送完毕之后,每执行的一次写命令,都向从服务器发送相同的写命令 | 执行主服务器发来的缓冲区中的写命令。之后,接收并执行主服务器创来的每个写命令 |
参数
-
slave-read-only
当一个 Redis 实例的 role 为 slave 时,是否处于只读状态。默认 yes。
-
repl-backlog-size
Replication Backlog 的大小。默认 1MB,比 RDB 快照大没多少意义(部分重新同步没多少优势)。
-
repl-backlog-ttl
当所有 slave 与 master 断开连接,master 需要等待多久释放 backlog 内存。默认 3600s。
-
repl-ping-slave-period
master PING slave 的间隔时间,默认 10s(slave 则是每秒向 master 发送 REPLCONF ACK {offset} 来报告复制偏移量)。
-
repl-timeout
两次 PING 或 REPLCONF ACK {offset} 间隔时间比超时时间长,或者在该时间内,master、slave之间没有数据流量,将会断开主从复制连接。默认 60s。
键过期
当 master 中的键过期时,master 会向所有 slave 发送 DEL 命令。在同步期间,master 也会将 DEL 命令放到从客户端缓冲区中。