Redis-主从复制


前言

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
    

信息

​ 可以分别从 masterslave 实例中通过 info replication 命令查看复制信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# ===============================================================
# 主实例
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=42,lag=1
master_replid:183a1f6ad7808740d2fb1ab463404512de42e698
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:42

# ===============================================================
# 从实例
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:56
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:183a1f6ad7808740d2fb1ab463404512de42e698
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56

流程

同步机制

  • 部分重新同步

    slave 通过向 master 发送 (master_replid : master_repl_offset) 进行部分重新同步。当 mastermaster_replid 与之相符,并且 master_repl_offsetbacklog 缓冲区范围内,master 会将 backlog 中指定偏移量的写命令发送给 slave 来完成增量同步。

  • 完全重新同步

    master 开启后台进程 BGSAVE(非阻塞)转储 RDB 文件,期间接收到的写命令会放入一个叫作从客户端缓冲区(Slave Client Buffer)的缓冲区中,RDB 文件会发送给 slaveslave 清空内存所有旧数据,再载入 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

    当所有 slavemaster 断开连接,master 需要等待多久释放 backlog 内存。默认 3600s

  • repl-ping-slave-period

    master PING slave 的间隔时间,默认 10sslave 则是每秒向 master 发送 REPLCONF ACK {offset} 来报告复制偏移量)。

  • repl-timeout

    两次 PINGREPLCONF ACK {offset} 间隔时间比超时时间长,或者在该时间内,masterslave之间没有数据流量,将会断开主从复制连接。默认 60s

键过期

​ 当 master 中的键过期时,master 会向所有 slave 发送 DEL 命令。在同步期间,master 也会将 DEL 命令放到从客户端缓冲区中。

参考

​ [1] Josiah L. Carlson 著. 黄健宏 译. Redis实战. 4.2 复制

​ [2] 黄鹏程,王左非 著. 梅隆魁 译. Redis 4.x Cookbook中文版. 第五章 复制