共计 3069 个字符,预计需要花费 8 分钟才能阅读完成。
Redis 单机的吞吐是有上限的,在一些高并发业务场景下,我们需要对 Redis 进行扩展。
例如, 实现读写分离,缓解主服务器的压力。
Replication
Redis 提供了 replication 模式来实现主从复制。
replication 主要依赖于以下三个机制:
- 当 master 和 slave 连接正常时,matser 向 slave 发送命令来保持 slave 的更新, 包括数据的写入, 过期, 逐出
- 当 slave 与 master 的连接断开,slave 重新连接之后,slave 会尝试进行增量同步①, 只更新连接中断期间的数据
- 当 slave 无法执行增量同步时, 会执行全量同步②
(1) 增量同步
slave 由于某些原因与 master 断开连接, 重新连接之后, 只需要同步着期间缺少的数据
(2) 全量同步
master 执行 BGSAVE
指令, 完成后将快照文件传输给 slave
Replication 特点
Redis 的 replication 有以下特点需要了解:
- Redis 使用异步复制,主从之间异步的确认数据同步的数量
- 一个主可以有多个从
- 从还可以有从。从 4.0 版本开始,所有的从将会从 master 接受到完全一样的数据①
- 复制在主服务器上是异步的, 这意味着主可以在给多台从服务器器同步时还可以处理客户端的请求
- 复制在从服务器上也是异步的, 如果从服务器在复制期间有客户端请求, 从服务器将会从旧的数据集中返回数据。可以在配置项中进行配置
- 复制可以用于扩展读请求(实现读写分离)
- 可以使用复制来避免将全部数据写入磁盘的开销②
(1) 从服务器的数据只会从最原始的主服务器获得
例如,A –> B –> C, 存在这样一条主从链,B 设置为可以进行写入操作, 那么 C 不会获得 B 中写入的数据, 只能获得 A 中的数据集
(2) 不推荐这么做, 在主从重新连接时, 从服务器的数据如果没办法进行增量同步, 将会删除本地所有的数据, 再同步主服务器上的数据, 所以最好还是开启持久化
配置
slaveof <masterip> <masterport>
masterauth <master-password>
slave-serve-stale-data yes # 是否异步复制
slave-read-only yes
repl-diskless-sync no # 无盘复制
repl-diskless-sync-delay 5
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 1mb
repl-backlog-ttl 3600
slave-priority 100
min-slaves-to-write 3
min-slaves-max-lag 10
-
slaveof <masterip> <masterport>
设置从哪台 Redis 服务器同步数据 -
masterauth <master-password>
设置 master 的密码 -
slave-serve-stale-data
在同步数据时是否异步处理客户端请求① -
slave-read-only
是否开启只读,默认yes
开启 -
repl-diskless-sync
是否开启无盘复制②, 默认为no
-
repl-diskless-sync-delay
无盘复制延时, 默认为5
, 单位秒(s) -
repl-ping-slave-period
slave 发送 ping 的时间间隔, 默认为10
, 单位秒(s) -
repl-timeout
复制超时时长, 默认60
, 单位秒(s) -
repl-disable-tcp-nodelay
是否在同步完成之后禁用TCP_NODELAY
, 默认为no
-
repl-backlog-size
backlog 体积, 默认1mb
-
repl-backlog-ttl
backlog 过期时长, 默认3600
, 单位秒(s) -
slave-priority
从服务器权重③ -
min-slaves-to-write
④达到指定从服务器个数才开启写入功能, 设置为 0 表示禁用此项, 默认情况下为 0 -
min-slaves-max-lag
从服务器最大滞后时间, 如果超过该时长, 将关闭写入功能 , 默认为10
(1) 异步复制的同时处理客户端请求
Redis 可能会从旧的数据集中返回数据给客户端, 如果没有旧的数据集则返回空
(2) 无盘复制
子进程直接通过网络将 RDB 文件发给 slave, 不用使用磁盘作为中间存储
(3) slave-priority
在 Redis 的哨兵中, 检测 Redis 可用性, 如果 master 不可用, 哨兵将会依据此项来选取从服务器提升为主服务器
(4) 达到 N 个从服务才开启写入查询
由于 Redis 的异步复制, 无法保证 slave 接收到数据, 这将存在一段丢失数据的窗口期。
slave 每秒向 master 发送 ping, 确认处理的数据量,master 会记录每个 slave 最后一次 ping 的时间, 通过配置min-slaves-to-write N
和 min-slaves-max-lag M
来控制 master 的写入查询, 如果至少有 N 个 slave,滞后小于 M 秒,master 则接受写入;如果不满足条件, 则返回 error。
这是一种尽力保证数据安全的机制。其中对于给定的写入不确保一致性,但是至少数据丢失的时间窗口被限制为给定的秒数。通常,绑定数据丢失优于未绑定数据丢失。
工作机制
-
slave
启动,仅仅保存master
的信息,包括master
的 host 和 ip,但是复制流程没开始(master 的 host 和 ip 是通过 redis.conf 里面的 slaveof 配置的) -
slave
内部有个定时任务,每秒检查是否有新的master
要连接和复制,如果发现,就跟master
建立 socket 网络连接 -
slave
发送 ping 命令给master
- 口令认证,如果 master 设置了 requirepass,那么
slave
必须发送masterauth
的口令过去进行认证 -
master
第一次执行全量复制,将所有数据发给 slave node -
master
后续持续将写命令,异步复制给slave
从服务器怎么处理过期 key
从服务器并不会主动过期数据集中的数据, 主服务器在数据过期或被逐出的时候会向从服务器发送一条 del 的命令, 将从服务器中对应的数据删除
什么时候执行全量同步, 什么时候执行增量同步?
要理解全量, 增量同步的机制, 先要理解 Redis 复制中的三个概念:
- Replication ID(复制 ID), 标记数据集的给定历史记录。每次实例从头开始作为主服务器重新启动,或者从服务器提升为主服务器时,将为此实例生成新的复制 ID。连接到主服务器的从服务器将在握手后继承其复制 ID。
- offset(偏移量), 每个主服务器还会为生成的每个复制流字节递增一个偏移量,以便将其发送到从服务器, 从服务器也会保存这个值。
- backlog(缓冲区), 从服务器断开与主服务器的连接之后, 主服务器会暂时将数据存入 backlog, 默认 1mb, 有过期时间。
master
给slave
复制数据时,也会将数据在 backlog 中同步写一份,backlog 主要是用来做全量复制中断候的增量复制的
从服务器由于某些原因断开与主服务器的连接, 再次连接后, 从服务器上报当前的 Replication ID
和 offset
, 如果Replication ID
不一致则进行全量同步, 如果一致则判断 offset
, 这区间的数据如果还存在 backlog
中, 就进行 增量同步, 否则进行全量同步。(从节点执行 psync
,master 返回 FULLRESYNC runid offset
进行全量同步,CONTINUE
进行增量同步)
更多详细资料参考:
Redis 复制 - 官方文档
Redis 实战