作者 | wzy0623

责编 | 屠敏

出品 | CSDN 博客

大多数MySQL高可用解决方案都是基于MySQL自带的各种复制技术。本质上是将一个实例上的数据更新或事务,在其它实例上进行重放,从而完成数据复制。当生产实例出现问题无法提供服务时,应用连接切换到其它实例,实现数据库服务持续可用。从这个角度看,使用DRBD实现MySQL高可用的方式则完全不同,它与MySQL复制毫无关系,可以说是另辟蹊径。

DRBD简介

DRBD的全称是Distributed Replicated Block Device,即分布式复制块设备,是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。DRBD是镜像块设备,是按数据位镜像成一样的数据块。简单说DRBD是实现活动节点存储数据更动后自动复制到备用节点相应存储位置的软件,是一种数据块级别的物理复制。

1. 工作原理

图1是官方文档里给出的DRBD工作栈模型,可以看到DRBD需要运行在各个节点上,且是运行在节点主机的内核中,所以DRBD是内核模块,在Linux 2.6.33版本起开始整合进内核。

图1 DRBD 架构

图1中假设左节点为活动节点(primary),右节点为备用节点(secondary)。左节点接收到数据发往内核的数据通路,DRBD在数据通路中注册钩子检查数据,当发现接收到的数据是发往到自己管理的存储位置,就复制另一份,一份存储到本机的DRBD存储设备,另一份就发给TCP/IP协议栈,通过网卡网络传输到另一节点主机的网上TCP/IP协议栈。而另一节点运行的DRBD模块同样在数据通路上检查数据,当发现传输过来的数据时,就存储到DRBD存储设备对应的位置。

如果左节点宕机,右节点可以在高可用集群中成为活动节点,把接收到的数据先存储到本地,当左节点恢复上线时,再把宕机后右节点变动的数据镜像到左节点。镜像过程完成后还需要返回成功/失败的回应消息,这个回应消息可以在传输过程中的不同位置返回,如图上的A/B/C标识位置,可以分为三种复制模式:

  • A:Async,异步:本地写成功后立即返回,数据放在发送buffer中,可能丢失,但传输性能好。

  • B:Semi sync,半同步:对方接收到数据后,但还没有落盘前返回。

  • C:Sync,同步:本地和对方写成功落盘确认后返回,数据可靠性高,生产系统一般都采用这种方式。

2. DRBD 支持的底层设备

DRBD需要在底层设备上构建出一个块设备。对于用户来说,一个DRBD设备,就像是一块物理的磁盘,可以在DRBD设备内创建文件系统。DRBD所支持的底层设备类别包括:磁盘或者是磁盘的一个分区;soft raid 设备;LVM的逻辑卷;EVMS(Enterprise Volume Management System,企业卷管理系统)卷;或其它任何块设备。

3. DRBD资源

DRBD资源定义DRBD管理的存储空间及相关信息,主要配置以下四个选项:

  • 资源名称:可以是除了空白字符外的任意ACSII码字符。

  • DRBD设备:在双方节点上,此DRBD设备的设备文件,一般为/dev/drbdN,其主设备号147。

  • 磁盘:在双方节点上,各自提供的存储设备。

  • 网络配置:双方数据同步时所使用的网络属性。

4. DRBD 配置工具

DRBD主要有以下三个配置工具:

  • drbdadm:高级管理工具,管理/etc/drbd.conf,向drbdsetup和drbdmeta发送指令。

  • drbdsetup:配置装载进kernel的DRBD模块,平时很少直接用。

  • drbdmeta:管理META数据结构,平时很少直接用。

5. DRBD与RAID1区别

RAID1也是实现不同存储设备间的数据镜像备份,不同的是RAID1各存储设备是连接一个RAID控制器接入到一台主机上的,而DRBD是通过网络实现不同节点主机存储设备数据的镜像备份。

6. DRBD与共享存储

如果各节点访问同一个数据文件都是在同一个存储空间内的,就是说数据共享的就一份,则这个存储空间就共享存储。而DRBD定义上就指出了“无共享”——不同节点存储设备空间是镜像,DRBD可以直接应用在主备模型的集群中,也可通过高可用软件如corosycn应用在双主模型集群中,不过这就需要DML/OCFS2/GFS2等分布式集群文件系统为双主读写的时候分配锁。还有就是DRBD为NFS共享存储提供高可用镜像备份。

DRBD安装配置

1. 实验环境

IP与主机名:

172.16.1.125    node1

172.16.1.126    node2

软件环境:

CentOS Linux release 7.2.1511 (Core)

DRBD 9.0.20

MySQL 5.6.14

DRBD:

磁盘分区:/dev/sdb  5G

DRBD设备:/dev/drbd0

DRBD资源:mysql

mount点:/mnt

2. 配置前准备

在安装配置DRBD前,需要做一些准备工作,以下步骤需要在两个节点都执行。

(1)设置静态IP

编辑网卡配置文件,将BOOTPROTO设置为static,如node1的内容如下:

[root@node1~]#cat /etc/sysconfig/network-scripts/ifcfg-ens32 
# Generated by dracut initrd
NAME="ens32"
DEVICE="ens32"
ONBOOT=yes
NETBOOT=yes
UUID="adb62466-2361-405e-ada9-b48fe7c09546"
IPV6INIT=yes
BOOTPROTO=static
TYPE=Ethernet
IPADDR=172.16.1.125
NETMASK=255.255.255.0
GATEWAY=172.16.1.254
DNS1=172.16.1.10

重启网络服务:

service network restart

(2)配置域名解析

编辑/etc/hosts文件配置域名解析,如node1的内容如下:

[root@node1~]#cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

172.16.1.125 node1
172.16.1.126 node2

(3)禁用SELINUX与防火墙

  • 编辑/etc/selinux/config文件,设置SELINUX=disabled。

  • 执行下面的命令禁用防火墙:

(4)设置双向ssh免密

node1上执行:

ssh-keygen -t rsa
ssh-copy-id 172.16.1.126

node2上执行:

ssh-keygen -t rsa
ssh-copy-id 172.16.1.125

(5)设置NTP时钟同步

yum install ntp
systemctl enable ntpd.service
service ntpd start

3. 下载安装DRBD

在两个节点执行以下命令:

# 导入GPG-KEY,用于验证签名
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 安装yum源
yum install https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm
# 安装drbd和内核相关软件包
yum install -y drbd90-utils kmod-drbd90 kernel*
# 因为升级了内核,需要重启系统
reboot

重启向内核加载drbd模块并确认:

[root@node2~]#modprobe drbd
[root@node2~]#lsmod | grep drbd
drbd_transport_tcp     22144  1 
drbd                  568697  3 drbd_transport_tcp
libcrc32c              12644  4 xfs,drbd,ip_vs,nf_conntrack
[root@node2~]#

4. 配置DRBD

DRBD的主配置文件为/etc/drbd.conf,为了管理的便捷性,目前通常会将些配置文件分成多个部分,且都保存至/etc/drbd.d目录中,主配置文件中仅使用”include”指令将这些配置文件片断整合起来。通常,/etc/drbd.d目录中的配置文件为global_common.conf和所有以.res结尾的文件。其中global_common.conf中主要定义global段和common段,而每一个.res的文件用于定义一个资源。

在配置文件中,global段仅能出现一次,且如果所有的配置信息都保存至同一个配置文件中而不分开为多个文件的话,global段必须位于配置文件的最开始处。common段则用于定义被每一个资源默认继承的参数,可以在资源定义中使用的参数都可以在common段中定义。实际应用中,common段并非必须,但建议将多个资源共享的参数定义为common段中的参数以降低配置文件的复杂度。

resource段则用于定义drbd资源,每个资源通常定义在一个单独的位于/etc/drbd.d目录中的以.res结尾的文件中。资源在定义时必须为其命名,名字可以由非空白的ASCII字符组成。每一个资源段的定义中至少要包含两个host子段,以定义此资源关联至的节点,其它参数均可以从common段或drbd的默认中进行继承而无须定义。

下面的操作在node1上完成。(1)查看主配置文件/etc/drbd.conf,内容如下:

[root@node1~]#cat /etc/drbd.conf
# You can find an example in  /usr/share/doc/drbd.../drbd.conf.example

include "drbd.d/global_common.conf";
include "drbd.d/*.res";
[root@node1~]#

/etc/drbd.conf主配置文件里面配置了包含关系,不需要做任何修改,直接使用即可。(2)配置global_common.conf文件内容如下。

[root@node1~]#cat /etc/drbd.d/global_common.conf
global {
    usage-count no;    # 不让官方统计drbd的使用情况
}

common {
        protocol C;    # 使用DRBD的同步协议,数据可靠性高  
        disk {
        on-io-error detach; # 配置I/O错误处理策略为分离
    }
}

on-io-error策略可能为以下选项之一:

  • detach:这是默认和推荐的选项,如果在节点上发生底层的硬盘I/O错误,它会将设备运行在Diskless无盘模式下。

  • pass_on:DRBD会将I/O错误报告到上层,在主节点上,它会将其报告给挂载的文件系统。

  • local-in-error:调用本地磁盘I/O处理程序定义的命令。这需要有相应的local-io-error调用的资源处理程序,给管理员有足够自由的权力调用local-io-error处理I/O错误。 

/etc/drbd.d/global_common.conf是全局配置文件,这里只设置了使用统计量、同步协议、I/O错误处理策略三项。该文件中还有一些其它选项,每个选项的含义在安装后的样例文件中都有相应说明。

(3)配置资源文件/etc/drbd.d/mysql.res内容如下,资源文件名要和资源名一样。

[root@node1 ~]# cat /etc/drbd.d/mysql.res 
resource mysql {                 # 资源名称
  disk /dev/sdb;                 # 磁盘分区
  device /dev/drbd0;                # DRBD设备
  meta-disk internal;                # 元数据存储方式
  on node1 {
    device /dev/drbd0;
    disk /dev/sdb;
    address 172.16.1.125:7789;            # 节点1地址
  }
  on node2 {
    device /dev/drbd0;
    disk /dev/sdb;
    address 172.16.1.126:7789;            # 节点2地址
  }
}

metadata有两种存储方式internal和external,存储方式是在每个resource配置段中指定的。配置成使用internal意味着DRBD把它的metadata和实际生产数据存储于相同的底层物理设备中。该存储方式是在设备的最后位置留出一个区域来存储metadata。

(4)将配置文件远程复制到node2

scp -rp  /etc/drbd.d/* node2:/etc/drbd.d/

(5)初始化设备元数据

分别在两节点上创建DRBD设备元数据:

drbdadm create-md mysql

(6)启动DRBD资源

分别在两节点上启动DRBD资源:

drbdadm up mysql

(7)查看节点角色

当前两台均为备机:

[root@node1~]#drbdadm role mysql
Secondary

(8)将node1设置primary

在node1执行:

[root@node1~]#drbdadm --force primary mysql
[root@node1~]#drbdadm role mysql
Primary

Parimary表示资源目前为主,并且可能正在被读取或写入,如果不是双主只会出现在两个节点中的其中一个节点上。Secondary表示资源目前为从,正常接收对等节点的更新。

(9)在主节点对磁盘进行格式化

[root@node1~]#mkfs.xfs /dev/drbd0
meta-data=/dev/drbd0             isize=512    agcount=4, agsize=327668 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=1310671, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

因为文件系统的挂载只能在Primary节点进行,所以也只有在设置了主节点后才能对DRBD设备进行格式化,这样就会连格式化后的全部信息都镜像到另一个节点。

(10)在主节点挂在设备

mount /dev/drbd0 /mnt

(11)查看状态

查看两个节点的磁盘状态和资源状态:

[root@node1/mnt]#drbdadm dstate mysql
UpToDate/UpToDate
[root@node1/mnt]#drbdadm cstate mysql
Connected

节点的硬盘有可能为下列状态之一: 

  • Diskless:本地没有块设备分配给DRBD使用,这表示没有可用的设备,或者使用drbdadm命令手工分离或是底层的I/O错误导致自动分离。

  • Attaching:读取无数据时候的瞬间状态。

  • Failed:本地块设备报告I/O错误的状态,其下一个状态为Diskless无盘。

  • Negotiating:在已经连接的DRBD设置进行Attach读取无数据前的瞬间状态。

  • Inconsistent:数据是不一致的,在两个节点上(初始的完全同步前)这种状态出现后立即创建一个新的资源。此外,在同步期间在同步目标节点上出现这种状态。

  • Outdated:数据资源是一致的,但是已经过时。

  • DUnknown:当对等节点网络连接不可用时出现这种状态。

  • Consistent:一个没有连接的节点数据一致。当建立连接时,它决定数据是UpToDate或是Outdated。

  • UpToDate:一致的最新的数据状态,这个状态为正常状态。

一个资源可能有以下连接状态中的一种:

  • StandAlone:网络配置不可用,资源还没有被连接或是被管理断开(使用 drbdadm disconnect 命令),或是由于出现认证失败或是脑裂的情况。

  • Disconnecting:断开只是临时状态,下一个状态是StandAlone独立的。

  • Unconnected:是尝试连接前的临时状态,可能下一个状态为WFconnection和WFReportParams。

  • Timeout:与对等节点连接超时,也是临时状态,下一个状态为Unconected。

  • BrokerPipe:与对等节点连接丢失,也是临时状态,下一个状态为Unconected。

  • NetworkFailure:与对等节点推动连接后的临时状态,下一个状态为Unconected。

  • ProtocolError:与对等节点推动连接后的临时状态,下一个状态为Unconected。

  • TearDown:临时状态,对等节点关闭,下一个状态为Unconected。

  • WFConnection:等待和对等节点建立网络连接。

  • WFReportParams:已经建立TCP连接,本节点等待从对等节点传来的第一个网络包。

  • Connected:DRBD已经建立连接,数据镜像现在可用,节点处于正常状态。

  • StartingSyncS:完全同步,有管理员发起的刚刚开始同步,未来可能的状态为SyncSource或PausedSyncS。

  • StartingSyncT:完全同步,有管理员发起的刚刚开始同步,下一状态为WFSyncUUID。

  • WFBitMapS:部分同步刚刚开始,下一步可能的状态为SyncSource或PausedSyncS。

  • WFBitMapT:部分同步刚刚开始,下一步可能的状态为WFSyncUUID。

  • WFSyncUUID:同步即将开始,下一步可能的状态为SyncTarget或PausedSyncT。

  • SyncSource:以本节点为同步源的同步正在进行。

  • SyncTarget:以本节点为同步目标的同步正在进行。

  • PausedSyncS:以本地节点是一个持续同步的源,但是目前同步已经暂停,可能是因为另外一个同步正在进行或是使用命令(drbdadm pause-sync)暂停了同步。

  • PausedSyncT:以本地节点为持续同步的目标,但是目前同步已经暂停,这可以是因为另外一个同步正在进行或是使用命令(drbdadm pause-sync)暂停了同步。

  • VerifyS:以本地节点为验证源的线上设备验证正在执行。

  • VerifyT:以本地节点为验证目标的线上设备验证正在执行。

测试MySQL数据同步

1. 将MySQL数据目录设置为DRBD挂载点

在my.cnf配置文件中修改设置:

datadir = /mnt/

2. 启动mysql服务

# 停止mysql服务
service mysql stop
# 将数据目录拷贝到挂载点
cp -r /data/* /mnt/
# 将数据目录的属主改为MySQL
chown -R mysql:mysql /mnt/
# 启动mysql服务
service mysql start

3. 建立数据库表

create database db1;
use db1;
create table t1 (a int);
insert into t1 select 1;
commit;

4. 手工执行主从切换,验证数据同步

(1)将node1降为从

service mysql stop
umount /mnt
drbdadm secondary mysql

(2)将node2升为主,并启动mysql服务

drbdadm primary mysql
mount /dev/drbd0 /mnt
chown -R mysql:mysql /mnt
service mysql start

(3)验证数据同步

mysql> select * from db1.t1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

可以看到数据已经同步,在node2上已经有了新建的库表数据。

heartbeat+DRBD+mysql高可用方案

前面的DRBD环境充其量只是一个容灾配置,还算不上高可用方案。设想当主节点的MySQL数据库出现问题时,需要人为发现故障,并手工执行主从切换,这个过程不可避免的长时间停止服务。要保证主服务器不间断服务,需要实现自动故障转移,与DRBD一起使用比较多的是Heartbeat。顾名思义,Heartbeat像是在主从两个DRBD之间接了一条心跳线,当从节点接收不到主节点的心跳时接管服务。Heartbeat双机热备软件来保证数据库服务的稳定性和连续性,数据一致性由DRBD来保证。默认情况下只有一台MySQL实例在工作,当主MySQL服务器出现问题后,系统将自动切换到备机上继续提供服务。这个方案的优点显而易见:安全性、稳定性、可用性高,出现故障自动切换;但缺点也彰明较著:只有一台服务器提供服务,成本相对较高,不方便扩展,可能会发生脑裂。

1. 配置

实验环境的架构如图2所示。

图2 DRBD+Heartbeat+MySQL 高可用架构

前面已经完成了DRBD+mysql的安装部署,下面配置heartbeat。heartbeat的安装参见“https://wxy0327.blog.csdn.net/article/details/81188814#%E4%BA%8C%E3%80%81%E5%AE%89%E8%A3%85Heartbeat”

(1)编辑配置文件ha.cf

node1上的ha.cf文件内容如下:

[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/ha.cf 
debugfile /var/log/ha-debug
logfile /var/log/ha-log
logfacility local0
keepalive 1
deadtime 30
warntime 10
initdead 120
udpport 694
bcast ens32
ucast ens32 172.16.1.126
auto_failback off
node node1
node node2
ping 172.16.1.254
respawn hacluster /usr/local/heartbeat/libexec/heartbeat/ipfail  
apiauth ipfail gid=haclient uid=hacluster
[root@node1 ~]#

节点2上的/usr/local/heartbeat/etc/ha.d/ha.cf文件只有一个配置项与节点1不同。

ucast ens32 172.16.1.125

(2)编辑认证文件authkeys

节点1与节点2上的authkeys文件相同,内容如下:

[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/authkeys
auth 1
1 crc

(3)编辑资源配置文件haresources

所有节点的haresources文件相同,内容如下:

[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/haresources
node1 IPaddr::172.16.1.101/24/ens32 drbddisk::mysql Filesystem::/dev/drbd0::/mnt::xfs mysql

node1:主节点的主机名。

IPaddr::172.16.1.101/24/ens32:用IPaddr脚本配置对外服务的浮动虚拟IP。

drbddisk::mysql:用drbddisk脚本实现DRBD主从节点资源组的挂载和卸载。该脚本文件为heartbeat自带,缺省安装在/etc/ha.d/resource.d/drbddisk。

Filesystem::/dev/drbd0::/mnt::xfs:用Filesystem脚本实现磁盘挂载和卸载。

mysql:MySQL启动脚本。

(4)建立插件软连接

在两个节点执行以下命令:

cd /usr/local/heartbeat/etc/ha.d
chmod 600 authkeys
ln -svf /usr/local/heartbeat/lib64/heartbeat/plugins/RAExec/* /usr/local/heartbeat/lib/heartbeat/plugins/RAExec/
ln -svf /usr/local/heartbeat/lib64/heartbeat/plugins/* /usr/local/heartbeat/lib/heartbeat/plugins/ 

(5)创建脚本文件

在两个节点的heartbeat资源目录下创建脚本文件:

创建drbddisk文件:

cp /etc/ha.d/resource.d/drbddisk /usr/local/heartbeat/etc/ha.d/resource.d/

创建mysql文件,内容如下:

[root@node1 ~]# more /usr/local/heartbeat/etc/ha.d/resource.d/mysql 
chown -R mysql:mysql /mnt/
service mysql start

创建MySQL服务检测脚本文件,内容如下:

[root@node1 ~]# more /home/mysql/mysql_check.sh 
#!/bin/bash
. /home/mysql/.bashrc

count=1

while true
do

mysql -uroot -p123456 -S /data/mysql.sock -e "show status;" > /dev/null 2>&1
i=$?
ps aux | grep mysqld | grep -v grep > /dev/null 2>&1
j=$?
if [ $i = 0 ] && [ $j = 0 ]
then
   sleep 3
else
   if [ $i = 1 ] && [ $j = 0 ]
   then
       sleep 3
   else
        if [ $count -gt 5 ]
        then
              break
        fi
   let count++
   continue
   fi
fi

done

/etc/init.d/heartbeat stop

(6)启动heartbeat

在两个节点上启动HeartBeat服务,先启动node1,再启动node2。

systemctl start heartbeat
systemctl enable heartbeat
systemctl status heartbeat

如下所示,此时VIP绑定在node1上:

客户端通过VIP可以正常访问MySQL:

C:\Users\wxy>mysql -h172.16.1.101 -uroot -p123456 -e "select * from db1.t1"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------+
| a    |
+------+
|    1 |
+------+

当启动heartbeat时同时启动ipfail来检测心跳,hacluster为启动heartbeat时的用户 ,也就是说ipfail和heartbeat都是用hacluster这个用户来运行。heartbeat和ipfail进程如下所示:

2. 测试

(1)停掉node1上的mysqld,查看服务是否切换到node2

# 首先启动mysql检测脚本,因为heartheat不检查服务的可用性,需要通过自定义脚本实现
nohup /home/mysql/mysql_check.sh &
# 停止mysqld
service mysql stop

node1的heartbeat进程停止,VIP和DRBD都切换到node2,客户端可以正常访问MySQL,自动切换成功。

(2)停掉node2的heartheat,查看服务是否切换回node1

# 先启动node1的heartheat
systemctl start heartbeat
# 停止node2的heartheat,也可以使用 iptables -I INPUT -p icmp -j DROP 禁用 ping
systemctl stop heartbeat

node2的heartbeat进程停止,VIP和DRBD都切换回node1,客户端可以正常访问MySQL,自动切换成功。

(3)node1重启,查看服务是否切换到node2

# 先启动node2的heartheat
systemctl start heartbeat
# node1重启
reboot

VIP和DRBD都切换到node2,客户端可以正常访问MySQL,自动切换成功。

(4)测试脑裂

# 停止node1的heartbeat服务
systemctl stop heartbeat

# 停止node2的heartbeat服务
systemctl stop heartbeat

# 在node1上添加防火墙策略,拒绝node2的广播包
iptables -A INPUT -i ens32 -p udp -s 172.16.1.126 --dport 694 -j DROP

# 在node2上添加防火墙策略,拒绝node1的广播包
iptables -A INPUT -i ens32 -p udp -s 172.16.1.125 --dport 694 -j DROP

# 启动node1的heartbeat服务
systemctl start heartbeat

# 启动node2的heartbeat服务
systemctl start heartbeat

在超过initdead定义的时间后,两个节点都绑定了同一个VIP,都挂载了DRDB盘,都启动了MySQL服务,都可以进行MySQL的读写。它们之间各自为政,不知道对方的存在,出现的脑裂。

由于两节点之间在指定的时间内,无法互相检测到对方心跳而各自启动故障转移功能,取得了资源以及服务的所有权,此时的两节点都还活着并作正常运行,这样会导致资源冲突,最严重的就是两台主机同时占用一个VIP的地址,当用户写入数据的时候可能会分别写入到两端,这样可能会导致两节点数据不一致或造成数据丢失,这种情况被称为裂脑。

一般来说,裂脑的发生,主要是由以下的几个原因导致的:

  • 节点对之间心跳线路故障,导致无法正常的通信。

  • 节点对上开启了防火墙阻挡了心跳消息的传输。

  • 节点对上的心跳网卡地址等信息配置的不正确,导致发送心跳失败。

  • 其它服务配置不当等原因,如心跳的方式不同,心跳广播冲突,软件出现了BUG等。

发生脑裂的时候,对业务的影响是及其严重的,有的时候甚至是致命的。如:两节点之间发生脑裂,导致互相竞争同一个IP资源,就如同我们局域网内常见的IP地址冲突一样,两个机器就会有一个或者两个不正常,影响用户正常访问服务器。如果是应用在数据库或者是存储服务这种极重要的高可用上,那就导致用户发布的数据间断的写在两台服务器上的恶果,最终导致数据难以恢复。

实际的生产环境中,我们可以从以下几个方面来防止裂脑的发生:

  • 同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个线路还是好的,依然能传送消息,这是最简单的一个方案,也是推荐的防脑裂方法。

  • 检测到裂脑的时候强行的关闭一个心跳节点(需要特殊的节点支持,如stonith,fence),相当于程序上备节点发现心跳线故障,发送关机命令到主节点。

  • 做好对裂脑的监控报警,如邮件以及手机短信等,在问题发生的时候能够人为的介入到仲裁,降低损失。当然,在实施高可用方案的时候,要根据业务的实际需求确定是否能够容忍这样的损失。对于一般的网站业务,这个损失是可控的。

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

  • 报警报在服务器接管之前,给人员处理留足够的时间就是1分钟内报警了,但是服务器不接管,而是5分钟之后接管,接管的时间较长。数据不会丢失,但就是会导致用户无法写数据。

  • 报警后,不直接自动服务器接管,而是由人员接管。

  • 增加仲裁的机制,确定谁该获得资源,这里面有几个参考的思路:增加一个仲裁机制。例如设置参考的IP,当心跳完全断开的时候,2个节点各自都ping一下参考的IP,不同则表明断点就出现在本段,这样就主动放弃竞争,让能够ping通参考IP的一端去接管服务。或者通过第三方软件仲裁谁该获得资源。

参考:

  • DRBD详解 及 DRBD+Mysql应用:https://www.cnblogs.com/chenghuan/articles/7531984.html

  • CentOS 7下DRBD数据同步部署:https://www.linuxidc.com/Linux/2017-12/149268.htm

  • heartbeat心跳检测和裂脑:https://blog.51cto.com/xxr007/1912518?utm_source=oschina-app

版权声明:本文为CSDN博主「wzy0623」加入原力计划的原创文章。

【成就一亿技术人】

即日起至12.24日,

CSDN协调更多流量给优秀原创作者!详情请戳下方二维码~~

年底了,给用心写技术文章的同学意思意思 

热 文 推 荐 

5G 是否有过度承诺之嫌?

☞3 天开发物联网应用!腾讯云 IoT 超级小程序来了

☞30 年间,软件开发行业为何 Bug 纷飞?

2019年区块链安全事件总结,全球损失超60亿美元 | 盘点

互联网诞生记: 浪成于微澜之间

GitHub宝藏项目标星1.6w+,编程新手有福了

马云穿布鞋演讲,任正非打的出行,盘点科技大佬们令人发指的节俭生活

点击阅读原文,即刻参加!

你点的每个“在看”,我都认真当成了喜欢

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐