【重难点】【Redis 02】Redis 的持久化、Redis 的主从复制和集群、哨兵
一、Redis 的持久化
Redis 的持久化分为 RDB 持久化和 AOF 持久化,其中 RDB 持久化是镜像全量持久化,AOF 是增量持久化。在 Redis 的实际运行过程中,因为 RDB 需要做全量持久化,所以会耗费很长时间,导致服务阻塞,因此需要配合 AOF 使用,当然也可以使用 BGSAVE 命令另外开一个子进程来进行 RDB 持久化,但是这种方式实际上是采用的 CopyOnWrite 的思想,只能持久化当前的数据库状态,无法完全同步,想要完全同步还是需要使用 AOF。在 Redis 实例重启的时候,会使用 RDB 文件重新构建内存,然后加载 AOF 文件重新执行近期的指令来完整地恢复重启之前的状态
Redis 服务器突然宕机怎么办?
对于 Redis 来说,把数据库从内存持久化到磁盘上的 AOF 文件需要经过两层缓存,先是由 Redis 管理的 AOF 缓存,然后是由操作系统管理的系统缓存区。Redis 可以控制 AOF 缓存区实时地写入系统缓存区,但是想要让系统缓存区的数据真正写入硬盘需要调用 fsync 系统函数。我们可以通过 Redis 配置文件中的 appendfsync 选项来设置调用该函数的频率,分别是 always、everysec 和 no,宕机时丢失数据的多少就取决于这个选项
RDB 与 AOF 的区别
- RDB 是通过保存数据库中的键值对来记录数据库状态;AOF 是通过保存 Redis 服务器所执行的写命令来记录数据库状态
- RDB 持久化的频率没有 AOF 持久化的频率高
注意点
BGSAVE 和 BGREWRITEAOF 不能同时执行,因为同时开启两个子进程执行大量的磁盘写入操作,会非常耗费系统性能,也没有这个必要
二、Redis 的主从复制和集群
Redis 的主从复制是怎么实现的?
用户可以通过执行 SLAVEOF 命令来让一个服务器去复制另一个服务器。在第一次同步的时候,主节点会进行一次 BGSAVE,并同时将后续的写操作记录到 AOF 日志中,BGSAVE 执行完毕后再将 RDB 文件全部同步到从节点,待从节点同步完成后,再通知主节点同步 AOF 日志
Redis 的集群是怎么实现的?
用户可以通过执行 CLUSTER MEET 命令让当前节点与指定节点进行握手,握手成功后,这两个节点就形成了一个集群。Redis 集群是通过分片的方式来保存数据库中的键值对,集群的整个数据库背分为 16384 个槽,数据库中的某个键值对就存放在这 16384 个槽中的其中一个里面。用户可以通过执行 CLUSTER ADDSLOT 命令进行槽指派,将指定序号的槽指派给集群中的某个节点。每个节点都会存储集群中所有节点的信息,以及槽指派的信息,这样就可以通过键值对所在槽来定位到实际存储的节点地址
主从复制和集群有什么联系?
主从复制中,主节点和从节点存储着相同的数据,可以看作是一种数据备份,主节点宕机,从节点可以顶上去。集群是让多个节点合作,一起做一件事情,各有各的分工,一个节点宕机了,如果该节点没有做主从复制,那么整个集群就无法正常运作
三、哨兵
哨兵是 Redis 的高可用解决方案,用于监视任意多个主服务器以及这些主服务器的所有从服务器,并且在主服务器故障时,自动将从服务器升级为新的主服务器,以达到故障转移的效果
哨兵的原理是什么?
哨兵实现故障转移的原理是 Raft 算法,Raft 算法是一种选举算法。假如有 A、B、C、D、E 五个节点,其中 A 是主节点。正常情况下,主节点 A 会向从节点发送心跳信息来同步数据,当主节点 A 宕机后,B、C、D、E 就无法收到 A 的心跳信息,超过设定的时间从节点就会自动成为候选人,向其余节点发起拉票请求,并且投自己一票,其余节点收到拉票请求就会自动投该候选人一票,当其中一个候选人得票超过半数就会成为新的主节点
如何处理脑裂?
脑裂是指由于网络故障,导致一个主从集群中出现了两个主节点,客户端会同时向两个主节点写入数据或者只向其中一个主节点写入数据,当故障排排除后,哨兵将其中一个主节点降级为从节点,这样就会导致这个主节点的数据无法同步到其他从节点,造成数据的大量丢失
应对脑裂问题的最好办法就是防止脑裂,通过 Redis 配置文件中的 min-slaves-to-write 和 min-slaves-max-lag 来设置主节点能进行数据同步的最少从节点数量和主从复制时确认消息允许的最大延迟,不满足条件的主节点不能接收客户端的请求
选举领头 Sentinel
当一个主节点下线时,监视这个主节点的各个 Sentienl 会进行协商,选举一个零头 Sentienl,并由领头 Sentinel 对下线主节点执行故障转移操作
以下是 Redis 选举领头的规则和方法:
- 所有在线的 Sentinel 中的任意一个都有可能成为领头 Sentinel
- 每次进行领头 Sentinel 选举之后,不论选举是否成功,所有 Sentinel 的配置纪元都会自增
- 在一个配置纪元内,所有 Sentinel 都有一次设置局部领头的机会
- 每个发现主节点下线的 Sentinel 要求其他 Sentinel 将自己设置为局部领头
- Sentinel 设置局部领头的规则是先到先得
- Sentinel 将源 Sentinel 设置为局部领头后会给源 Sentinel 返回一条信息,信息中记录了当前 Sentienl 的运行 ID 和配置纪元
- 源 Sentinel 收到超过半数的 Sentinel 发来的返回信息就会成为领头