高可用集群系统如何防止脑裂( 二 )


对MySQL , 即使配置成半同步复制 , 在超时发生后 , 它可能会自动降级为异步复制 。为了防止MySQL的复制降级 , 可以设置一个超大的rpl_semi_sync_master_timeout , 同时保持rpl_semi_sync_master_wait_no_slave为on(即默认值) 。但是 , 这时如果从宕了 , 主也会hang住 。这个问题的破解方法和PostgreSQL是一样的 , 或者配置成1主2从 , 只要不是2个从都宕机就没事 , 或者由外部的集群监视软件动态切换半同步和异步 。
如果本来就是配置的异步复制 , 那就是说已经做好丢数据的准备了 。这时候 , 主从切换时丢点数据也没啥大不了 , 但要控制自动切换的次数 。比如控制已经被failover掉的原主不允许自动上线 , 否则如果因为网络抖动导致故障切换 , 那么主从就会不停的来回切 , 不停的丢数据 , 破坏数据的一致性 。
如何实现上面的策略你可以自己完全从头开始实现一套符合上述逻辑的脚本 。但我更倾向于基于成熟的集群软件去搭建 , 比如Pacemaker+Corosync+合适的资源Agent 。Keepalived我是极不推荐的 , 它就不适合用于有状态服务的HA , 即使你把仲裁 , fence那些东西都加到方案里 , 总觉得别扭 。
使用Pacemaker+Corosync的方案也有一些注意事项
1)了解资源Agent的功能和原理
了解资源Agent的功能和原理 , 才能知道它适用的场景 。比如pgsql的资源Agent是比较完善的 , 支持同步和异步流复制 , 并且可以在两者之前自动切换 , 并且可以保证同步复制下数据不会丢失 。但目前MySQL的资源Agent就很弱了 , 没有使用GTID又没有日志补偿 , 很容易丢数据 , 还是不要用的好 , 继续用MHA吧(但是 , 部署MHA时务必要防范脑裂) 。
2)确保法定票数(quorum)
quorum可以认为是Pacemkaer自带的仲裁机制 , 集群的所有节点中的多数选出一个协调者 , 集群的所有指令都由这个协调者发出 , 可以完美的杜绝脑裂问题 。为了使这套机制有效运转 , 集群中至少有3个节点 , 并且把no-quorum-policy设置成stop , 这也是默认值 。(很多教程为了方便演示 , 都把no-quorum-policy设置成ignore , 生产环境如果也这么搞 , 又没有其它仲裁机制 , 是很危险的!)
但是 , 如果只有2个节点该怎么办?
一是拉一个机子借用一下凑足3个节点 , 再设置location限制 , 不让资源分配到那个节点上 。
二是把多个不满足quorum小集群拉到一起 , 组成一个大的集群 , 同样适用location限制控制资源的分配的位置 。
但是如果你有很多双节点集群 , 找不到那么多用于凑数的节点 , 又不想把这些双节点集群拉到一起凑成一个大的集群(比如觉得不方便管理) 。那么可以考虑第三种方法 。
第三种方法是配置一个抢占资源 , 以及服务和这个抢占资源的colocation约束 , 谁抢到抢占资源谁提供服务 。这个抢占资源可以是某个锁服务 , 比如基于zookeeper包装一个 , 或者干脆自己从头做一个 , 就像下面这个例子 。
http://my.oschina.net/hanhanztj/blog/515065
(这个例子是基于http协议的短连接 , 更细致的做法是使用长连接心跳检测 , 这样服务端可以及时检出连接断开而释放锁)
但是 , 一定要同时确保这个抢占资源的高可用 , 可以把提供抢占资源的服务做成lingyig高可用的 , 也可以简单点 , 部署3个服务 , 双节点上个部署一个 , 第三个部署在另外一个专门的仲裁节点上 , 至少获取3个锁中的2个才视为取得了锁 。这个仲裁节点可以为很多集群提供仲裁服务(因为一个机器只能部署一个Pacemaker实例 , 否则可以用部署了N个Pacemaker实例的仲裁节点做同样的事情 。) 。但是 , 如非迫不得已 , 尽量还是采用前面的方法 , 即满足Pacemaker法定票数 , 这种方法更简单 , 可靠 。

【高可用集群系统如何防止脑裂】


推荐阅读