Keepalived与VIP漂移机制

Keepalived基于VRRP协议实现主备切换,原理是两台服务器共享一个虚拟IP(VIP),正常情况下VIP绑定在主节点上,对外提供服务。主节点定期发送VRRP通告包,备节点监听这些包,如果一段时间内收不到通告,就认为主节点挂了,立即把VIP接管过来,对外服务不受影响。

实际配置中要注意几个关键参数。vrrp_instance的priority决定主备角色,数值大的为主。advert_int是通告间隔,默认1秒,生产环境用默认值就行。authentication要配,不配的话同一个网段内有多个VRRP实例可能互相干扰。script字段可以绑定健康检查脚本,比如检测Nginx进程是否存活,如果脚本执行失败就降低priority触发切换,这样即使机器没挂但服务异常也能自动转移。

脑裂问题的防范

脑裂是高可用架构里最让人头疼的问题。主备之间的网络断了,备节点以为主节点挂了,把VIP接管过来,但主节点其实还活着,也在用这个VIP。两个节点同时写同一个VIP,数据一致性就崩了。防范脑裂的常用手段是加冗余通信链路,主备之间除了主网络再连一根独立网线或者走另一个网段,两条链路同时断的概率低很多。

更彻底的方案是引入第三方仲裁。比如用一个独立的节点做仲裁机,主备都跟仲裁机保持心跳,切换前先问仲裁机对方是否真的不可达。ZooKeeper和Consul都能担这个角色,方案成熟但增加了架构复杂度。对于规模不大的集群,fencing设备也是选择,直接通过IPMI或SSH把对方关机,简单粗暴但有效。

多活架构的设计原则

主备方案虽然能用,但备机平时闲着,资源利用率低。双活或多活架构让所有节点同时提供服务,没有主备之分,资源利用率高,故障切换也更平滑。设计多活架构首要考虑的是数据同步。如果各节点共享一套存储,比如用SAN或者分布式文件系统,数据一致性好保证,但存储本身又成了单点。如果各节点独立存储,就要用数据库同步或者消息队列做数据复制,复杂度上去了,延迟也需要考虑。

异地多活还要考虑网络延迟。北京和上海之间的RTT大概30毫秒,同步写的话这个延迟会叠加到每个请求上。对于读多写少的业务可以做异地只读,写请求统一走中心节点。对于强一致要求高的场景,三地五副本的方案比较稳,Google Spanner就是这个思路,但运维成本不低。

故障切换后的自愈流程

故障切换只是第一步,故障节点的修复和重新加入集群同样重要。运维团队要建立完善的告警通知机制,切换发生时第一时间通知到人。修复后的节点要经过健康检查才能重新接入,不能直接加回去,否则如果故障没真正解决,又会让集群处于异常状态。整个自愈流程最好自动化,通过Ansible或自研脚本实现检测、隔离、修复、回切的闭环。