ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Redis 哨兵(Sentinel)集群实现高可用:核心机制、部署架构与数据丢失防护

Redis 哨兵(Sentinel)集群实现高可用:核心机制、部署架构与数据丢失防护 Redis 哨兵Sentinel集群实现高可用核心机制、部署架构与数据丢失防护【免费下载链接】advanced-java Core Interview Questions Answers For Experienced Java(Backend) Developers | 互联网 Java 工程师进阶知识完全扫盲涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识项目地址: https://gitcode.com/gh_mirrors/ad/advanced-javaRedis 单机一旦宕机写请求将全部失效主从架构下的 slave 也会因失去复制源而形同虚设。本文基于本仓库「Redis 哨兵集群实现高可用」一文系统讲解哨兵Sentinel如何通过集群监控、故障转移与配置中心实现 Redis 主从架构的高可用剖析哨兵集群的部署形态、主观/客观宕机判定、自动发现与 slave 选举算法并给出主备切换数据丢失的配置级防护方案。读完本文你将掌握一套可直接落地的哨兵 主从高可用部署方案并理解其不保证零丢失的边界条件。哨兵是什么Redis 高可用的四大核心功能sentinel中文名是哨兵。哨兵是 Redis 集群架构中非常重要的一个组件主要有以下功能集群监控负责监控 Redis master 和 slave 进程是否正常工作。消息通知如果某个 Redis 实例有故障那么哨兵负责发送消息作为报警通知给管理员。故障转移如果 master node 挂掉了会自动转移到 slave node 上。配置中心如果故障转移发生了通知 client 客户端新的 master 地址。哨兵用于实现 Redis 集群的高可用本身也是分布式的作为一个哨兵集群去运行互相协同工作故障转移时判断一个 master node 是否宕机了需要大部分的哨兵都同意才行这涉及到了分布式选举的问题。即使部分哨兵节点挂掉了哨兵集群还是能正常工作的——因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的那就很坑爹了。从整个缓存架构的视角看本仓库在「如何保证 Redis 高并发、高可用」一文中明确指出Redis 实现高并发主要依靠主从架构一主多从单主写入、多从查询而实现高可用任何实例宕机都能进行主备切换则依靠哨兵。也就是说哨兵解决的是master 挂了怎么办的问题它让主从架构从一个人工干预才能恢复的系统变成自动故障转移的高可用系统。哨兵的核心知识与部署底线在使用哨兵之前有三个核心知识点必须刻在脑子里哨兵至少需要 3 个实例来保证自己的健壮性。哨兵 Redis 主从的部署架构是不保证数据零丢失的只能保证 Redis 集群的高可用性。对于哨兵 Redis 主从这种复杂的部署架构尽量在测试环境和生产环境都进行充足的测试和演练。至少 3 个实例并不是拍脑袋的数字而是由哨兵的分布式选举机制决定的——判断 master 是否宕机需要多数派majority同意哨兵自身也必须避免单点故障。下面通过具体的部署拓扑来分析为什么 2 个哨兵不够、3 个哨兵才稳妥。哨兵部署架构剖析从 2 节点到经典 3 节点为什么 2 个哨兵不够稳quorum 1 的场景哨兵集群必须部署 2 个以上节点如果哨兵集群仅仅部署了 2 个哨兵实例quorum 1---- ---- | M1 |---------| R1 | | S1 | | S2 | ---- ----配置quorum1时如果 master 宕机s1 和 s2 中只要有 1 个哨兵认为 master 宕机了就可以进行切换同时 s1 和 s2 会选举出一个哨兵来执行故障转移。但是与此同时还需要majority大多数哨兵都是运行的2 个哨兵majority2 3 个哨兵majority2 4 个哨兵majority2 5 个哨兵majority3 ...也就是说majority 是哨兵总数的过半数量n / 2 1。在 2 个哨兵的场景下如果此时仅仅是 M1进程宕机了哨兵 s1 正常运行那么故障转移是 OK 的。但如果整个 M1 和 S1 运行的机器宕机了那么哨兵只剩下 1 个S2此时没有 majority 来允许执行故障转移。虽然另外一台机器上还有一个 R1slave但故障转移不会执行。这就是 2 个哨兵的根本缺陷一旦一台机器整体宕机哨兵集群就凑不齐 majority整个 Redis 主从架构就失去了自动恢复能力。经典 3 节点哨兵集群quorum 2经典的 3 节点哨兵集群是这样的---- | M1 | | S1 | ---- | ---- | ---- | R2 |--------| R3 | | S2 | | S3 | ---- ----配置quorum2时如果 M1 所在机器宕机了那么三个哨兵还剩下 2 个S2、S3S2 和 S3 可以一致认为 master 宕机了然后选举出一个来执行故障转移同时 3 个哨兵的 majority 是 2所以还剩下的 2 个哨兵运行着就可以允许执行故障转移。这正是哨兵至少需要 3 个实例的原因只有哨兵数量 ≥ 3才能容忍任意一台哨兵所在机器整体宕机后仍然凑齐 majority 并完成主备切换。在实际生产环境中参考本仓库「生产环境中的 Redis 是怎么部署的」一文中的典型形态Redis cluster 用 10 台机器5 台部署主实例、5 台部署从实例每个主实例挂一个从实例任何主实例宕机都会自动故障迁移、从实例自动变为主实例继续对外读写。如果采用主从 哨兵方案则同样需要为哨兵规划独立的 3 个或以上实例避免哨兵与 Redis 节点同机部署导致机器宕机连带哨兵宕机。哨兵主备切换的数据丢失问题主备切换的过程可能会导致数据丢失。理解这一点至关重要哨兵只保证高可用不保证零丢失。数据丢失主要有两种情况。异步复制导致的数据丢失因为 master - slave 的复制是异步的所以可能有部分数据还没复制到 slavemaster 就宕机了此时这部分数据就丢失了。脑裂导致的数据丢失脑裂也就是说某个 master 所在机器突然脱离了正常的网络跟其他 slave 机器不能连接但是实际上 master 还运行着。此时哨兵可能就会认为master 宕机了然后开启选举将其他 slave 切换成了 master。这个时候集群里就会有两个 master也就是所谓的脑裂。此时虽然某个 slave 被切换成了 master但是可能 client 还没来得及切换到新的 master还继续向旧 master 写数据。因此旧 master 再次恢复的时候会被作为一个 slave 挂到新的 master 上去自己的数据会清空重新从新的 master 复制数据。而新的 master 并没有后来 client 写入的数据因此这部分数据也就丢失了。数据丢失问题的解决方案进行如下配置min-slaves-to-write 1 min-slaves-max-lag 10含义是要求至少有 1 个 slave数据复制和同步的延迟不能超过 10 秒。如果说一旦所有的 slave数据复制和同步的延迟都超过了 10 秒钟那么这个时候master 就不会再接收任何请求了。这两个配置分别从两个方向压低数据丢失减少异步复制数据的丢失有了min-slaves-max-lag这个配置就可以确保说一旦 slave 复制数据和 ack 延时太长就认为可能 master 宕机后损失的数据太多了那么就拒绝写请求这样可以把 master 宕机时由于部分数据未同步到 slave 导致的数据丢失降低到可控范围内。减少脑裂的数据丢失如果一个 master 出现了脑裂跟其他 slave 丢了连接那么上面两个配置可以确保说如果不能继续给指定数量的 slave 发送数据而且 slave 超过 10 秒没有给自己 ack 消息那么就直接拒绝客户端的写请求。因此在脑裂场景下最多就丢失 10 秒的数据。需要注意的是这类防护参数的取值slave 数量、延迟阈值应当结合业务对数据丢失的容忍度来设定阈值设得越小数据越安全但可用性越容易被单点 slave 抖动所伤阈值设得过大则数据丢失窗口会拉长。sdown 与 odown主观宕机与客观宕机sdown 是主观宕机Subjectively Down一个哨兵如果自己觉得一个 master 宕机了那么就是主观宕机。odown 是客观宕机Objectively Down如果 quorum 数量的哨兵都觉得一个 master 宕机了那么就是客观宕机。sdown 达成的条件很简单如果一个哨兵 ping 一个 master超过了is-master-down-after-milliseconds指定的毫秒数之后就主观认为 master 宕机了如果一个哨兵在指定时间内收到了 quorum 数量的其它哨兵也认为那个 master 是 sdown 的那么就认为是 odown 了。这背后的设计思想是单个哨兵的判断可能因为网络抖动、瞬时超时等偶发因素而误判只有多个哨兵达成一致达到 quorum才能把疑似宕机升级为确认宕机从而触发后续的故障转移流程。这里的is-master-down-after-milliseconds与选举算法中的down-after-milliseconds共同构成了哨兵对节点状态的完整判定体系。哨兵集群的自动发现机制哨兵互相之间的发现是通过 Redis 的pub/sub系统实现的每个哨兵都会往__sentinel__:hello这个 channel 里发送一个消息这时候所有其他哨兵都可以消费到这个消息并感知到其他的哨兵的存在。每隔两秒钟每个哨兵都会往自己监控的某个 masterslaves 对应的__sentinel__:hellochannel 里发送一个消息内容是自己的 host、ip 和 runid还有对这个 master 的监控配置。每个哨兵也会去监听自己监控的每个 masterslaves 对应的__sentinel__:hellochannel然后去感知到同样在监听这个 masterslaves 的其他哨兵的存在。每个哨兵还会跟其他哨兵交换对 master 的监控配置互相进行监控配置的同步。自动发现机制保证了新增哨兵节点无需手工告知其它哨兵我是谁只要新哨兵加入了同一套 masterslaves 的监控它就会通过__sentinel__:hello频道被其它哨兵感知并纳入集群协同。slave 配置的自动纠正哨兵会负责自动纠正 slave 的一些配置如果 slave 要成为潜在的 master 候选人哨兵会确保 slave复制现有 master 的数据如果 slave 连接到了一个错误的 master 上比如故障转移之后slave 还指向旧的 master那么哨兵会确保它们连接到正确的 master上。这一点在故障转移后尤为重要新 master 产生后其它 slave 需要被重新指向新 master 继续复制数据这个收敛动作正是由哨兵的配置纠正机制完成的。slave - master 选举算法如果一个 master 被认为 odown 了而且 majority 数量的哨兵都允许主备切换那么某个哨兵就会执行主备切换操作。此时首先要选举一个 slave 来晋升会考虑 slave 的一些信息跟 master 断开连接的时长slave 优先级复制 offsetrun id首先进行资格过滤如果一个 slave 跟 master 断开连接的时间已经超过了down-after-milliseconds的 10 倍外加 master 宕机的时长那么 slave 就被认为不适合选举为 master。判定公式如下(down-after-milliseconds * 10) milliseconds_since_master_is_in_SDOWN_state接下来会对 slave 进行排序依次按以下规则择优按照slave 优先级进行排序slave priority 越低优先级就越高优先级默认值相同可通过配置调整。如果 slave priority 相同那么看replica offset哪个 slave 复制了越多的数据、offset 越靠后优先级就越高——这样可以最大限度地保留已复制的数据。如果上面两个条件都相同那么选择一个run id 比较小的 slave。这个选举算法同时兼顾了数据完整性offset 越新越好与稳定性断连过久的 slave 被排除是哨兵切换质量的核心保障。quorum 与 majority 的配合每次一个哨兵要做主备切换需要两个层次的确认首先需要quorum数量的哨兵认为 odown然后选举出一个哨兵来做切换这个哨兵还需要得到majority哨兵的授权才能正式执行切换。如果quorum majority比如 5 个哨兵majority 就是 3quorum 设置为 2那么就 3 个哨兵授权就可以执行切换。如果quorum majority那么必须 quorum 数量的哨兵都授权比如 5 个哨兵quorum 是 5那么必须 5 个哨兵都同意授权才能执行切换。可以这样理解二者的分工quorum 决定要不要认为 master 挂了majority 决定允不允许真正执行切换。quorum 设置得越小故障转移越灵敏但误判概率越高quorum 设置得越大越保守但切换的确认成本越高甚至可能出现多数派都在但凑不齐 quorum 导致无法切换的情况。生产实践中通常建议 quorum 设置为哨兵节点数的过半数同时保证quorum majority让切换可以在多数派存活时顺利执行。configuration epoch切换的版本号哨兵会对一套 Redis masterslaves 进行监控有相应的监控的配置。执行切换的那个哨兵会从要切换到的新 masterslave - master那里得到一个configuration epoch这就是一个version 号每次切换的 version 号都必须是唯一的。如果第一个选举出的哨兵切换失败了那么其他哨兵会等待failover-timeout时间然后接替继续执行切换此时会重新获取一个新的 configuration epoch作为新的 version 号。configuration epoch 的存在是为了在多个哨兵可能并发/先后尝试切换的情况下给每一次切换打上唯一的世代标记避免新旧 master 配置互相覆盖、集群状态产生歧义。configuration 传播哨兵完成切换之后会在自己本地更新生成最新的 master 配置然后同步给其他的哨兵——就是通过之前说的pub/sub消息机制。这里之前的 version 号就很重要了因为各种消息都是通过一个 channel 去发布和监听的所以一个哨兵完成一次新的切换之后新的 master 配置是跟着新的 version 号的。其他的哨兵都是根据版本号的大小来更新自己的 master 配置的——只有携带更新 version 号的配置才能覆盖旧的配置这就保证了即使切换消息在网络中乱序到达所有哨兵最终也能收敛到同一个最新配置。生产实践要点与选型建议结合本仓库「Redis 主从架构」与「如何保证 Redis 高并发、高可用」的内容在实际落地哨兵 主从方案时还应关注以下几点主从复制是哨兵高可用的前置基础哨兵切换的本质是把 slave 提升为 master因此需要先保证主从复制链路健康异步复制、断点续传、心跳机制等才能谈得上切换后的数据完整性。务必开启 master 的持久化如果采用主从架构建议必须开启 master node 的持久化不建议用 slave node 作为 master node 的数据热备——否则 master 宕机重启时数据为空经过复制后 slave 的数据也会被清空。同时 master 的各种备份方案也需要做确保本地文件全部丢失时能从备份恢复。高可用不等于零丢失哨兵 主从架构只保证系统可用不保证数据不丢。对数据敏感的业务必须配合min-slaves-to-write/min-slaves-max-lag之类的配置把丢失窗口压到可接受范围。容量与规模选型如果数据量不大缓存一般几个 G单机 replication一主多从 哨兵集群即可支撑高并发与高可用如果数据量海量、需要横向扩容多个 master 分片则应考虑Redis 集群模式。本仓库生产部署文档中的典型形态是每个主实例挂一个从实例、任何主实例宕机自动故障迁移这正是哨兵高可用思路在集群规模下的延伸。测试与演练是上线前提哨兵切换涉及网络分区、进程崩溃、整机宕机等多种故障场景务必在测试环境完整演练master 进程宕机master 所在机器宕机网络分区形成脑裂等场景确认切换时间、数据丢失量都在业务可接受范围内再进入生产。小结哨兵集群是 Redis 主从架构走向高可用的关键组件它通过pub/sub自动发现彼此、通过 sdown/odown 两级判定确认故障、通过 quorum majority 双重确认触发切换、通过选举算法挑选最优 slave 晋升、并通过 configuration epoch 保证切换配置的全局收敛。但请始终记住它的边界——哨兵 主从只保证高可用不保证数据零丢失部署至少 3 个哨兵实例、配置好min-slaves-to-write与min-slaves-max-lag、开启持久化并做好备份、上线前充分演练是让这套方案在生产环境稳定运行的基本前提。【免费下载链接】advanced-java Core Interview Questions Answers For Experienced Java(Backend) Developers | 互联网 Java 工程师进阶知识完全扫盲涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识项目地址: https://gitcode.com/gh_mirrors/ad/advanced-java创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表