实验环境:Centos 6.7_64位

服务器:

Master节点:dm1 IP地址:10.0.0.61(eth0) 192.168.3.150(eth1,心跳) 

Slave节点:dm2  Ip地址:10.0.0.62(eth0) 192.168.3.160(eth1,心跳)

VIP地址:192.168.0.180


一、DRBD环境搭建

DRBD(DistributedReplicatedBlockDevice)是一个基于块设备级别在远程服务器直接同步和镜像数据的软件,用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。它可以实现在网络中两台服务器之间基于块设备级别的实时镜像或同步复制(两台服务器都写入成功)/异步复制(本地服务器写入成功),相当于网络的RAID1,由于是基于块设备(磁盘,LVM逻辑卷),在文件系统的底层,所以数据复制要比cp命令更快,DRBD已经被MySQL官方写入文档手册作为推荐的高可用的方案之一。

DRBD工作原理:

提供两个大小相同的分区,在数据流的层次上构建一个磁盘镜像,就如同raid1,所以又被称为分布式raid

主从架构:primary/secondary
默认结构,两节点的所有存储属性,内容皆相同;
同一时刻只能有一个节点上线(即从节点,读写皆不可),主节点接到数据后,将数据备份到磁盘,同时传递给从节点,并存放到磁盘中.此时文件系统可以使用本地文件系统:ext2 ext3 xfs等

双主模型:
同一时刻可以有两个节点同时工作,即组内节点皆上线;
节点必须为集群文件系统,如:GFS2;OCFS2(本身提供高可用功能)
必须支持分布式文件锁(内核支持),主节点写入的时候,从节点就从文件锁得知对方在写入;
高可用集群的底层文件信息通道(必须将DRBD做成集群资源).

简言之:
Master/Master模式:
1、文件系统必须为集群文件系统如:GFS2;OCFS2(本身提供高可用功能)
2、使用高可用环境
3、使用分布式锁DLM

Master/Slave模式:
1、可以使用普通文件系统
2、可以切换主从角色
3、如果需要为高可用提供存储空间,需要将DRBD作为HA的一个资源
4、从节点不可读、不可写、不可挂载

因为drbd工作在内核,故需要用户空间工具提供规则,所以它由用户空间工具和内核模块组成,就如同iptables和LVS一样.drbd共有两 部分组成:内核模块和用户空间的管理工具。其中drbd内核模块代码已经整合进Linux内核2.6.33以后的版本中,因此,如果您的内核版本高于此版 本的话,你只需要安装管理工具即可;否则,您需要同时安装内核模块和管理工具两个软件包,并且此两者的版本号一定要保持对应。

不支持多个从,至少当前不支持

用户空间工具:

告知内核哪个分区是drbd设备

 drbdadm     /usr/local/drbd  /etc/drbd.d/

|__  drbdadm primary resource_name        升级为主节点

|__  drbdadm secondary resource_name    降级为备节点

drbdsetup

drbdmeta

查看drbd状态,有两种方法:

service  drbd  status

cat  /proc/drbd

工作模式:

DRBD有三种工作模式告知上层进程写入完成:A异步(异步的传输),B半同步(同步到内存),C同步(同步到对方的磁盘上)
A模式:主节点接到数据,只保证发送到本地网卡的数据缓冲区(性能最好),即数据一旦写入磁盘并发送到网络中就认为完成了写入操作。
B模式:主节点接到数据,保证数据发送到从节点缓冲区,且存到了从节点的内核区,但是是否数据存储到从节点的硬盘,则不清楚。即收到接收确认就认为完成了写入操作。
C模式:主节点接到数据,保证数据发送到从节点缓冲区,同时接到从节点存到从节点硬盘的信息(安全最高)。即收到写入确认就认为完成了写入操作。

简言之:
ProtocolA:异步,数据被送到TCP/IP协议缓冲区就宣布复制完成
ProtocolB:半同步,也称内存同步,数据发送到从节点的内存接收缓冲区
ProtocolC:同步,数据写到对方的磁盘

如何解决故障后自动切换

利用高可用的底层信息通道(如HA的heartbeat或者corosync)+pacemaker进行资源监控,将drbd定义为资源,且drbd资源有主从之分.

1. 添加附加库:

官方网站:http://elrepo.org/tiki/tiki-index.php

以下测试针对Centos 6.7 版本:

a)import public key:

#rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

b)安装库:

#rpm -Uvh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm

2. 安装DRBD:

DRBD官方网站:http://drbd.linbit.com/docs/install/

  # yum install drbd84 kmod-drbd84-y

3. 两台服务器上的分区/dev/sdb1作为drbd的网络mirror分区:

 格式化分区

# fdisk /dev/sdb

[root@dm1~]# fdisk -l /dev/sdb

Disk/dev/sdb: 10.7 GB, 10737418240 bytes

255heads, 63 sectors/track, 1305 cylinders

Units= cylinders of 16065 * 512 = 8225280 bytes

Sectorsize (logical/physical): 512 bytes / 512 bytes

I/Osize (minimum/optimal): 512 bytes / 512 bytes

Diskidentifier: 0xbe3466e3

   Device Boot      Start         End      Blocks  Id  System

/dev/sdb1               1         650    5221093+  83  Linux #存放数据

/dev/sdb2             651        1305    5261287+   5  Extended

/dev/sdb5             651        1305    5261256   83  Linux  #meta分区,存放drbd同步的状态信息

注意:

1>、meta分区一定不能格式化建立文件系统(sdb5存放drbd同步的状态信息)

2>、分好的分区不要进行挂载

3>、生产环境DRBD meta分区一般可设置为1-2G,数据分区看需求给最大

4>、在生产环境中两块硬盘一样大

# mkfs.ext4 /dev/sdb1  #只在主机上做

4.开始配置drbd:

# modprobe drbd

注意:不要设置echo'modprobe drbd' >>/etc/rc.loca开机自动加载drbd模块,如果drbd服务是开机自启动的,会先启动drbd服务在加载drbd的顺序,导致drbd启动不了出现的问题.

主备节点两端配置文件完全一致

[root@dm1~]# vi /etc/d

dbus-1/        depmod.d/      dracut.conf    drbd.conf

default/       dhcp/          dracut.conf.d/ drbd.d/

[root@dm1 ~]# cat /etc/drbd.conf

# Youcan find an example in /usr/share/doc/drbd.../drbd.conf.example

 

include"drbd.d/global_common.conf";

include"drbd.d/*.res";

[root@dm1 ~]# vi /etc/drbd.d/mysql.res

#设定资源名称为: mysql_data

resource  mysql_data {

            protocol C;

            net {

                 cram-hmac-alg sha1;

                 shared-secret "abc";

            }

            on dm1 {

                 device    /dev/drbd1;

                 disk      /dev/sdb1;   #挂载drbd对应的系统分区

                 address   10.0.0.61:7788;

                 meta-disk /dev/sdb5 [0];

            }

            on dm2 {

                 device    /dev/drbd1;

                 disk      /dev/sdb1;

                 address   10.0.0.62:7788;

                 meta-disk /dev/sdb5 [0];

            }

}

5.初始化meta分区:

[root@dm1 ~]# drbdadm create-md mysql_data

initializing activity log

NOT initializing bitmap

Writing meta data...

New drbd meta data block successfully created.

Success

6. 启动drbd:

[root@dm1 ~]# /etc/init.d/drbd start

[root@dm1 ~]# chkconfig drbd off

7.初始化设备同步(覆盖备节点,保持数据一致):

[root@dm1 ~]# drbdadm -- --overwrite-data-of-peer primary mysql_data  #只在主服务器上操作

8. 挂载drbd分区到data数据目录:

[root@dm1 ~]# df -h

Filesystem      Size  Used Avail Use% Mounted on

/dev/sda3        14G  1.5G  12G  12% /

tmpfs           238M     0 238M   0% /dev/shm

/dev/sda1       190M   52M 129M  29% /boot

[root@dm1 ~]# mkdir /data

[root@dm1 ~]# drbdadm primary all

[root@dm1 ~]# mount /dev/drbd1 /data

[root@dm1 ~]# df -h

Filesystem      Size  Used Avail Use% Mounted on

/dev/sda3        14G  1.5G  12G  12% /

tmpfs           238M     0 238M   0% /dev/shm

/dev/sda1       190M   52M 129M  29% /boot

/dev/drbd1      4.8G   10M 4.6G   1% /data

说明:/data目录为数据库的数据目录

9. 测试DRBD:

正常状态

[root@dm1 ~]# cat /proc/drbd

version: 8.4.7-1 (api:1/proto:86-101)

GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build bymockbuild@Build64R6, 2016-01-12 13:27:11

 1: cs:SyncSourcero:Primary/Secondary ds:UpToDate/Inconsistent C r-----

    ns:4701184 nr:0 dw:0 dr:4701843al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:519912

        [=================>..]sync'ed: 90.2% (504/5096)M

        finish: 0:00:12 speed:42,268 (32,872) K/sec

[root@dm2 ~]# cat /proc/drbd

version: 8.4.7-1 (api:1/proto:86-101)

GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build bymockbuild@Build64R6, 2016-01-12 13:27:11

 1: cs:SyncTargetro:Secondary/Primary ds:Inconsistent/UpToDate C r-----

    ns:0 nr:309640 dw:309640 dr:0al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:4911456

        [>...................]sync'ed:  93.20% (4796/5096)M

        finish: 0:05:37 speed:14,552 (11,056) want: 21,240 K/sec

说明:dm1为主节点,dm2为备节点

模拟dm1宕机:

[root@dm1 ~]# umount /dev/drbd1

[root@dm1 ~]# drbdadm down all

[root@dm2 ~]# cat /proc/drbd     

version: 8.4.7-1 (api:1/proto:86-101)

GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build bymockbuild@Build64R6, 2016-01-12 13:27:11

 1: cs:WFConnectionro:Secondary/Unknown ds:UpToDate/DUnknown C r-----

   ns:0 nr:5221101 dw:5221101 dr:0al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

[root@dm2 ~]# mkdir /data

[root@dm2 ~]# drbdadmprimary all

[root@dm2 ~]# mount/dev/drbd1 /data

[root@dm2 ~]# df -h

Filesystem     Size  Used Avail Use% Mounted on

/dev/sda3       14G  1.5G   12G 12% /

tmpfs          238M     0  238M  0% /dev/shm

/dev/sda1      190M   52M  129M 29% /boot

/dev/drbd1     4.8G   10M  4.6G  1% /data

说明:dm1宕机后,dm2可以升级为主节点,可挂载drbd分区继续使用


二、Heartbeat环境搭建

官方站点:http://linux-ha.org/wiki/Main_Page

heartbeat可以资源(VIP地址及程序服务)从一台有故障的服务器快速的转移到另一台正常的服务器提供服务,heartbeat和keepalived相似,heartbeat可以实现failover功能,但不能实现对后端的健康检查

heartbeat和keepalived应用场景及区别:

很多网友说为什么不使用keepalived而使用长期不更新的heartbeat,下面说一下它们之间的应用场景及区别

1、对于web,db,负载均衡(lvs,haproxy,nginx)等,heartbeat和keepalived都可以实现

2、lvs最好和keepalived结合,因为keepalived最初就是为lvs产生的,(heartbeat没有对RS的健康检查功能,heartbeat可以通过ldircetord来进行健康检查的功能)

3、mysql双主多从,NFS/MFS存储,他们的特点是需要数据同步,这样的业务最好使用heartbeat,因为heartbeat有自带的drbd脚本

总结:无数据同步的应用程序高可用可选择keepalived,有数据同步的应用程序高可用可选择heartbeat

# rpm-ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

Heartbeat具体的安装配置:http://linuxzkq.blog.51cto.com/9379412/1771152

以下仅提供配置文件供参考:

vi authkeys #打开下面两项:一共有三种认证方式供选择,第一种是CRC循环冗余校验,第二种是SHA1哈希算法,第三种是MD3哈希算法,其中他们的密码可以任意设置,但是两边密码必须保持一致。  

auth 3 

3 md5 Hello!

chmod 600 authkeys  #给认证文件授权为600

[root@dm1 ha.d]# cat ha.cf

debugfile/var/log/ha-debug

logfile/var/log/ha-log

logfacility     local0

keepalive 2

deadtime 30

warntime 10

initdead 120

udpport 694

ucast eth1 192.168.3.160

auto_failback  off

node    dm1

node    dm2

ping 10.0.0.254

respawn hacluster  /usr/lib64/heartbeat/ipfail

[root@dm2 ha.d]# cat ha.cf

debugfile/var/log/ha-debug

logfile/var/log/ha-log

logfacility     local0

keepalive 2

deadtime 30

warntime 10

initdead 120

udpport 694

ucast eth1 192.168.3.150

auto_failback  off

node    dm1

node    dm2

ping 10.0.0.254

respawn  hacluster  /usr/lib64/heartbeat/ipfail

[root@dm1 ha.d]# vi haresources

#dm1IPaddr::192.168.0.180/32/eth0 drbddisk::mysql_dataFilesystem::/dev/drbd1::/data::ext4 mysqld

dm1 IPaddr::192.168.0.180/32/eth0drbd_primary

说明:

drbddisk::data   <==启动drbd data资源,相当于执行/etc/ha.d/resource.d/drbddiskdata stop/start操作

Filesystem::/dev/drbd1::/data::ext3  <==drbd分区挂载到/data目录,相当于执行/etc/ha.d/resource.d/Filesystem/dev/drbd1 /data ext3 stop/start <==相当于系统中执行mount  /dev/drbd1  /data

mysql  <==启动mysql服务脚本,相当于/etc/init.d/mysql stop/start

资源切换脚本:

drbd_primary  resource-group用来指定需要Heartbeat托管的服务,也就是这些 服务可以由Heartbeat来启动和关闭。如果要托管这些服务,就必须将服务写成可以通过start/stop来启动和关闭的脚步,然后放到/etc /init.d/或者/etc/ha.d/resource.d/目录下,Heartbeat会根据脚本的名称自动去/etc/init.d或者/etc /ha.d/resource.d/目录下找到相应脚步进行启动或关闭操作。

本脚本复制drbd的切换,已经mysql服务的启动和关闭:

[root@dm1 ~]# cat drbd_primary 
#!/bin/sh
case "$1" in
start)
    drbdadm primary mysql_data
    mount /dev/drbd1 /data
   /etc/init.d/mysqld start
;;
stop)
   /etc/init.d/mysqld stop
   umount /dev/drbd1
   drbdadm secondary mysql_data
;;
esac
exit 0

启动heartbeat:

# /etc/init.d/heartbeatstart

# chkconfig heartbeat off

说明:关闭开机自启动,当服务器重启时,需要人工去启动

heartbeat的管理:

    配置好heartbeat之后,需要将mysql从自启动服务器中去掉,因为主heartbeat启动的时候会挂载drdb文件系统以及启动 mysql,切换的时候会将主上的mysql停止并卸载文件系统,从上会挂载文件系统,并启动mysql。因此需要做如下操作(两台服务器):

# chkconfig mysqld off

# chkconfig heartbeat off

# chkconfig drbd off     

#!/bin/sh

#

# This script will be executed *after* all the other  init scripts.

# You can put your own initialization stuff in here if  you don't

# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

modprobe drbd  #必须先加载模块,这也是因为将启动命令放在这里的原因

/etc/init.d/drbd start 

/etc/init.d/heartbeat start


三、 MySQL安装部署

注意:两台数据库都安装mysql服务,dm2只安装到make install即可,mysqld服务不要设置为开机自启动

二进制安装:

[root@dm1 ~]# tar xfmysql-5.5.49-linux2.6-x86_64.tar.gz

[root@dm1 ~]# groupadd mysql

[root@dm1 ~]# useradd -g mysql -M -s/sbin/nologin mysql

[root@dm1 ~]# mv mysql-5.5.49-linux2.6-x86_64/usr/local/mysql-5.5.49

[root@dm1 ~]# echo'PATH=/usr/local/mysql/bin:$PATH' >>/etc/profile     

[root@dm1 ~]# source /etc/profile

[root@dm1 ~]# drbdadm up all

[root@dm1 ~]# drbdadm primary all

[root@dm1 ~]# mount /dev/drbd1 /data

说明:数据库存放数据的目录是drbd分区

[root@dm1~]# df -h

Filesystem      Size Used Avail Use% Mounted on

/dev/sda3        14G 2.5G   11G  19% /

tmpfs           238M     0 238M   0% /dev/shm

/dev/sda1       190M  52M  129M  29% /boot

/dev/drbd1      4.8G  10M  4.6G   1% /data

[root@dm1~]# chown -R mysql:mysql /data

[root@dm1~]# chown -R mysql.mysql /usr/local/mysql-5.5.49

[root@dm1~]# ln -s /usr/local/mysql-5.5.49/ /usr/local/mysql

[root@dm1~]#  cd /usr/local/mysql

[root@dm1mysql]# cp support-files/mysql.server /etc/init.d/mysqld

[root@dm1mysql]# sed –i 's#datadir=#datadir=/data#g' /etc/init.d/mysqld

说明:修改mysql启动脚本,指定数据库的目录为/data

[root@dm1mysql]# sed -i 's#basedir=#basedir=/usr/local/mysql#g' /etc/init.d/mysqld

[root@dm1mysql]# ./scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/data --user=mysql

[root@dm1mysql]# cp support-files/my-huge.cnf /etc/my.cnf

[root@dm1mysql]# /etc/init.d/mysqld start

StartingMySQL.. SUCCESS!

[root@dm1mysql]# netstat -tunlp|grep 3306

tcp        0     0 0.0.0.0:3306               0.0.0.0:*                   LISTEN      14838/mysqld       

[root@dm1mysql]# chkconfig mysqld off

[root@dm1~]# mysql -uroot -e "show databases;"

mysql:Unknown OS character set 'GB18030'. #服务端的字符集得设置下

mysql:Switching to the default character set 'latin1'.

+--------------------+

|Database           |

+--------------------+

|information_schema |

|mysql              |

|performance_schema |

|test               |

+--------------------+

通过my.cnf文件增加
两个参数:
1.在[mysqld]下添加
default-character-set=utf8(mysql 5.5 版本添加character-set-server=utf8)
2.在[client]下添加
default-character-set=utf8
   这样我们建数据库建表的时候就不用特别指定utf8的字符集了。配置文件里的这种写法解决了数据存储和比较的问题,但是对客户端的连接是没有作用的,客户端这时候一般需要指定utf8方式连接才能避免乱码。也就是传说总的set names命令。事实上,set names utf8命令对应的是服务器端以下几个命令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
  但这三个参数是不能写在配置文件my.cnf里的。只能通过set命令来动态修改。我们需要的是在配置文件里写好一劳永逸的办法。那么这时候,是否有在服务端解决问题的办法呢,可行的思路是在init_connect里设置。这个命令在每个普通用户连接上来的时候都会触发执行,可以在[mysqld]部分增加以下一行设置连接字符集:
在[mysqld]下添加:
init_connect = 'SET NAMES utf8'
总结:
1、首选在编译安装MySQL的时候指定两个参数使用utf8编码。
2、次选在配置文件my.cnf或my.ini设定两个参数,同时设置init_connect参数。
3、第三在配置文件my.cnf或my.ini设定两个参数,同时客户端的连接指定set names命令。
4、在配置文件my.cnf里的client和server处加入default-character-set参数方便管理。

[root@dm1~]# mysql -uroot -e "show databases;"

+--------------------+

|Database           |

+--------------------+

|information_schema |

|mysql              |

|performance_schema |

|test               |

+--------------------+

[root@dm1~]# mysql -uroot -e "show variables like '%char%';"

+--------------------------+-----------------------------------------+

|Variable_name            | Value                                   |

+--------------------------+-----------------------------------------+

|character_set_client     | utf8                                    |

|character_set_connection| utf8                                   |

|character_set_database   | utf8                                    |

|character_set_filesystem| binary                                 |

|character_set_results    | utf8                                    |

|character_set_server     | utf8                                    |

|character_set_system     | utf8                                    |

|character_sets_dir      | /usr/local/mysql-5.5.49/share/charsets/|

+--------------------------+---------------------------------------+

 

[[email protected]]# /etc/init.d/heartbeat start

[root@dm1~]# ip a|grep eth0

eth0: mtu 1500 qdisc pfifo_fast state UP qlen1000

    link/ether 00:0c:29:92:b5:37 brdff:ff:ff:ff:ff:ff

    inet 10.0.0.61/24 brd 10.0.0.255 scopeglobal eth0

    inet 192.168.0.180/32 scope global eth0

    inet6 fe80::20c:29ff:fe92:b537/64 scope link

       valid_lft forever preferred_lft forever

[root@dm1~]# netstat -tunlp

Active Internet connections(only servers)

Proto Recv-Q Send-Q LocalAddress               ForeignAddress             State       PID/Program name  

tcp        0     0 0.0.0.0:3306               0.0.0.0:*                   LISTEN      29981/mysqld       

tcp        0     0 10.0.0.61:7788              0.0.0.0:*                   LISTEN      -                  

tcp        0     0 0.0.0.0:52668              0.0.0.0:*                   LISTEN      1048/sshd          

tcp        0     0 :::52668                   :::*                        LISTEN      1048/sshd          

udp        0     0 0.0.0.0:694                0.0.0.0:*                              29218/heartbeat: wr

udp        0     0 0.0.0.0:55111              0.0.0.0:*                              29218/heartbeat: wr

[root@dm1~]# df -h        

Filesystem      Size Used Avail Use% Mounted on

/dev/sda3        14G 2.5G   11G  20% /

tmpfs           238M     0 238M   0% /dev/shm

/dev/sda1       190M  52M  129M  29% /boot

/dev/drbd1      4.8G  40M  4.5G   1% /data

 

[root@dm2 ha.d]# ln -s /usr/local/mysql-5.5.49/ /usr/local/mysql

[root@dm2 ha.d]# chown -R mysql.mysql /usr/local/mysql-5.5.49

[root@dm2 ha.d]# chown -R mysql:mysql /data

[root@dm2 ha.d]# cd /usr/local/mysql

[root@dm2 mysql]# cp support-files/mysql.server /etc/init.d/mysqld

[root@dm2 mysql]# sed –i 's#datadir=#datadir=/data#g' /etc/init.d/mysqld

说明:修改mysql启动脚本,指定数据库的目录为/data

[root@dm2 mysql]# sed -i 's#basedir=#basedir=/usr/local/mysql#g' /etc/init.d/mysqld

[root@dm2 mysql]# ./scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/data --user=mysql

[root@dm2 mysql]# cp support-files/my-huge.cnf /etc/my.cnf

注意:同上dm1,#dm2服务端的字符集得设置下,dm2的mysql服务不用启动,由heartbeat接管时来启动!

[root@dm2~]# modprobe drbd

[root@dm2~]# lsmod | grepdrbd

[root@dm2~]# drbdadm create-md mysql_data

[root@dm2~]# /etc/init.d/drbd start

[root@dm2~]# /etc/init.d/heartbeat start

[root@dm2~]# netstat -tunlp

Active Internet connections(only servers)

Proto Recv-Q Send-Q LocalAddress               ForeignAddress             State       PID/Program name  

tcp        0     0 0.0.0.0:52668              0.0.0.0:*                   LISTEN      1126/sshd          

tcp        0     0 :::52668                    :::*                        LISTEN      1126/sshd          

udp        0     0 0.0.0.0:694                0.0.0.0:*                              3344/heartbeat: wri

udp  0  00.0.0.0:22105   0.0.0.0:*                               3344/heartbeat:wri

 

先看看两台服务器的状态:

[root@dm1~]# df -hT

Filesystem     Type  Size  Used Avail Use% Mounted on

/dev/sda3      ext4   14G  2.5G   11G 20% /

tmpfs          tmpfs 238M     0  238M  0% /dev/shm

/dev/sda1      ext4  190M   52M  129M 29% /boot

/dev/drbd1     ext4  4.8G   40M  4.5G  1% /data

[root@dm2~]# df -hT

Filesystem     Type  Size  Used Avail Use% Mounted on

/dev/sda3      ext4   14G  2.5G   11G 20% /

tmpfs          tmpfs 238M     0  238M  0% /dev/shm

/dev/sda1      ext4  190M   52M  129M 29% /boot

#可以看见挂载在第一台服务器。

 

四、故障切换测试

测试方法:

1.停掉dm1上的mysqld,看看是否切换(因为heartheat不检查服务的可用性,因此需要通过额外的脚本来实现)。
2.停掉dm1的heartheat看看是否能正常切换。
3.停掉dm1的网络或者直接将dm1系统shutdown,看看能否正常切换。
4.启动dm1的heartbeat看看是否能正常切换回来。
5.重新启动dm1看看能否切换,过程是否OK。
注意:这里说的切换是指是不是已经将mysql停掉、是否卸载了文件系统等等。

我就停止dm1(10.0.0.61)上的heartbeat来测试是否会自动切换,这里除了第一条无法实现,其他的都可以切换:

对主Primary/Secondary模型的drbd服务来讲,在某个时刻[只能有一个节点为Primary],因此,要切换两个节点的角色,只能在先将原有的Primary节点设置为Secondary后,才能将原来的Secondary节点设置为Primary。

dm1:

[root@dm1~]# /etc/init.d/heartbeat stop

Stopping High-Availabilityservices: Done.

[root@dm1~]# ip a|grep eth0

eth0: mtu 1500 qdisc pfifo_fast state UP qlen1000

    link/ether 00:0c:29:92:b5:37 brdff:ff:ff:ff:ff:ff

    inet 10.0.0.61/24 brd 10.0.0.255 scopeglobal eth0

    inet6 fe80::20c:29ff:fe92:b537/64 scopelink

       valid_lft forever preferred_lft forever

 [root@dm1 ~]# df -hT

Filesystem     Type  Size  Used Avail Use% Mounted on

/dev/sda3      ext4   14G  2.5G   11G 20% /

tmpfs          tmpfs 238M     0  238M  0% /dev/shm

/dev/sda1      ext4  190M   52M  129M 29% /boot

 [root@dm1 ~]# netstat -tunlp

Active Internet connections(only servers)

Proto Recv-Q Send-Q LocalAddress               ForeignAddress             State       PID/Program name  

tcp        0     0 0.0.0.0:52668               0.0.0.0:*                   LISTEN      1126/sshd          

tcp        0     0 :::52668                   :::*                        LISTEN      1126/sshd    

[root@dm1 ~]# cat /proc/drbd

version: 8.4.7-1(api:1/proto:86-101)

GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49build by mockbuild@Build64R6, 2016-01-12 13:27:11

 

 1: cs:Connected ro:Secondary/Primaryds:UpToDate/UpToDate C r-----

ns:5221557 nr:316 dw:780 dr:5227792 al:16 bm:0 lo:0 pe:0 ua:0ap:0 ep:1 wo:f oos:0

dm2:

[root@dm2~]# df -hT

Filesystem     Type  Size  Used Avail Use% Mounted on

/dev/sda3      ext4   14G  2.5G   11G 20% /

tmpfs          tmpfs 238M     0  238M  0% /dev/shm

/dev/sda1      ext4  190M   52M  129M 29% /boot

/dev/drbd1     ext4  4.8G   40M  4.5G  1% /data

[root@dm2~]# netstat -tunlp

Active Internet connections(only servers)

Proto Recv-Q Send-Q LocalAddress               ForeignAddress             State       PID/Program name  

tcp        0     0 0.0.0.0:3306               0.0.0.0:*                   LISTEN      4113/mysqld        

tcp        0     0 0.0.0.0:52668              0.0.0.0:*                   LISTEN      1126/sshd          

tcp        0     0 :::52668                   :::*                        LISTEN      1126/sshd          

udp        0     0 0.0.0.0:694                0.0.0.0:*                              3344/heartbeat: wri

udp        0     0 0.0.0.0:22105              0.0.0.0:*                              3344/heartbeat: wri

[root@dm2~]# ip a|grep eth0

eth0: mtu 1500 qdisc pfifo_fast state UP qlen1000

    link/ether 00:0c:29:5b:bc:19 brdff:ff:ff:ff:ff:ff

    inet 10.0.0.62/24 brd 10.0.0.255 scopeglobal eth0

    inet 192.168.0.180/32 scope global eth0

    inet6 fe80::20c:29ff:fe5b:bc19/64 scopelink

       valid_lft forever preferred_lft forever

[root@dm2~]# cat /proc/drbd        

version: 8.4.7-1(api:1/proto:86-101)

GIT-hash:3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6,2016-01-12 13:27:11

 

 1: cs:Connected ro:Primary/Secondaryds:UpToDate/UpToDate C r-----

ns:316 nr:5221557 dw:5221873 dr:6036 al:14 bm:0 lo:0 pe:0 ua:0ap:0 ep:1 wo:f oos:0

对于mysqld服务挂掉的情况无法实现自动切换,需要一个脚本来帮助我们完成。

 

五、可能存在的问题

报错1:
问题描述:设备被其他人占用,无法停止或者下线资源
0: State change failed: (-12) Device is held open by someone
解决办法:查看是否有设备挂载,umount即可
报错2:
问题描述:0:mydrbd WFConnection Primary/UnknownUpToDate/DUnknown C r—–,即总有一个节点是未知状态
解决办法:
主节点上执行:
drbdadm connect all(all可以换成自己定义的DRBD资源名称)
从节点上执行:
drbdadm -- --discard-my-data connect all

报错3:
configure: error: Cannot build utils without flex, either install flex or passthe –without-utils option.
解决办法:
yum -y intalls flex
报错4:
make: [check-kdir] error 1
解决办法:yum install -y kernel-devel
报错5:
SORRY, kernel makefile not found.
You need to tell me a correct KDIR,
Or install the neccessary kernel source packages.
报错6:
‘drbd’ not defined in your config (for this host).
这个因为没有加载到drbd模块
报错7:
启动报错:
Command ‘drbdmeta 0 v08 /dev/sdb1 internal create-md’ terminated with exit code40
这是因为sdb1已经有文件系统了,已经有数据存在了
解决方法:
[root@node1 ~]# dd  if=/dev/zero bs=1M count=1 of=/dev/sdb1


总结

   搭建还不算复杂,但是也踩了不少坑,比如yum安装的heartbeat没有drbddisk脚本。该方案的优点是安全性高、稳定性高、可用性高,出现故障自动切换,但是缺点也很明显,只有一台服务器提供服务,成本相对较高。不方便扩展。可能会发生脑裂。当mysql服务挂掉或者不可用的情况下不能进行自动切换,需要通过crm模式实现或者额外的脚本实现(比如shell脚本监测到master的mysql不可用就将主上的heartbeat停掉, 这样就会切换到backup中去)。监控也特别重要,可以使用nagios或者zabbix监控。


高可用脑裂问题及解决方案

(1)、导致裂脑发生的原因

1、高可用服务器之间心跳链路故障,导致无法相互检查心跳

2、高可用服务器上开启了防火墙,阻挡了心跳检测

3、高可用服务器上网卡地址等信息配置不正常,导致发送心跳失败

4、其他服务配置不当等原因,如心跳方式不同,心跳广播冲突,软件BUG等

(2)、防止裂脑一些方案

1、加冗余线路

2、检测到裂脑时,强行关闭心跳检测(远程关闭主节点,控制电源的电路fence)

3、做好脑裂的监控报警

4、报警后,备节点在接管时设置比较长的时间去接管,给运维人员足够的时间去处理(人为处理)

5、启动磁盘锁,正在服务的一方锁住磁盘,裂脑发生时,让对方完全抢不走"共享磁盘资源"

磁盘锁存在的问题:

使用锁磁盘会有死锁的问题,如果占用共享磁盘的一方不主动"解锁"另一方就永远得不到共享磁盘,假如服务器节点突然死机或崩溃,就不可能执行解锁命令,备节点也就无法接管资源和服务了,有人在HA中设计了智能锁,正在提供服务的一方只在发现心跳全部断开时才会启用磁盘锁,平时就不上锁

DRDB各种状态查看:

查看资源的连接状态

# drbdadm cstate mysql_data
Connected
资源的连接状态;一个资源可能有以下连接状态中的一种
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:以本地节点为验证目标的线上设备验证正在执行

查看资源角色的命令

# drbdadm role mysql_data
Primary/Secondary (在前面为当前节点)
Parimary 主:资源目前为主,并且可能正在被读取或写入,如果不是双主只会出现在两个节点中的其中一个节点上
Secondary 次:资源目前为次,正常接收对等节点的更新
Unknown 未知:资源角色目前未知,本地的资源不会出现这种状态

查看硬盘状态

# drbdadm dstate mysql_data
UpToDate/UpToDate
本地和对等节点的硬盘有可能为下列状态之一:
Diskless  无盘:本地没有块设备分配给DRBD使用,这表示没有可用的设备,或者使用drbdadm命令手工分离或是底层的I/O错误导致自动分离
Attaching:读取无数据时候的瞬间状态
Failed  失败:本地块设备报告I/O错误的下一个状态,其下一个状态为Diskless 无盘
Negotiating:在已经连接的DRBD设置进行Attach读取无数据前的瞬间状态
Inconsistent:数据是不一致的,在两个节点上(初始的完全同步前)这种状态出现后立即创建一个新的资源。此外,在同步期间(同步目标)在一个节点上出现这种状态
Outdated:数据资源是一致的,但是已经过时
DUnknown:当对等节点网络连接不可用时出现这种状态
Consistent:一个没有连接的节点数据一致,当建立连接时,它决定数据是UpToDate或是Outdated
UpToDate:一致的最新的数据状态,这个状态为正常状态


查看同步进度

# cat /proc/drbd 或者 执行/usr/local/drbd/sbin/drbd-overview或者 service drbd status
version: 8.4.3 (api:1/proto:86-101)
GIT-hash: 89a294209144b68adb3ee85a73221f964d3ee515 build [email protected], 2016-04-24 20:16:24
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r—–
ns:2767088 nr:0 dw:0 dr:2774680 al:0 bm:168 lo:0 pe:1 ua:7 ap:0 ep:1 wo:foos:18202972
[=>………………] sync’ed: 13.3% (17776/20476)M
finish: 0:12:59 speed: 23,344 (22,492) K/sec
由此可见:进度已经完成了13.3%,传输速度大概22M/S
注:
ds  是磁盘状态信息
dw 是磁盘写信息
dr  是磁盘读信息

cat /proc/drbd 、/usr/local/drbd/sbin/drbd-overview或者 service drbd status执行后显示的信息格式会有所不同

注意点:

1)mount drbd设备以前必须把设备切换到primary状态。
2)两个节点中,同一时刻只能有一台处于primary状态,另一台处于secondary状态。
3)处于secondary状态的服务器上不能加载drbd设备。
4)主备服务器同步的两个分区大小最好相同,这样不至于浪费磁盘空间,因为drbd磁盘镜像相当于网络raid1。


参考资料:

三木的人生——3mu.me

http://shineforever.blog.51cto.com/1429204/1633519

http://oldboy.blog.51cto.com/2561410/1240412

http://oldboy.blog.51cto.com/2561410/515345