新闻详情

新闻详情

首页 / 资讯中心 / 详情

高可用架构三支柱:无状态化、水平扩展与故障转移设计实战

发布时间:2026/10/1 19:48:44来源:尧图网络
高可用架构三支柱:无状态化、水平扩展与故障转移设计实战
1. 重新理解高可用三件事一个目标做后端开发和架构设计这些年我被问得最多的问题之一就是你的系统到底怎么保证高可用高可用这三个字在简历里人人都会写但在真实的生产环境里真正经得起故障演练、扛得住突发流量、能在凌晨三点数据库宕机时依然不丢请求的系统我见过的不算多。先说一个我自己的观点高可用不是某个组件、某条命令、某个配置文件能解决的它本质上是三件事的协同设计——无状态化、水平扩展和故障转移。这三件事单拆开看每一件都不算难网上资料一大把难的是把它们放在同一个系统里让它们互为前提、互相兜底。很多高可用方案做失败不是因为某一件事没做而是因为三件事之间出现了断层——比如应用做了无状态化但数据库还是单点比如水平扩展做了但扩展完发现 session 还黏在原来的节点上比如故障转移做了但切换之后应用连接池里的旧连接全废了。这篇文章我就把这三件事从头到尾拆一遍包括每一件背后的原理、常见的落地方式、以及三者如何协同设计。我还会结合我实际接触过的场景——Web 服务集群、MySQL 高可用、SQL Server 高可用同步、集群故障转移——把具体的配置思路和踩坑经验也一并分享出来。适合正在做架构设计、运维保障、或者准备把单机系统改造为高可用集群的同学参考。1.1 高可用的本质是把不可用时间压到最低我们聊高可用其实聊的是一个非常朴素的指标系统一年到头能正常服务的时间占比也就是常说的几个九。99%两个九意味着一年大概宕机 3.65 天99.9%三个九是 8.76 小时99.99%四个九是 52.6 分钟。很多业务其实连三个九都做不到不是因为技术不行而是因为架构层面压根没把高可用当成一个系统工程来做。要把不可用时间压到最低光靠买好机器用好硬件是没有出路的因为任何硬件都会坏任何软件都会有 bug任何机房都可能出事故。真正靠谱的思路只有一个让系统在部分组件失效的情况下仍然能对外提供服务。这就是无状态化、水平扩展和故障转移共同指向的那个目标。无状态化解决的是任何一个节点都可以被替换水平扩展解决的是有足够多的节点可以分担和接替故障转移解决的是节点失效后流量能自动切换到健康节点上。1.2 三件事不是三个独立方案而是环环相扣我见过不少团队把这三件事当成三个独立的优化项来推进先做无状态化做完就以为高可用搞定了后来又加负载均衡做水平扩展扩展完发现故障转移靠人工盯告警再后来配了故障转移结果切换时才发现应用层根本没准备好。这三件事其实是环环相扣的——无状态化是水平扩展的前提。如果应用节点持有本地状态比如 session 存在本地内存你扩到十个节点用户的下一个请求被负载均衡分到另一台机器状态就丢了扩展不仅没提升可用性反而制造了新故障。水平扩展是故障转移的基础。如果只有一台应用节点故障转移做得再漂亮也无处可转只有集群里存在多个健康节点故障转移才有意义。故障转移是无状态化和水平扩展的闭环。无状态化和水平扩展解决了正常情况下如何分摊流量的问题故障转移解决的是异常情况下如何把流量交给健康节点的问题。没有故障转移前面两件事做得再好遇到单点硬件故障时系统还是会停摆。所以设计高可用架构时千万不要一个一个地做而是要把这三件事放一起通盘考虑。下面我分别拆开讲最后再讲怎么协同设计。2. 无状态化把记忆赶出业务节点2.1 什么是状态为什么状态是高可用的天敌先明确一个概念。在分布式系统里状态指的是一份数据在某个节点上被持久化地保存并且后续请求的处理依赖这份数据。最常见也最典型的状态就是用户会话session。一个用户登录之后服务器在本地内存里记下他的登录信息后续请求带着 cookie 或 token 过来服务器从本地内存里找到对应的 session识别出这是同一个用户。听起来很自然对吧但问题来了如果这台服务器挂了对于那些 session 存在它内存里的用户来说他们的登录状态就丢了请求被负载均衡转发到另一台服务器另一台服务器查不到这个 session会直接把用户踢回登录页。用户侧的感受就是系统突然要我重新登录这在生产环境里就是不可用。更麻烦的是如果你把负载均衡策略配成按用户 IP 哈希或者按 session ID 哈希强行把同一用户的请求都打到同一台机器上那这台机器的负载就会变成一个热点其他机器闲着这台机器累死所谓水平扩展变成了伪扩展。除了 session以下这些也属于状态的范畴应用节点本地磁盘上的临时文件、进程内存里的业务计数器、节点本地缓存等。凡是只有某一台节点拥有、其他节点读不到、并且业务依赖它的数据都是高可用的天敌。2.2 把状态踢出去的三种手段无状态化的核心思路一句话就能概括让业务节点变成无记忆的纯计算节点所有需要保留的数据都放到外部共享存储里。具体来说有三种常见手段**第一Session 外置。**把原本存在内存里的 session 挪到 Redis、Memcached 或数据库里。所有应用节点都去同一个 Redis 集群读写 session任何一台应用节点处理请求都能拿到完整的会话数据。这样任意节点宕机用户请求被转发到其他节点后session 还能从 Redis 里取回来登录状态不丢。我当时改造过一个老项目session 从本地内存迁到 Redis代码改动其实很小引入一个 session 管理库配置连接信息再改一下 session 存取路径半天就完成了但可用性提升是立竿见影的。**第二本地文件外置。**业务产生的临时文件、上传的图片、导出的报表不要往应用节点的本地磁盘写。本地磁盘有两个问题一是节点扩容时文件不会自动同步到新节点二是节点宕机被替换时本地文件随机器一起消失。正确做法是把文件放到对象存储比如 MinIO、云上的 OSS/S3或者分布式文件系统中应用节点只负责处理文件的读写请求不持有文件本体。**第三业务数据集中化。**应用节点内的本地缓存能不用就不用非要用也要做好缓存失效广播的机制否则一旦节点数多了缓存一致性会变成一场噩梦。正式的缓存应该放到独立的缓存集群Redis Cluster 或者 Hazelcast 这类分布式缓存里由集群自身去保证数据分布和副本。提示无状态化并不是说系统里不允许有状态而是说状态要收敛到专门的、具备自身高可用能力的组件上。Redis、数据库这些组件本来就是有状态的它们的高可用靠后面要讲的故障转移来保证。无状态化说的是业务节点这一层不要持有状态。2.3 无状态化改造的实操要点无状态化改造看似简单但实际操作中容易踩坑。我列几个自己亲身踩过的**连接池的管理。**应用节点把状态外置之后每一个节点都会同享地连接 Redis 或数据库连接池的连接数上限、空闲超时、最大等待时间这些参数要提前规划。10 个节点和 1 个节点对后端连接数的压力完全不同。我记得有一次改造完 session 外置后Redis 的连接数一夜之间涨了 8 倍Redis 默认的 maxclients 直接被打满反而引发了新的故障。**配置的收敛。**无状态化不只是数据层面的配置也算一种状态。每台应用节点上散落的配置文件比如数据库地址、第三方服务的密钥要收敛到配置中心比如 Nacos、Consul、etcd confd里统一管理。否则节点扩容时新拉起一台机器还得手动改配置文件一旦配错新节点一上线就带着错误配置加入集群危害更大。**随机性和本地性操作的排查。**改造完之后要专门做一轮代码审查检查有没有往本地磁盘写东西用了本机 IP 拼 URL依赖了本机时间戳做业务主键之类的隐性状态。特别是本机 IP 拼 URL这种操作单机部署时没啥问题一旦水平扩展回调地址全打到同一台机器上轻则功能异常重则雪崩。无状态化做完之后你会得到一个非常清爽的结论**应用层任意一台机器随时可以宕机、随时可以被替换业务不受影响。**这是后面所有高可用设计的地基。3. 水平扩展从一台机器扛所有到集群分摊压力3.1 垂直扩展的天花板与水平扩展的逻辑无状态化做完之后紧接着的问题是一台机器的处理能力是有上限的怎么突破很多团队的第一反应是加配置也就是垂直扩展——把 CPU 从 4 核升到 32 核内存从 8G 升到 64G磁盘从 SATA 换成 NVMe。垂直扩展的好处是简单不改造代码业务毫无感知。但它的天花板很明显硬件是有上限的双路 CPU 的服务器最多就那么多核内存插满也就那么大的容量而且越往上走成本不是线性增长而是指数级增长一台顶配服务器能买好几台中端配置的机器。水平扩展的思路完全反过来**不追求单台机器更强而是让一堆普通机器一起工作每台机器分摊一部分流量。**核心机制就两个负载均衡把请求分发到多台节点上节点之间无状态、可互换。我拿一个非常直观的生活例子来类比一家餐厅只有一个厨师客人一多就只能排队这是垂直扩展思路给厨师加薪让他干活更快但一天就那么多时间水平扩展是再请几个厨师一起在厨房做菜来多少客人都能接得住。要让多个厨师协作不出乱子前提是他们之间不需要共享记忆——比如不能出现这个菜只有张厨师知道怎么做的情况这就是无状态化。3.2 扩展的艺术分层扩展与容量规划水平扩展不是把应用节点复制 N 份那么简单。一套完整的系统通常分好几层负载均衡层、应用层、缓存层、数据层。每一层的扩展方式各不相同负载均衡层部署多台 Nginx/HAProxy前端再挂虚拟 IPVIP或者 DNS 轮询保证负载均衡器本身也不成为单点。应用层这是最方便扩展的因为经过无状态化改造之后应用节点就像即插即用的积木新起一个节点、注册到服务发现或负载均衡池里就能立刻接流量。缓存层单机 Redis 有容量上限可以升级为 Redis Cluster把数据自动分片到多个主节点上每个主节点再挂从节点。分片数量可以随着数据量增长而扩展。数据层MySQL 可以选择业务拆分拆库、读写分离一主多从、或者分库分表ShardingSphere、MyCat。SQL Server 则更多依赖 Always On 可用性组实现读写分离与高可用同步。做水平扩展时有个特别关键的考量**先搞清楚瓶颈在哪里再决定扩哪一层。**我见过不少团队应用层 CPU 才用到 30%就慌忙加应用节点结果数据库连接被打满整体性能反而更差了。正确做法是先压测、 先监控确认瓶颈是 CPU、内存、IO、连接数还是数据库的查询慢然后针对瓶颈层做扩展。3.3 常见扩展方案的选型对比我把自己实际用过的几种方案整理一下供大家选型时参考方案适用场景优点缺点DNS 轮询 多应用节点简单 Web 服务配置简单几乎零成本DNS 缓存导致切换不实时故障时无法自动摘除LVS/HAProxy 多应用节点中等规模集群调度能力强健康检查灵活故障节点自动摘除负载均衡器自身需要做主备部署Nginx 应用节点大部分 Web 场景配置简单、自带健康检查和重试机制单台 Nginx 是潜在单点需要前置 LVS 或 DNS 冗余Redis Cluster缓存量大、吞吐高的场景自动分片、自动故障转移扩展方便客户端需要适配 Cluster 协议MySQL 主从 MHA/MGR数据库高可用主从切换相对成熟读写分离效果好切换有秒级延迟主库故障时仍有短暂不可用SQL Server Always On微软技术栈、强一致性要求同步提交模式下数据零丢失可自动故障转移对网络要求高配置复杂度大表格里这几个方案其实正好对应了无状态化、水平扩展和故障转移这三件事在不同层次上的展开。接下来重点讲第三件事故障转移。4. 故障转移让系统具备自我修复的能力4.1 故障转移的两种模式主动切换与被动发现无状态化和水平扩展解决的是正常情况下多节点分摊流量但高可用最核心的临门一脚是**某台节点突然挂了之后系统能不能自动把它的流量交给别人。**这就是故障转移。故障转移有两种常见模式我分别说一下。**主动切换模式也叫做主备切换。**这种模式下系统里有两个角色主节点Active和备节点Standby。正常时所有流量都进主节点备节点处于待命状态持续从主节点同步数据或配置。主节点出现故障时监控组件比如 Keepalived 的 VRRP、MySQL MHA 的 manager检测到心跳丢失就会把 VIP虚拟 IP从主节点摘下来绑定到备节点上同时对备节点执行升级动作。应用层完全感知不到 IP 变化因为访问的始终是那个 VIP。这种模式适合数据库这类有状态组件。**被动发现模式也叫服务发现健康检查。**应用节点们把自己注册到注册中心Nacos、Consul、etcd负载均衡器定期对所有节点发起健康检查HTTP 探活、TCP 探测、执行自定义脚本。节点挂了健康检查失败负载均衡自动把它从可用节点列表里摘除新节点上线健康检查通过自动加回列表。这种模式适合无状态应用层因为无状态节点之间没有主备关系所有节点都是平等的任何一个挂掉只需把它从分发列表里剔除即可。无论是哪种模式故障转移都包含三个关键动作检测到故障、作出切换决策、执行切换动作。三个动作任何一个慢了或者错了故障转移就不会成功。4.2 数据库层的故障转移MySQL 主从切换与 SQL Server 高可用同步数据库是所有系统里最有状态的组件也是故障转移最难做的部分。原因很简单应用节点挂了数据在别处没啥影响数据库挂了数据就在它身上切换不只是把流量转走还要保证数据完整。我在实际工作中接触过的两个主流场景值得重点说说。MySQL 高可用的常见落地。MySQL 的高可用方案很成熟网上资料也多但落地时细节极其繁琐。从简单到复杂大致有三个层次第一层主从复制 手动切换。一个主库一个或多个从库开启 binlog从库通过 IO 线程拉取主库的 binlog写入自己的 relay log再由 SQL 线程回放。这个方案的优点是完全免费、配置简单、对业务代码透明缺点是主库宕机时需要运维人员手动把从库提升为主库再修改应用连接配置整个过程动不动就是十几分钟到半小时而且容易出错——比如提升之前忘了检查从库的回放进度导致提升后丢失最近几秒的数据。第二层使用 MHAMaster High Availability自动切换。MHA 是 MySQL 生态里老牌的高可用管理工具它监控主库的状态如果主库挂了MHA manager 会在候选从库中选择一个数据最完整的节点自动补全缺失的 binlog 事件然后提升为新主库并把其他从库重新指向新主库。使用 MHA 时有一个重要细节网络分区或者主库假死的情况下MHA 可能会把实际上还活着的旧主库误判为宕机触发切换这就可能造成双主的脑裂问题。所以生产环境里最好在切换脚本里加入一个旧主库隔离的步骤——确认旧主库已经被踢出集群之后才允许执行提升动作。第三层使用 MySQL 组复制MGR。MGR 是官方提供的多主/单主强一致方案底层用 Paxos 协议保证数据一致性。相比传统主从复制MGR 的故障检测由集群内部完成切换也更自动化、更迅速。MGR 的问题是配置门槛较高对网络延迟敏感而且某些 DDL 和事务存在限制比如不支持一些隐式锁需要业务侧做适配。另外现在很多人还会借助 Orchestrator 这类工具来做 MySQL 故障转移的编排它比 MHA 更现代拓扑感知能力更强支持跨机房场景。工具选型上我的建议是**不要盲目追求最新最炫的组件关键是理顺故障转移的语义和操作步骤然后做好充分的切换演练。**我见过一家公司MHA 配好了半年没切换过第一次真实故障时才发现 manager 所在机器和主库在同一台物理机上主库断电的时候 manager 也连不上了切换根本没法执行。SQL Server 高可用同步实践。微软技术栈里与其对应的高可用方案就是 Always On 可用性组Availability Group。它的核心思路是把一组数据库放进一个可用性组里组内有主副本和若干辅助副本辅助副本通过同步提交或异步提交模式接收主副本的数据变更。启用同步提交时事务在主副本上提交之前必须等辅助副本确认已持久化日志因此理论上可以做到零数据丢失的自动故障转移。Always On 故障转移的基本流程是主副本发生故障可用性组监听器Availability Group Listener检测到失联自动将某个辅助副本切换为主副本由于监听器提供了固定的虚拟网络名应用连接串指向监听器即可切换之后应用不需要修改连接字符串。配置 Always On 时下面几个坑是很多人都会遇到的域环境依赖。Always On 的自动故障转移通常依赖 Windows Server 故障转移集群WSFC而 WSFC 又依赖域环境。如果公司基础设施里没有域控配置起来会非常痛苦。这种场景下有时候只能退而求其次做手动故障转移。同步提交的性能开销。同步提交模式对事务响应时间的损耗是实实在在的尤其在跨机房的场景下每次提交都在等网络往返。所以异地灾备副本一般会设置成异步提交只有同城/同机房的副本才用同步提交。见证Witness配置。Always On 做自动故障转移时需要一个见证节点来防止脑裂。很多人在测试环境里不配见证结果两节点之间网络抖动一下集群就不知道应该选谁做主了。生产环境一定记得部署独立的见证节点云虚拟机或共享文件夹都可以。数据库层的故障转移之所以难归根到底是因为**它不仅要解决流量去哪儿的问题还要解决数据不能丢和数据不能乱的问题。**无状态化那一套在这些场景里用不了数据库本身必须持有状态。应对办法就是依靠数据库内核提供的复制协议、仲裁协议和切换机制把这些机制理解和配置到位才能真正做好高可用的最后一环。4.3 故障转移的边界脑裂、数据丢失与切换条件故障转移看起来是把流量从坏的节点挪到好的节点但实际执行时常常会遇到两个非常棘手的边界问题。第一是脑裂Split-Brain。所谓脑裂就是集群里两个节点都认为自己才是主节点同时对外提供服务导致数据双写、状态混乱。脑裂的根源往往是网络分区主节点和备份节点的网络断了心跳检测失败备份节点以为主节点死了于是把自己升级为主节点但此时主节点其实还活着还在对外提供服务两个主节点同时存在业务立刻乱套。解决脑裂的手段主要有两种仲裁机制比如引入第三方的 witness 节点投票少数服从多数和隔离机制比如抢占共享锁/STONITH把旧主节点强制关停。无论是哪种都在强调一件事切换必须经过严格的合法性确认宁可不切换也不能双主。第二是数据丢失风险与切换窗口。故障转移的另一个核心矛盾是切换越快越容易丢数据切换越安全耗时越长。拿 MySQL 主从来说异步复制下从库往往落后主库几百毫秒甚至几秒主库突然断电从库切换后最近那几百毫秒的事务就丢了。这种数据丢失对金融、交易类业务是完全不能接受的所以这类业务通常要求半同步复制或者强一致方案MGR、Galera但付出的代价是写入性能下降。故障转移不是免费的每一个高可用的承诺背后都需要你用一致性和性能去买单。因此做故障转移设计时我给自己定了一个原则**先明确定义可用性目标和一致性容忍度再选择对应的复制模式和切换策略。**目标越清楚方案越不容易做变形。5. 三者的协同设计从单一方案走向高可用架构5.1 一个典型的协同架构如何搭建无状态化、水平扩展、故障转移这三件事拆开讲容易协同起来才是真正的难点。我举个最常见的 Web 应用从单机演进到高可用集群的例子把协同设计的完整过程走一遍大家照着这个思路去套自己的场景就行。假设最初系统是一台服务器上面同时跑着 Nginx、应用进程比如 Spring Boot / Go 写的服务、Redis、MySQL。整个系统只有一个节点任何组件出问题系统就不可用。第一步应用层无状态化。把 Spring Boot 的 session 存储从内存切到 Redis把上传文件从本地磁盘迁到 MinIO 或 OSS把配置从本地配置文件切到 Nacos。这一步做完应用进程本身变成了无状态的可以随便复制。第二步负载均衡与水平扩展。在前面部署一层 Nginx把流量分发到 N 个应用节点上。Nginx 配置 upstream里面列出所有应用节点的 IP 和端口开启健康检查。应用节点不够了就新起一台机器把代码部署上去然后在 Nginx upstream 里加一条记录reload 一下 Nginx 就完成扩容。应用层的水平扩展到这里基本就通了。第三步缓存和数据层的故障转移。Redis 从单机改为 Redis Cluster至少三主三从或者退一步用一个主一从 Keepalived 的架构保证缓存层有自动切换能力。MySQL 从单机改为主从复制 MHA或 Orchestrator开启半同步复制配置自动切换脚本和 VIP 漂移SQL Server 则配置 Always On 可用性组和监听器设置好见证节点。第四步全局演练与收尾。完整地把这三件事串起来之后做一次故障演练杀掉一台应用节点看 Nginx 是否自动摘除该节点、流量是否平滑转移杀掉 Redis 主节点看 Redis Cluster 是否自动选出新主节点杀掉 MySQL 主库看 MHA 是否在 10~30 秒内完成切换、应用侧是否只是出现少量失败重试。这个演进路径每一步都是在给前面的步骤填坑无状态化让应用可以扩展扩展让故障转移有地方可去故障转移让整体架构有了自愈能力。三者协同的本质就是这么个逻辑。5.2 协同设计中的几个关键参数考量协同设计听起来有点虚但落到实操上确实有一些具体参数值得认真打磨。我把自己的经验集中列一下**注册中心/健康检查的超时与重试次数。**负载均衡的健康检查间隔建议设在 3~5 秒失败阈值 2~3 次成功阈值 2 次。间隔太短会频繁触发探活对节点造成不必要的压力太长则故障发现速度慢。Nginx 的proxy_next_upstream要配置为http_502 http_503 http_504这样单次请求遇到后端异常时Nginx 可以自动重试下一个节点应用层看到的就是一次成功响应。**会话超时与 Redis 连接池。**Session 外置到 Redis 之后session 超时时间要按业务实际需求设置不要随手设一个 30 分钟否则 Redis 里堆积大量无效 session导致内存膨胀。连接池参数方面Redis 连接池的maxTotal建议按单节点预计 QPS × 平均耗时 × 节点数冗余系数来估算比如一个节点大约 3000 QPS、平均获取连接耗时 0.5ms理论上需要约 1.5 个并发连接但为了留足余量通常直接按 8~16 配置即可。我没见过几个系统真的需要几百个 Redis 连接配置过大反而会打爆 Redis 的 fd 限制。**MySQL 半同步复制的超时。**半同步复制有一个超时参数rpl_semi_sync_master_timeout如果默认值比如 10 秒过大主库写入在从库迟迟不响应时会一直等待写入延迟飙升如果过小半同步会频繁退化成异步复制失去至少一份从库确认的保障。生产环境我一般设置在 1000~3000ms 之间性能和数据安全取一个平衡点。**自动切换的触发条件。**不要一看到主库端口不通就立刻切换。很多时候进程卡死、磁盘接近写满导致心跳超时并不代表主库彻底没救。合理的触发条件应该是连续 N 次心跳失败 监控组件尝试了 M 次重连 排除网络抖动可能性然后再执行切换。我见过一个团队因为网络抖动导致误切换切换后数据回放延迟引发了一连串连锁故障比不切还惨。5.3 协同设计中的常见误区和避坑建议协同设计做得多了自然能总结出一些规律性的坑。这里我重点说三个**误区一把状态外置等同于用 Redis。**Redis 本身是单线程模型虽然快但它也有自己的高可用问题主从切换瞬间有秒级卡顿、持久化 RDB fork 时会短暂阻塞。把 session 放进 Redis 之后Redis 就成了新的单点。所以做无状态化时必须同步考虑缓存层自身的高可用方案比如 Redis Cluster、主从 Sentinel 等。这一点最容易被忽略因为大家的注意力都在应用层很少有人会想到状态被踢到了 Redis 里Redis 挂了怎么办。**误区二故障转移做完了就不做回归测试。**故障转移直接影响的就是线上稳定性但很多团队只在初次配置时测一次后面业务代码、数据库 schema、网络环境都在变早就不是当初验证过的状态了。比如应用在代码里引入了对数据库的SELECT ... FOR UPDATE锁切换之后由于主从延迟应用可能读到旧数据或者锁等待表现完全不一样。我自己的习惯是每季度做一次故障演练把主库切换、Redis 主从切换、应用节点摘除这几个动作全部实际执行一遍确认监控告警是否都正常触发。**误区三把高可用寄托在某一个工具上。**使用 MHA、Orchestrator、Always On 等工具时最常见的心态是只要配置好了它数据库就高可用了。但工具只是切换的执行者它做不了业务层面的判断。真正的高可用需要的是整体机制的设计监控怎么采集、告警怎么分级、切换后应用的连接池怎么快速重建、下游的 binlog 消费端怎么应对主库切换带来的 binlog 坐标变化……这些细节都是在工具之外的。工具越高级越要警惕工具掩盖了机制不足的问题。提示一个实战时很有用的习惯把所有切换操作写进切换手册里包括检查清单、执行步骤、回滚措施。手册的目的是让一个不熟悉该系统的同事也能在故障时较快地执行切换。别小看这个动作出故障时大家脑子都是懵的有手册照着做状态会稳定非常多。6. 常见问题与排查技巧实录协同设计是一个系统工程在实操过程中遇到问题实在太正常了。我把过去几年里在 MySQL 高可用、SQL Server 高可用同步、集群故障转移这几个方向遇到的典型问题整理成一张速查表顺便把排查思路写清楚大家遇到类似情况时可以参考着查。6.1 典型问题速查表问题现象可能原因排查与解决思路故障转移后应用一直报连接超时应用连接池里的数据库连接还是指向旧主库 IP切换后连接未被重建应用侧数据库连接串改为指向 VIP 或使用连接池的自动重建机制切换脚本里增加一条通知应用的步骤或者依赖注册中心让连接自动刷新主从切换完成后部分数据查不到异步复制下从库落后主库切换时丢失了尾部事务开启半同步复制切换前检查从库的Seconds_Behind_Master对数据敏感场景使用 MGR/Always On 同步提交切换之后出现双主两个数据库同时在写脑裂旧主库未被真正隔离在切换脚本里加入隔离步骤如SET GLOBAL read_onlyON、关闭旧主库的网络或抢占仲裁配置好仲裁节点防止网络抖动导致误判应用水平扩展后用户频繁被踢下线session 还在本地内存未完全外置到 Redis检查 session 配置文件和代码中的 session 存取实现确认应用节点之间共享同一个 Redis 集群扩展节点后数据库连接数暴涨每个新应用节点都会建立一批数据库连接池池大小配置过大合理设置应用侧数据库连接池的maximum-pool-size如 10~20并预留冗余在数据库侧监控max_connections必要时调整数据库连接上限SQL Server 自动故障转移后辅助副本迟迟不进主Always On 的健康检查和仲裁配置有问题或者辅助副本同步模式是异步且落后太多检查 WSFC 群集事件日志确认同步提交副本数量是否满足自动故障转移条件检查见证节点是否在线Redis Cluster 主节点挂了但客户端报错重定向失败客户端没有正确支持 Cluster 协议如使用普通 Jedis 而非 JedisCluster替换为支持 Cluster 协议的客户端检查cluster-require-full-coverage配置建议生产环境设为no以提高可用性健康检查偶尔失败应用节点被频繁摘除和加回健康检查路径太敏感如探活依赖数据库查询数据库慢查询导致探活超时健康检查改为轻量级探活如检查进程存活 静态页面或内存状态不要在里面做数据库操作6.2 一些值得收藏的实战经验仔细讲讲我在实际排障过程中的几个体会。第一**故障转移之后最先要做的事情不是恢复业务而是确认没有双主。**很多人一看流量切过去了、系统恢复了就松了一口气。实际上如果切换过程有问题旧主库和新主库同时在接受写入这种隐患比宕机更可怕——因为数据分裂是慢慢发生的等之后再发现已经很难追回。所以我在切换完成后一定会第一时间检查集群状态、确认旧主库已被降级或隔离。第二**所有高可用系统的首要瓶颈往往不在组件本身而在切换后的人工决策环节。**自动切换脚本能把主库从 30 分钟手忙脚乱压缩到 30 秒自动完成前提是脚本可靠。但如果监控告警不够精准每次半夜告警都让人去排查原因等确认真的需要切换的时候系统的不可用时间已经过去好几分钟了。所以我会把告警分级做得非常细哪些是预警手动观察哪些是必须立即自动切换不可等待。把决策前移是高可用升级的着力点。第三**尽量让切换和恢复自动化但保留人介入的开关。**全自动切换不是万能的比如机房断电、核心交换机故障这类场景自动切换动作本身可能也是无效的。所以我会设计一个维护模式开关——在可预期的大规模变更期间比如机房迁移、网络割接把自动切换临时关闭改为人工决策。等变更结束再重新打开自动切换。第四**做高可用方案时多准备一条逃生通道。**比如数据库主库彻底损坏、所有副本都不完整时还能不能从最近的备份 binlog 恢复到某个时间点这听起来很原始但我见过很多团队把精力都花在主备切换上备份策略反而荒废了。其实备份和 binlog 归档是最后一道防线平时的恢复演练比切换演练更重要。真到了最坏的时刻一道可靠的备份通道比任何花哨的自动切换机制都让人安心。这篇文章把我对无状态化、水平扩展和故障转移的多年理解和盘托出了。最后再分享一个小建议高可用不是一次性的项目而是一个持续演进的过程。每次故障演练之后把出现的问题记录下来逐个补齐你的系统会一年比一年更稳。配合着这些经验试着从自己的最小系统开始先做无状态化再做扩展再配故障转移然后主动搞一次演练——我相信你会有不一样的体会。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

鱼缸潜水泵EMC整改:传导与辐射噪声根治方案 2026/10/1 20:37:13

鱼缸潜水泵EMC整改:传导与辐射噪声根治方案

1. 为什么鱼缸潜水泵的EMC问题总在深夜“闹鬼”?你有没有遇到过这种场景:鱼缸刚换上新买的静音潜水泵,水声潺潺,灯光柔和,造景美得像水下森林——结果第二天早上,WiFi断连三次、智能音箱突然开始念《道德经…

阅读更多 →
电控工程师必备:10个开源项目打造真实工程感 2026/10/1 20:37:00

电控工程师必备:10个开源项目打造真实工程感

1. 为什么电控岗简历石沉大海?不是你不行,是“工程感”没立住秋招季一到,我几乎每天都会收到私信:“投了30家车企/机器人公司/工业自动化企业的电控岗,连面试邀约都寥寥无几。”翻看这些同学的简历,硬件设计…

阅读更多 →
从Figma到Neovim:theSVG 10+插件与扩展生态全景清单 2026/10/1 20:36:47

从Figma到Neovim:theSVG 10+插件与扩展生态全景清单

从Figma到Neovim:theSVG 10插件与扩展生态全景清单 【免费下载链接】thesvg 7,400 brand SVG icons for developers. Tree-shakeable, typed, open source. npm i thesvg 项目地址: https://gitcode.com/gh_mirrors/th/thesvg theSVG 是一个开源的品牌 SVG 图…

阅读更多 →
机器学习大作业救星:Python+Streamlit算法可视化平台实战 2026/10/1 20:36:46

机器学习大作业救星:Python+Streamlit算法可视化平台实战

简介:这份资源是面向计算机、电子信息工程、数学等专业大学生的机器学习课程设计、期末大作业与毕业设计参考方案,核心为一个机器学习算法可视化平台,配套完整源代码与文档说明,帮助读者快速理解算法原理并完成可运行的项目交付。…

阅读更多 →
IAP升级死机?中断向量表重映射的绝对禁忌与正确实操 2026/10/1 20:36:40

IAP升级死机?中断向量表重映射的绝对禁忌与正确实操

做过IAP升级的嵌入式工程师,十有八九都遇到过这种场面:固件下载完成、校验通过,一复位,板子直接“睡死”——灯不闪、串口无输出、按复位键也没反应。更诡异的是,有些机器第一次升级后一切正常,第二次再升就…

阅读更多 →
RTC实时时钟驱动开发实战:从初始化到低功耗唤醒与校准 2026/10/1 20:36:39

RTC实时时钟驱动开发实战:从初始化到低功耗唤醒与校准

简介:面向嵌入式驱动开发者的RTC(实时时钟)驱动开发参考包,围绕实时时钟芯片的驱动实现展开,覆盖初始化、时间读取与设置、中断处理、电源管理、闰年与月份天数更新等关键环节,适合需要基于嵌入式平台实现或…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉