redis高可用(一)
redis 集群
主从复制
为了避免单点故障,redis提供了 主从复制功能
保证服务器 数据一致性,且主从服务器之间采用 「读写分离」 方式
第一次同步
使用 replicaof 命令形成主服务器和从服务器关系
比如
1 | 服务器 B 执行这条命令,成为 A 的从服务器 |
主从服务器第一次同步过程分为三个阶段
- 建立连接、协商同步
- 主服务器同步数据给从服务器
- 主服务器发送新写操作命令给从服务器
建立连接、协商同步
执行了 replicaof 后,从服务器会给主服务器发送 psync 命令,表示数据同步
psync 命令包含两个参数, 主服务器的 runID 和 复制进度 offset
- runID,每个redis在启动时会产生一个随机的ID用来唯一标识自己
- offset,表示复制进度,第一次同步时,值为 -1
主服务器收到 psync 命令后,会用 FULLRESYNC 作为响应返回给对方
FULLRESYNC 也携带两个参数: 主进程的 runID 和 主服务器目前的复制进度 offset
FULLRESYNC 响应命令 采用 全量复制 的方式
主服务器同步数据给从服务器
主服务器会执行 bgsave 来生成 RDB 文件,然后把文件发送给从服务器
从服务器收到 RDB 文件后,会清空数据库,然后载入 RDB 文件
这里在主服务器上执行 bgsave 的期间,如果执行写操作,记录不会记录到刚刚生成的 RDB 文件中,这时主从服务器间数据不一致
为了保证主从服务器数据一致性, 主服务器在下面这三个时间间隙收到的写操作命令,写入到 replication buffer 缓冲区
- 主服务器生成 RDB 文件期间
- 主服务器发送 RDB 文件给从服务器期间
- 「从服务器」加载 RDB 文件期间
主服务器发送新写操作命令给从服务器
完成 RDB 的载入后,从服务器会回复一个确认消息给主服务器
接着主服务器将 replication buffer 缓冲区中读取命令,发送给从服务器,来保证数据一致性
命令传播
主从服务器在完成第一次同步后,双方维护一个 TCP 长连接
后续主服务器通过连接将写操作命令发送给从服务器,维持数据一致性
增量复制
当主从服务器连接断开,客户端可能从 「从服务器」读到旧数据
如果此时断开的网络,又恢复正常,如何保证主从服务器数据一致性
redis 2.8 之前,会进行全量复制,即重新执行一次主从服务器第一次同步过程
redis 2.8 开始,主从服务器采用 增量复制 的方式继续同步,三个步骤
- 恢复连接后,从服务器发送 psync 给主服务器,此时 offset 不为 -1
- 主服务器收到命令后,用 CONTINUE 响应,采用增量复制的方式同步数据
- 主服务器从主从服务器断开期间,所执行的写命令发送给从服务器执行
主服务器怎么知道要将哪些增量数据发送给从服务器?
repli_backlog_buffer是一个 「环形」缓冲区replication offset标记上面那个缓冲区的同步进度,主从服务器有各自的偏移量,主服务器使用 master_repl_offset 标记自己的「写」,从服务器使用 slave_repl_offset 来标记自己「读」到的位置
在主服务器进行命令传播时,会将写命令发送给从服务器,也会写入到 repli_backlog_buffer 缓冲区中
重连后,从服务器将自己的偏移量 offset 发送给主服务器
- 如果偏移量在 repl_backlog_buffer 缓冲区里,采用 增量复制
- 如果不在,则采用 全量同步
为避免频繁使用全量同步,应该调整 repl-backlog-size 参数,默认为 1M
1 | 通过命令修改 |
面试题
如何判断 redis 某个节点是否正常工作
主节点每隔 10 秒
从节点每隔 1 秒
主从复制架构中,过期 key 如何处理
redis 是同步复制还是异步复制
主从复制中两个 Buffer(replication buffer 和 repl-backlog-size)有什么区别
如何应对主从数据不一致
为什么会出现主从不一致?
如何应对主从不一致
主从切换如何减少数据丢失
主从切换,产生数据丢失的情况有两种
- 异步复制同步丢失
- 集群产生脑裂数据丢失
我们不可能保证数据完全不丢失,只能做到使得尽量少的数据丢失
异步复制同步丢失
对于 redis 主节点与从节点之间的数据复制,是「异步复制」的,当客户端发送写请求给主节点,客户端会返回 ok ,主节点将写请求 异步 同步给各个从节点,但如果主节点还没来得及同步发生了断电,主节点内存的数据会丢失
减少异步复制的数据丢失方案
redis 配置中 min-slaves-max-lag ,表示一旦所有从节点数据复制和同步的延迟超过了 min-slaves-max-lag 值,主节点就会停止接受写请求,直到所有从节点数据同步完成
假设将 min-slaves-max-lag 设置为 5,那么当所有从节点数据复制和同步的延迟都超过 5 秒,就会认为 master 未来宕机后损失的数据会很多,拒绝写入新请求,这样 master 和 slave 数据差控制在 5 秒内,可以减少数据丢失
对于客户端,当发现不可写后,可以降级处理,先将数据写入本地缓存和磁盘,等恢复后再写入 master ;也可以写入消息队列,隔一段时间消费消息,重新写入
集群产生脑裂数据丢失
由于网络波动,集群节点间失去联系,主从数据不同步;重新选举主节点,将原来的主节点数据清空作为从节点,这导致原来的主节点的「断开期间的写操作」数据丢失
减少脑裂数据丢失
- min-slaves-to-write x,主节点必须 至少 x 个从节点连接,否则禁止写数据
- min-slaves-max-lag x,数据复制和同步的延迟 不能超过 x 秒,否则禁止写入
主从切换
redis 哨兵机制…
