MySQL におけるスプリット ブレインとは、高可用性 (HA) システムにおいて、接続されている 2 つのノードが切断されると、もともと全体だったシステムが 2 つの独立したノードに分割されることを意味します。ノードが共有リソースをめぐって競合し始め、その結果、システムが混乱し、データが破損します。ステートレス サービスの HA システムの場合、スプリット ブレインであるかどうかは問題ではありませんが、ステートフル サービス (MySQL など) の HA システムの場合は、スプリット ブレインを厳密に防止する必要があります。
このチュートリアルの動作環境: Windows7 システム、mysql8 バージョン、Dell G3 コンピューター。
スプリットブレイン
は、接続されている 2 つのノードが切断されたときの高可用性 (HA) システムを指します。 、もともと全体だったシステムが 2 つの独立したノードに分割され、このとき 2 つのノードが共有リソースをめぐって競合し始め、システムの混乱やデータの損傷につながります。
高可用性クラスター環境には、アクティブ ノードと、アクティブ ノードに障害が発生したり応答が停止したときにサービスを引き継ぐ 1 つ以上のスタンバイ ノードがあります。
ノード間のネットワーク層を考慮するまでは、これは合理的な仮定のように思えます。ノード間のネットワーク パスに障害が発生した場合はどうなりますか?
どちらのノードももう一方のノードと通信できなくなります。この場合、スタンバイ サーバーは、アクティブ ノードに障害が発生したと判断して、自身をアクティブ サーバーに昇格させる可能性があります。これにより、各ノードは他のノードが死んでいると考えるため、両方のノードが「生きた」状態になります。その結果、両方のノードでデータが変更されるため、データの整合性と一貫性が損なわれます。これは「スプリット ブレイン」と呼ばれます。
ステートレス サービスの HA の場合、スプリット ブレインであるかどうかは関係ありませんが、ステートフル サービス (MySQL など) の HA の場合は、スプリットブレインは厳密に防止する必要があります。 (ただし、運用環境の一部のシステムでは、ステートレス サービス HA セットに従ってステートフル サービスが構成されており、その結果は想像できます...)
HA クラスターのスプリット ブレインを防ぐ方法
通常は 2 つの方法を使用します 1) 仲裁 2 つのノードの意見が一致しない場合、第三者のアービターがどちらの決定を聞くかを決定します。このアービターは、ロック サービス、共有ディスク、またはその他のものである可能性があります。
2) フェンシング ノードの状態が判断できない場合は、信頼性の高いフェンス設備が存在することを前提として、フェンシングによって他のノードを強制終了し、共有リソースが完全に解放されるようにします。
理想的には、上記のどちらも欠けてはいけません。 ただし、ノードがマスター/スレーブ レプリケーションに基づくデータベース HA などの共有リソースを使用しない場合、フェンス デバイスは安全に省略でき、クォーラムのみが保持されます。また、多くの場合、クラウド ホストなどの環境では利用可能なフェンス デバイスがありません。
それでは、調停を省略してフェンス装置だけを維持することはできるのでしょうか? できません。 2 つのノードが相互に接続できなくなると、同時にお互いをフェンシングすることになるためです。フェンシング方法が再起動の場合、2 台のマシンは継続的に再起動します。フェンシング方式の電源がオフの場合、結果として 2 つのノードが一緒に停止するか、1 つが生き残る可能性があります。しかし、2 つのノードが相互に接続できなくなった理由が、一方のノードのネットワーク カード障害であり、生き残ったノードがたまたま障害のあるノードだった場合、結末は悲劇的になります。 したがって、単純な二重ノードでは、いかなる場合でもスプリット ブレインを防ぐことはできません。
上記の戦略を実装する方法
上記のロジックに準拠する一連のスクリプトを最初から実装できます。 Pacemaker Corosync や適切なリソース エージェントなど、成熟したクラスター ソフトウェアを使用して構築することをお勧めします。 Keepalived はステートフル サービスの HA には適しておらず、たとえアービトレーションやフェンスがソリューションに追加されたとしても、常にぎこちなく感じられます。
Pacemaker Corosync を使用する際には、いくつかの注意事項もあります。 1) リソースエージェントの機能と原理を理解する リソース エージェントの機能と原則を理解することによってのみ、リソース エージェントが適用されるシナリオを知ることができます。たとえば、pgsql のリソース エージェントは比較的完成度が高く、同期および非同期ストリーム レプリケーションをサポートし、2 つを自動的に切り替えることができ、同期レプリケーション中にデータが失われないことを保証できます。しかし、現在の MySQL のリソース エージェントは非常に弱いです。GTID やログ補償がないと、データが失われやすくなります。これを使用せず、MHA を使い続けることをお勧めします (ただし、MHA をデプロイするときは、スプリット ブレインに注意してください) )。
2) 法定の投票数 (定足数) を確保する クォーラムは Pacemkaer 独自の調停メカニズムと考えることができ、クラスター内のすべてのノードの大部分がコーディネーターを選択し、クラスター内のすべての命令はこのコーディネーターによって発行されるため、スプリット ブレイン問題を完全に排除できます。このメカニズムが効果的に機能するには、クラスター内に少なくとも 3 つのノードが必要であり、no-quorum-policy が stop に設定されており、これがデフォルト値でもあります。 (多くのチュートリアルでは、デモンストレーションの便宜上、no-quorum-policy を無視するように設定しています。運用環境でもこれが行われ、他の調停メカニズムがない場合、これは非常に危険です!)
ただし、 2ノードどうすればいいでしょうか?
但是如果你有很多双节点集群,找不到那么多用于凑数的节点,又不想把这些双节点集群拉到一起凑成一个大的集群(比如觉得不方便管理)。那么可以考虑第三种方法。 第三种方法是配置一个抢占资源,以及服务和这个抢占资源的colocation约束,谁抢到抢占资源谁提供服务。这个抢占资源可以是某个锁服务,比如基于zookeeper包装一个,或者干脆自己从头做一个,就像下面这个例子。这个例子是基于http协议的短连接,更细致的做法是使用长连接心跳检测,这样服务端可以及时检出连接断开而释放锁)但是,一定要同时确保这个抢占资源的高可用,可以把提供抢占资源的服务做成lingyig高可用的,也可以简单点,部署3个服务,双节点上个部署一个,第三个部署在另外一个专门的仲裁节点上,至少获取3个锁中的2个才视为取得了锁。这个仲裁节点可以为很多集群提供仲裁服务(因为一个机器只能部署一个Pacemaker实例,否则可以用部署了N个Pacemaker实例的仲裁节点做同样的事情。但是,如非迫不得已,尽量还是采用前面的方法,即满足Pacemaker法定票数,这种方法更简单,可靠。
--------------------------------------------------------------keepalived的脑裂问题----------------------------------------------
1)解决keepalived脑裂问题
检测思路:正常情况下keepalived的VIP地址是在主节点上的,如果在从节点发现了VIP,就设置报警信息。脚本(在从节点上)如下:
[root@slave-ha ~]# vim split-brainc_check.sh #!/bin/bash # 检查脑裂的脚本,在备节点上进行部署 LB01_VIP=192.168.1.229 LB01_IP=192.168.1.129 LB02_IP=192.168.1.130 while true do ping -c 2 -W 3 $LB01_VIP &>/dev/null if [ $? -eq 0 -a `ip add|grep "$LB01_VIP"|wc -l` -eq 1 ];then echo "ha is brain." else echo "ha is ok" fi sleep 5 done 执行结果如下: [root@slave-ha ~]# bash check_split_brain.sh ha is ok ha is ok ha is ok ha is ok 当发现异常时候的执行结果: [root@slave-ha ~]# bash check_split_brain.sh ha is ok ha is ok ha is ok ha is ok ha is brain. ha is brain.
2)曾经碰到的一个keepalived脑裂的问题(如果启用了iptables,不设置"系统接收VRRP协议"的规则,就会出现脑裂)
曾经在做keepalived+Nginx主备架构的环境时,当重启了备用机器后,发现两台机器都拿到了VIP。这也就是意味着出现了keepalived的脑裂现象,检查了两台主机的网络连通状态,发现网络是好的。然后在备机上抓包:
[root@localhost ~]# tcpdump -i eth0|grep VRRP tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 22:10:17.146322 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:17.146577 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:17.146972 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:18.147136 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:18.147576 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:25.151399 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:25.151942 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:26.151703 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:26.152623 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:27.152456 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:27.153261 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:28.152955 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:28.153461 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:29.153766 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:29.155652 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:30.154275 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:30.154587 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:31.155042 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:31.155428 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:32.155539 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:32.155986 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:33.156357 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:33.156979 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 22:10:34.156801 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20 22:10:34.156989 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20 备机能接收到master发过来的VRRP广播,那为什么还会有脑裂现象? 接着发现重启后iptables开启着,检查了防火墙配置。发现系统不接收VRRP协议。 于是修改iptables,添加允许系统接收VRRP协议的配置: -A INPUT -i lo -j ACCEPT ----------------------------------------------------------------------------------------- 我自己添加了下面的iptables规则: -A INPUT -s 192.168.1.0/24 -d 224.0.0.18 -j ACCEPT #允许组播地址通信 -A INPUT -s 192.168.1.0/24 -p vrrp -j ACCEPT #允许VRRP(虚拟路由器冗余协)通信 ----------------------------------------------------------------------------------------- 最后重启iptables,发现备机上的VIP没了。 虽然问题解决了,但备机明明能抓到master发来的VRRP广播包,却无法改变自身状态。只能说明网卡接收到数据包是在iptables处理数据包之前发生的事情。
3)预防keepalived脑裂问题
1)可以采用第三方仲裁的方法。由于keepalived体系中主备两台机器所处的状态与对方有关。如果主备机器之间的通信出了网题,就会发生脑裂,此时keepalived体系中会出现双主的情况,产生资源竞争。 2)一般可以引入仲裁来解决这个问题,即每个节点必须判断自身的状态。最简单的一种操作方法是,在主备的keepalived的配置文件中增加check配置,服务器周期性地ping一下网关,如果ping不通则认为自身有问题 。 3)最容易的是借助keepalived提供的vrrp_script及track_script实现。如下所示:
# vim /etc/keepalived/keepalived.conf ...... vrrp_script check_local { script "/root/check_gateway.sh" interval 5 } ...... track_script { check_local } 脚本内容: # cat /root/check_gateway.sh #!/bin/sh VIP=$1 GATEWAY=192.168.1.1 /sbin/arping -I em1 -c 5 -s $VIP $GATEWAY &>/dev/null check_gateway.sh 就是我们的仲裁逻辑,发现ping不通网关,则关闭keepalived service keepalived stop。
4)推荐自己写脚本
写一个while循环,每轮ping网关,累计连续失败的次数,当连续失败达到一定次数则运行service keepalived stop关闭keepalived服务。如果发现又能够ping通网关,再重启keepalived服务。最后在脚本开头再加上脚本是否已经运行的判断逻辑,将该脚本加到crontab里面。
【相关推荐:mysql视频教程】
以上がMySQL のスプリット ブレインとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。