Redis 进阶知识点(可学习,可复习,可面试)
前言:本文参考了与 Redis 相关的课程,主要讲解了 Redis 面试中常问的几个问题,如 Redis 主从,Redis 哨兵,非常详细,适合小白和复习的大佬如果文章中有什么不准确或者需要改进的地方,还请大佬不吝赐教。在这里先感谢各位大佬
以下正文开始
文章目录
Redis 集群模式
Redis 主从架构
全量同步(sync)
增量同步(psync)
repl_backlog 原理
主从同步优化
全量和增量区别
Redis 哨兵
Redis 集群监控原理
集群故障恢复
Redis 集群模式
Redis 有三种集群模式,分别是:主从模式、哨兵模式、Cluster 模式。Rdis 最开始使用主从模式做集群,若 master 宕机需要手动配置 slave 转为 master;后来为了高可用提出来哨兵模式,该模式下有一个哨兵监视 master 和 slave,若 master 宕机可自动将 slave 转为 master,但它也有一个问题,就是不能动态扩充;所以在 3.x 提出 cluster 集群模式。
Redis 主从架构
Redis 的主从模式支持客户端的高并发状况。主从模式是三种模式中最简单的一种,在主从复制中,数据库被分为主数据库(master)和从数据库(slave)。其中,主节点主要负责写数据,而且主节点需要将数据写到其他的从节点上,而从节点负责读,所有的读请求全部走从节点。主从模式需要注意:
1.复制的数据流是单向的,只能由主节点复制到从节点。2.主(master)数据库可以进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库
3.从(slave)数据库一般都是只读的,并且接收主数据库同步过来的数据 4.一个 master 可以拥有多个 slave,但是一个 slave 只能对应一个 master
5.slave 挂了不影响其他 slave 的读和 master 的读和写,重新启动后会将数据从 master 同步过来 6.master 挂了以后,不影响 slave 的读,但 redis 不再提供写服务,master 重启后 redis 将重新对外提供写服务
7.master 挂了以后,不会在 slave 节点中重新选一个 master
假设 A,B 为两个 Redis 示例,如果想让 B 作为 A 的从节点,需要在 B 节点上执行命令:slaveof A 的 IP A 的端口(port)
全量同步(sync)
一般用于初次复制场景,Redis 早期支持的复制功能只有全量复制,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。
判断依据:Replication Id:简称 replid,是数据集的标记,id 一致则说明是同一数据集。每一个 master 都有唯一的 replid,slave 则会继承 master 节点的 replid。
offset:偏移量,随着记录在 repl_baklog 中的数据增多而逐渐增大。slave 完成同步时也会记录当前同步的 offset。如果 slave 的 offset 小于 master 的 offset,说明 slave 数据落后于 master,需要更新。
因此 slave 做数据同步,必须向 master 声明自己的 replication id 和 offset,master 才可以判断到底需要同步哪些数据。
因为 slave 原本也是一个 master,有自己的 replid 和 offset,当第一次变成 slave,与 master 建立连接时,发送的 replid 和 offset 是自己的 replid 和 offset。
master 判断发现 slave 发送来的 replid 与自己的不一致,说明这是一个全新的 slave,就知道要做全量同步了。
master 会将自己的 replid 和 offset 都发送给这个 slave,slave 保存这些信息。以后 slave 的 replid 就与 master 一致了
因此,master 判断一个节点是否是第一次同步的依据,就是看 replid 是否一致。
完整流程描述如下:
slave 节点请求增量同步
master 节点判断 replid,发现不一致,拒绝增量同步
master 将完整内存数据生成 RDB,发送 RDB 到 slave
slave 清空本地数据,加载 master 的 RDB
master 将 RDB 期间的命令记录在 repl_baklog,并持续将 log 中的命令发送给 slave
slave 执行接收到的命令,保持与 master 之间的同步
增量同步(psync)
增量同步:用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点。补发的数据远远小于全量数据,可以有效避免全量复制的过高开销
说白了就是只更新 slave 与 master 存在差异的部分数据
在 Redis 2.8 之后使用 psync 命令代替 sync 命令执行同步操作,psync 具备了数据全量重同步 和 部分重同步模式。
repl_backlog 原理
master 怎么知道 slave 与自己的数据差异在哪里呢?
这就要说到全量同步时的 repl_baklog 文件了。
这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从 0 开始读写,这样数组头部的数据就会被覆盖。
repl_baklog 中会记录 Redis 处理过的命令日志及 offset,包括 master 当前的 offset,和 slave 已经拷贝到的 offset:
slave 与 master 的 offset 之间的差异,就是 salve 需要增量拷贝的数据了。
随着不断有数据写入,master 的 offset 逐渐变大,slave 也不断的拷贝,追赶 master 的 offset:
直到数组被填满:
此时,如果有新的数据写入,就会覆盖数组中的旧数据。不过,旧的数据只要是绿色的,说明是已经被同步到 slave 的数据,即便被覆盖了也没什么影响。因为未同步的仅仅是红色部分。
但是,如果 slave 出现网络阻塞,导致 master 的 offset 远远超过了 slave 的 offset:
如果 master 继续写入新数据,其 offset 就会覆盖旧的数据,直到将 slave 现在的 offset 也覆盖:
棕色框中的红色部分,就是尚未同步,但是却已经被覆盖的数据。此时如果 slave 恢复,需要同步,却发现自己的 offset 都没有了,无法完成增量同步了。只能做全量同步。
主从同步优化
主从同步可以保证主从数据的一致性,非常重要。
可以从以下几个方面来优化 Redis 主从就集群:
在 master 中配置 repl-diskless-sync yes 启用无磁盘复制,避免全量同步时的磁盘 IO。
Redis 单节点上的内存占用不要太大,减少 RDB 导致的过多磁盘 IO
适当提高 repl_baklog 的大小,发现 slave 宕机时尽快实现故障恢复,尽可能避免全量同步
限制一个 master 上的 slave 节点数量,如果实在是太多 slave,则可以采用主-从-从链式结构,减少 master 压力
全量和增量区别简述全量同步和增量同步区别?
全量同步:master 将完整内存数据生成 RDB,发送 RDB 到 slave。后续命令则记录在 repl_baklog,逐个发送给 slave。
增量同步:slave 提交自己的 offset 到 master,master 获取 repl_baklog 中从 offset 之后的命令给 slave
什么时候执行全量同步?
slave 节点第一次连接 master 节点时
slave 节点断开时间太久,repl_baklog 中的 offset 已经被覆盖时
什么时候执行增量同步?
slave 节点断开又恢复,并且在 repl_baklog 中能找到 offset 时
Redis 哨兵
哨兵(sentinal)是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的 master 并将所有的 slave 连接到新的 master。哨兵的作用如下:
监控:Sentinel 会不断检查您的 master 和 slave 是否按预期工作
自动故障恢复:如果 master 故障,Sentinel 会将一个 slave 提升为 master。当故障实例恢复后也以新的 master 为主
通知:Sentinel 充当 Redis 客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给 Redis 的客户端
Redis 集群监控原理
Sentinel 基于心跳机制监测服务状态,每隔 1 秒向集群的每个实例发送 ping 命令:
•主观下线:如果某 sentinel 节点发现某实例未在规定时间响应,则认为该实例主观下线。
•客观下线:若超过指定数量(quorum)的 sentinel 都认为该实例主观下线,则该实例客观下线。quorum 值最好超过 Sentinel 实例数量的一半。
集群故障恢复
一旦发现 master 故障,sentinel 需要在 salve 中选择一个作为新的 master,选择依据是这样的:
首先会判断 slave 节点与 master 节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该 slave 节点
然后判断 slave 节点的 slave-priority 值,越小优先级越高,如果是 0 则永不参与选举
如果 slave-prority 一样,则判断 slave 节点的 offset 值,越大说明数据越新,优先级越高
最后是判断 slave 节点的运行 id 大小,越小优先级越高。
当选出一个新的 master 后,该如何实现切换呢?
流程如下:
sentinel 给备选的 slave1 节点发送 slaveof no one 命令,让该节点成为 master
sentinel 给所有其它 slave 发送 slaveof 192.168.150.101 7002 命令,让这些 slave 成为新 master 的从节点,开始从新的 master 上同步数据。
最后,sentinel 将故障节点标记为 slave,当故障节点恢复后会自动成为新的 master 的 slave 节点
哨兵小结 Sentinel 的三个作用是什么?
监控
故障转移
通知
Sentinel 如何判断一个 redis 实例是否健康?
每隔 1 秒发送一次 ping 命令,如果超过一定时间没有相向则认为是主观下线
如果大多数 sentinel 都认为实例主观下线,则判定服务下线
故障转移步骤有哪些?
首先选定一个 slave 作为新的 master,执行 slaveof no one(永不为奴)
然后让所有节点都执行 slaveof 新 master
修改故障节点配置,添加 slaveof 新 master
再次感谢各位小伙伴儿们的支持
评论