1、什么是脑裂(split-brain)

在“双机热备”高可用(HA)的集群系统中,当联系两个节点的“心跳线”断开时(也就是两个节点断开联系时),本来为一个整体、动作协调的HA集群集群,就会分裂出两个独立的节点(也就是两个独立的个体)。由于双方都失去了联系,都会以为对方出现了故障,两个节点上的HA软件就会像“裂脑人”一样,“本能”地去争抢“共享资源”、争起“应用服务”。这样就会发生严重的后果:

  1. 出现共享资源被瓜分、两边"服务"都起不来了;
  2. 或者出现两边"服务"都起来了,但同时读写"共享存储",导致数据损坏(常见如数据库轮询着的联机日志出错)。

两个节点相互争抢共享资源,结果会导致系统混乱,数据损坏。对于无状态服务的HA,无所谓脑裂不脑裂,但对有状态服务(比如MySQL)的HA,必须要严格防止脑裂。 有的生产环境下会按照无状态服务HA的那一套配置去配置有状态服务,这样的结果可想而知。

2、集群脑裂产生的原因

一般来说,脑裂的发生,有以下几种原因:

  1. 高可用服务器各节点之间心跳线链路发生故障,导致无法正常通信。
  2. 因心跳线坏了(包括断了,老化)。
  3. 因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)。
  4. 因心跳线间连接的设备故障(网卡及交换机)。
  5. 因仲裁的机器出问题(采用仲裁的方案)。
  6. 高可用服务器上开启了iptables防火墙阻挡了心跳消息传输。
  7. 高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。
  8. 其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等。

注意:Keepalived配置里同一VRRP实例如果virtual_router_id两端参数配置不一致也会导致裂脑问题发生。

3、预防HA集群的脑裂发生

1、添加冗存的心跳线(也就是冗存通信的方法) 同时使用串行电缆和以太网电缆连接,同时用两条心跳线路(即心跳线也HA),这样的话其中一条线路坏了,另一个还是好的,依然可以传送心跳的消息,从而减少了“脑裂”现象的发生几率。

2、设置仲裁机制 当两个节点出现分歧时,由第3方的仲裁者决定听谁的。这个仲裁者,可能是一个锁服务,一个共享盘或者其它什么东西。例如设置参考IP(如网关IP),当心跳线完全断开时,2个节点都各自ping一下参考IP,不通则表明断点就出在本端。不仅"心跳"、还兼对外"服务"的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通参考IP的一端去起服务。更保险一些,ping不通参考IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。

3、fence机制 当不能确定某个节点的状态时,通过fence设备强行关闭该心跳节点,确保共享资源被完全释放!相当于Backup备用节点接收不到心跳信息,通过单独的线路发送关机命令关闭主节点的电源。

4、启用磁盘锁 正在服务一方锁住共享磁盘,“裂脑"发生时,让对方完全"抢不走"共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动"解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了"智能"锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。

5、编写监控状态是否正常的脚本 通过脚本来监控和检测节点的服务状态是否正常,假设某一个节点出现了异常,并在脚本设置的时间内无法修复异常,就会把异常节点的服务进程kill掉,将资源丢给另一个节点来管理。