MySQL+heartbeat+DRBD+LVS高可用集群搭建

1.简介

MySQL+heartbeat+DRBD+LVS是一套成熟的集群解决方案,通过heartbeat+DRBD完成MySQL的主节点写操作的高可用性,而通过MySQL+LVS实现MySQL数据库主从复制和MySQL读操作的负载均衡。整个方案在读写方面进行分离,融合写操作的高可用和读操作的负载均衡,是一个完美又廉价的企业应用解决方案。

mysql高可用性解决方案:

1.mysql的复制功能90.000%

2.mysql的复制功能+集群软件 95.000%

3.mysql+heartbeat+DRBD 99.900%

4.共享存储+mysql的复制功能 99.990%

5.mysql cluster的标准版和电信版 99.999%

2.heartbeat+DRBD高可用性实现原理

DRBD的英文全程为DistributedReplicated Block Device(分布式块设备复制),是Linux内核的存储层的一个分布式存储系统,可利用DRBD在两台Linux服务器之间共享块设备、文件系统和数据,类似于一个网络RAID1的功能。DRBD的架构如图所示。

wKioL1ZKeIHwSTRWAAF0khIkiGk136.jpg

当将数据写入到本地主节点的文件系统时,这些数据会通过网络发送到另一台主节点上,本地主节点和远程主节点数据通过TCP/IP协议保持同步,主节点故障时,远程节点保存着相同的数据库,可以接替主节点继续提供数据,两个节点之间使用heartbeat来检测对方是否存活。

同步过程如下:

1)在NODE1上写操作被提交时,然后通过内核传给DRBD模块。

2)DRBD发送写操作到NODE2

3)在NODE2上的DRBD发送写操作给本地磁盘。

4)在NODE2上的DRBD向NODE1发确认信息,确认已经收到写操作并发送给本地磁盘。

5)在NODE1上的DRBD发送写操作给本地磁盘。

6)在NODE1的内核回应写操作完成。

此同步过程还依赖于DRBD的3种同步协议:

Protocol A,写I/O到达本地磁盘和本地的TCP发送缓存区之后,返回操作成功。

Protocol B,写I/O到达本地磁盘和远程节点的缓存区之后,返回操作成功。

Protocol C,写I/O到达本地磁盘和远程节点的磁盘之后,返回操作成功。


3.MySQL高可用性集群部署

企业级MySQL集群具备高可用性、可扩展、易管理、低成本的特点,通常采用MySQL读写分离的办法,而读写之间的数据同步采用MySQL的单向或双向复制技术实现。MySQL写操作一般采用heartbeat+DRBD+MySQL搭建高可用集群的方案,而读操作普遍采用keepalived搭建高可用可扩展集群的方案。

3.1集群规划

一个MySQL集群中主机的IP地址信息及用途:

主机名     IP地址             用途

dbm133     172.19.19.133    Heartbeat+DRBD+MySQL的primary节点

dbm134     172.19.19.134    Heartbeat+DRBD+MySQL的secondary节点

dbs135     172.19.19.135    slave(master_host=172.19.19.222)

dbs136     172.19.19.136    slave(master_host=172.19.19.222)

dbs137     172.19.19.137    slave(master_host=172.19.19.222)

LVS1        172.19.19.144    LVS+keepalived

LVS2        172.19.19.145    LVS+keepalived

heartbeat+DRBD方案中的IP信息

heartbeat使用的VIP   heartbeat的主备节点

172.19.19.222         172.19.19.133

                         172.19.19.134


LVS+keepalived上的VIP和realserverIP信息

VIP                      realserver

172.19.19.223         172.19.19.135

                         172.19.19.136

                         172.19.19.137

wKiom1ZKfJiwSDImAAKAt2aRC3E608.jpg

3.2配置之前的准备

3.2.1设置hostname及解析

首先要给需要配置DRBD的两台主机配置hostname,设置之后通过uname �Ca检查是否成功,建议不要将hostname设置成全称域名(例如,dbm133.example.com、dbm134.example.com),设置短标识比较好(例如,dbm133、dbm134),因为这个短标识在以后的配置中会用到,较短的标识可以减少后期配置的复杂度,并避免出现问题。同时要求这两台主机的hostname能分别解析到两台机器的内网IP(即两台主机互相通信时使用的网络地址)。

编辑/etc/hosts文件,添加如下内容:

172.19.19.133    dbm133

172.19.19.134    dbm134

3.2.2磁盘分区规划

根据当前DB文件的大小及后期的增长划分出一个分区,用于存放所有可变数据文件,例如。整个MySQL的datadir目录、binlog文件、relaylog文件、my.cnf文件,还包括所有表的ibd文件(单独表空间)、ibdata文件和id_logfile文件。两台主机节点分区最好大小一样,至少要保证secondray节点分区尺寸大雨primary节点分区尺寸,以避免后期因空间不足而出现难以预见的问题。

3.2.3熟悉网络环境

确定利用DRBD进行同步的网络状况是够良好。DRBD同步操作对网络环境要求很高,特别是在写入数据量特别大、需要同步的数据很多时尤为重要。网络环境越好,同步的速度越快。可以考虑把DB对外提供服务的网络和DRBD网络同步分开,这样可以使业务对DB的访问请求和DRBD同步互不影响,但也会带来一些成本的增加。规划两台主机之间的心跳线为两根以上,这样能保证不会因为某一线路故障而产生的切换工作。在高可用性方案中,一般要求用三个以上的心跳线进行心跳检测,以此来减少误切换和“脑裂”问题,同时要确认上层交换机是够禁止ARP广播。

3.3DRBD部署

从官方网站下载源码包来编译或者直接使用yum来安装。

通过yum来安装

[root@dbm133 ~] yum install kmod-drbd84drbd84

检查是否安装成功

[root@dbm133 ~] modprode �Cl|grep -i drbd

[root@dbm133 ~] lsmod |grep �CI drbd

安装完成之后,在/sbin目录下有drbdadm、drdbmeta、drbdsetup命令,以及/etc/init.d/drbd启动脚本。

3.3.1DRBD配置

3.3.1.1DRBD使用的磁盘分区

使用尺寸相同的单独分区,同时考虑DB的大小和未来的增长量,也可以使用LVM进行分区。只有保证两台机器型号或性能一样,才能保证在切换到secondary节点能完成原来primary节点承担的业务负载。这里分配大小为145GB的/data分区给数据库使用,两台机器完全一样。

dbm133

[root@dbm133 ~]df �Ch |grep data

dbm134

[root@dbm133 ~]df �Ch |grep data

3.3.1.2drbd.conf配置文件

DRBD运行需要读取/etc/drbd.conf配置文件,可以通过如下命令重建这个配置文件,该文件中描述了DRBD设备与硬盘分区的映射关系和DRBD的一些配置参数。

cp /usr/share/doc/drbd83-8.3.8/drbd.conf/etc/drbd.conf

两台主机节点的相关信息如表所示。

节点角色 主机名 IP地址 DRBD分区

primary节点 dbm133 172.19.19.133 /dev/sda3

secondary节点 dbm134 172.19.19.134 /dev/sda3


修改配置文件/etc/drbd.conf

---------------------------------------------------------------------------------------------------------------------------------

global {

   minor-count 64;

   usage-count yes;

    #minor-count dialog-refresh disable-ip-verification

}

common {

   syncer { rate 1000M; }

   handlers {

       # These are EXAMPLE handlers only.

       # They may have severe implications,

       # like hard resetting the node under certain circumstances.

       # Be careful when chosing your poison.

 

       pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh;/usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ;reboot -f";

       pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh;/usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ;reboot -f";

       local-io-error "/usr/lib/drbd/notify-io-error.sh;/usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger; halt -f";

       fence-peer "/usr/lib/drbd/crm-fence-peer.sh";

       pri-lost "/usr/local/drbd/lib/drbd/notify-pri-lost.sh;/usr/local/drbd/lib/drbd/notify-emergency-reboot.sh; echo b>/proc/sysrq-trigger ; reboot -f";

       split-brain "/usr/lib/drbd/notify-split-brain.sh root";

       out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root";

       # before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh-p 15 -- -c 16k";

       # after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh;

    }

 

    startup{

 

       # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb

       wfc-timeout 60;

       degr-wfc-timeout 120;

       outdated-wfc-timeout 2;

    }

 

   options {

       # cpu-mask on-no-data-accessible

       }

 

   disk {

        # size max-bio-bvecs on-io-error fencingdisk-barrier disk-flushes

       # disk-drain md-flushes resync-rate resync-after al-extents

       # c-plan-ahead c-delay-target c-fill-target c-max-rate

       # c-min-rate disk-timeout

       on-io-error detach;

       fencing resource-only;

    }

net {

       # protocol timeout max-epoch-size max-buffers unplug-watermark

       # connect-int ping-int sndbuf-size rcvbuf-size ko-count

       # allow-two-primaries cram-hmac-alg shared-secret after-sb-0pri

       # after-sb-1pri after-sb-2pri always-asbp rr-conflict

       # ping-timeout data-integrity-alg tcp-cork on-congestion

       # congestion-fill congestion-extents csums-alg verify-alg

       # use-rle

       protocol C;

    }

}

resource r0 {

   on dbm133 {

       device          /dev/drbd0;

       disk            /dev/sda3;

       address        172.19.19.133:7788;

       meta-disk       internal;

    }

 

   on dbm134 {

       device          /dev/drbd0;

       disk            /dev/sda3;

       address        172.19.19.134:7788;

       meta-disk       internal;

    }

}

---------------------------------------------------------------------------------------------------------------------------------

将上面的drbd.conf文件分别复制到两台主机的/etc目录下。drbd.conf的配置参数很多,有兴趣可以使用man drbd.conf来了解更多的参数说明。

3.3.1.3DRBD的启动

启动DRBD服务器之前,首先分别在两台主机的/dev/sda3分区上创建DRBD元数据库信息。执行的命令如下:

[root@dbm133 ~]# drbdadm create-md all

initializing activity log

NOT initializing bitmap

Writing meta data...

New drbd meta data block successfullycreated.

[root@dbm134 ~]# drbdadm create-md all

initializing activity log

NOT initializing bitmap

Writing meta data...

New drbd meta data block successfullycreated.

 

这里也可以用drbdadm create-md r0代替dedbadm create-md all。r0是在drbd.conf中定义的资源名称。现在我们可以启动DRBD了,分别在两台主机上执行启动操作。这一步操作有可能出现创建不成功的情况。

[root@dbm133 ~]# drbdadm create-md all

md_offset 268431319040

al_offset 268431286272

bm_offset 268423094272

 

Found ext3 filesystem

  262139964 kB data area apparently used

  262131928 kB left usable by current configuration

 

Device size would be truncated, which

would corrupt data and result in

'access beyond end of device' errors.

You need to either

   *use external meta data (recommended)

   *shrink that filesystem first

   *zero out the device (destroy the filesystem)

Operation refused.

 

Command 'drbdmeta 0 v08 /dev/sda3 internalcreate-md' terminated with exit code 40

这时需要使用如下命令覆盖文件系统中的设备块信息,操作时确认此分区上的数据已经备份过。

dd if=/dev/zero of=/dev/sda3 bs=1Mcount=128

执行完“dd”命令后,再次执行“debdadm create-md all”命令。

启动DRBD服务,设置主节点后,格式化主节点的DRBD分区。

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

Starting DRBD resources:

 

 --==  Thank you for participatingin the global usage survey  ==--

the server's response is:

 

[

   adjust disk: r0

    adjust net: r0

]

degr-wfc-timeout has to be shorter thanwfc-timeout

degr-wfc-timeout implicitly set towfc-timeout (60s)

..........

***************************************************************

 DRBD's startup script waits for the peernode(s) to appear.

 - Ifthis node was already a degraded cluster before the

  reboot, the timeout is 120 seconds. [degr-wfc-timeout]

 - Ifthe peer was available before the reboot, the timeout

   is60 seconds. [wfc-timeout]

  (These values are for resource 'r0'; 0 sec -> wait forever)

 Toabort waiting enter 'yes' [ -- ]: [ 10]:[  11]:[  12]:[ 13]:[  14]:[  15]:[ 16]:[  17]:[  18]:[ 19]:[  20]:[  21]:[ 22]:[  23]:[  24]:[ 25]:[  26]:[  27]:[ 28]:[  29]:[  30]:[ 31]:[  32]:[  33]:[ 34]:[  35]:[  36]:[ 37]:[  38]:[  39]:[ 40]:[  41]:[  42]:[ 43]:[  44]:[  45]:[ 46]:[  47]:[  48]:[ 49]:[  50]:[  51]:[ 52]:[  53]:[  54]:[ 55]:[  56]:[  57]:[ 58]:[  59]:

.

WARN: nothing stacked for this host(dbm133), nothing to do in stacked mode!

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

Starting DRBD resources:

 

 --==  Thank you for participatingin the global usage survey  ==--

The server's response is:

 

[

   adjust disk: r0

    adjust net: r0

]

degr-wfc-timeout has to be shorter thanwfc-timeout

degr-wfc-timeout implicitly set towfc-timeout (60s)

.

WARN: nothing stacked for this host(dbm134), nothing to do in stacked mode!

 

查看drbd

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

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

GIT-hash:833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R6, 2015-04-0914:35:00

 0:cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r---b-

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

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

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

GIT-hash:833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R6, 2015-04-0914:35:00

 0:cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r---b-

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

设置主节点:

[root@dbm133 ~]# drbdadm ----overwrite-data-of-peer primary r0

查看状态:

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

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

GIT-hash:833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R6, 2015-04-0914:35:00

 0:cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r---a-

   ns:118724 nr:0 dw:0 dr:120480 al:0 bm:0 lo:0 pe:10 ua:2 ap:0 ep:1 wo:foos:262023384

       [>....................] sync'ed: 0.1% (255880/255988)M

       finish: 60:39:12 speed: 1,196 (968) K/sec
[root@dbm134 ~]# cat /proc/drbd

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

GIT-hash:833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R6, 2015-04-0914:35:00

 0:cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r---b-

   ns:0 nr:514048 dw:505856 dr:0 al:0 bm:0 lo:8 pe:0 ua:8 ap:0 ep:1 wo:foos:261626072

       [>....................] sync'ed:  0.2% (255492/255988)M

       finish: 59:57:21 speed: 1,208 (984) want:102,400 K/sec

 

从输出状态可知,主、备状态分别是Primiary和Secondary,主机磁盘状态是UpToDate,备机磁盘状态是Inconsistent。从加粗代码性可以看到,数据正在同步中,即主机正在将磁盘上的数据传到备用机上。现在同步的速率是100Mbit/s,进度为0.2%。

 

同步完成之后,再次查看DRBD状态,显示信息如下:

主节点:

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

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

GIT-hash:833d830e0152d1e457fa7856e71e11248ccf3f70 build by phil@Build64R6, 2015-04-0914:35:00

 0:cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----

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

备节点:

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

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

GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70build by phil@Build64R6, 2015-04-09 14:35:00

 0:cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----

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

 

从输出信息可知,磁盘状态都是”UpToDate“,表示数据同步完成了。

输出中的一些参数的含义如下:

ro 是角色信息,Primary/Secondary说明了当前主机是Primary节点,另一台是Secondary节点。

ds是磁盘状态,显示数据是否一致(如果显示UpToDate/UpToDate表示同步没有延时)。

ns是网络发送的数据包,以K字节计算。

dw是磁盘写操作。

dr是磁盘读操作。

3.3.2DRBD的维护和管理

挂载DRBD分区之前,首先要确认当前主机的DRBD分区是primary状态,可以从”cat/proc/drbd”命令中查询节点状态。例如:

其中“ro:Primary/Sencondary”表示dbm133主机处于Primary状态,可以执行挂载操作。如果显示”ro:Secondary/Primary“,则说明当前主机为Secondary状态,处于这个状态的主机不能对DRBD设备进行挂载操作。

如果当前是Secondary状态,额可以通过命令”drdbadm primary all”把当前主机更改为Primary状态。Drdbamin命令是DRBD的管理命令,它的很多参数可以用来管理DRBD同步或停止、网络断开或者连接等各种状态的转化。

3.3.2.1格式化文件系统

只需要在主节点执行即可

[root@dbm133 etc]# mkfs.ext4 /dev/drbd0

3.3.2.2挂载DRBP磁盘分区到/data

挂载DRBD分区到/data目录

[root@dbm133 ~]#mount /dev/drbd0 /data

[root@dbm133 ~]# df �Ch | grep data

3.3.2.3DRBD设备角色切换

DRBD设备在进行角色切换操作前,需要现在主节点执行umount命令,去掉对DRBD设备的挂载,然后在另一台主机上把DRBD角色改为Primary,最后再执行挂载。操作如下:

主节点:

[root@dbm133 ~]#df �Ch | grep data

[root@dbm133 ~]#umount /data

[root@dbm133 ~]#drbdadm secondary all

从节点:

[root@dbm134 ~]# drbdadm primary all

[root@dbm134 ~]# mount /dev/drbd0 /data

还有一种切换策略

主节点:

[root@dbm133 ~]# /etc/init.d/drbd stop

从节点:

[root@dbm134 ~]# drbdadm ----overwrite-data-of-peer primary all

[root@dbm134 ~]# mount /dev/drbd0 /data

3.3.3DRBD性能优化

3.3.3.1网络环境

使用千兆网卡的不要使用百兆网卡。当前主流机器都是使用千兆网卡,交换机也不例外。同时,DRBD的数据同步使用的网络最后和提供服务的网卡分开,尽量独立出来。例如两块网卡上直接连接一个网线,用作DRBD的数据同步。

3.3.3.2做DRBD分区的磁盘性能

用作DRBD分区的磁盘性能要尽量好,例如可以考虑用不少于6块的SAS盘作为RAID10或者RAID0(最后用BBU),以提供I/O性能。在网络环境很好的情况下,DRBD分区可能会由于I/O的写性能而成为瓶颈。

3.3.3.3更新系统

尽量把系统更新成最新的内核以及64位的系统,同时使用最新版本的DRBD。

3.3.3.4注意syncer参数设置

syncer主要用来设置同步相关参数。可以设置“重新”同步(re-syncronization)的速率(rate),当节点间出现不一致的block时,DRBD就需要执行re-synchronization动作,而syncer中的参数rate就是用来设置同步的速率的,rate的设置与网络和磁盘的I/O能力密切相关。

千兆网络的同步速率大约是125Mbit/s,百兆网络的同步速率大约是11Mbit/s,用这个同步速率和磁盘写入速率中最小者的30%带库来这是re-synchronization是白酒合适的,这也是官方给出的建议。

例如,同步速率为125Mbit/s,磁盘写入速度为110Mbit/s,应该设置rate为不能超过33Mbit/s。这样设置的原因是:DRBD同步由两个不同的进程来负责:一个replication进程用来同步block的更新,这个值受限于参数设置:一个synchronization进程用来同步元数据信息,这个值不受参数设置限制。如果写入量非常大,设置的参数超过磁盘的写入速率,元数据的同步速率就会受干扰,传输速度变慢,导致机器负载非常高,性能下降的非常厉害,所以这个值应该根据实际环境来进行设置,如果设置的太大,就会把所有的带宽占满了,导致replication进程没有可用带宽,最终可能导致I/O停止。出现同步不正常的情况。

3.3.3.5注意al-extents参数设置

al-extents控制着一次向磁盘写入多少个4MB的数据块。增大这个参数有以下的几个好处:

    可以减少更新元数据到DRBD设备的频率

    降低同步数据时对I/O流的中断数量。

    提高修改DRBD设备的速度。

但同时也存在一个风险:当主节点出现宕机时,所有活动的数据(al-extends的值x 4M的数据块)需要在同步连接建立后重新同步,即主节点出现宕机时,备用节点出现数据不一致的情况。因此不建议在HA部署上调整这个参数,可以在某些情况下调整这个参数来提高性能。

 

3.4heartbeat部署

Heartbeat源码安装

3.4.1安装依赖包

[root@dbm133 ~]# yum install gcc gcc-c++autoconf automake libtool glib2-devel libxml2-devel bzip2-devel e2fsprogs-devellibxslt-devel libtool-ltdl-devel make wget docbook-dtds docbook-style-xsl

3.4.2添加用户

添加 Haclient 组和 Hacluster 账户。这个用户主要用来配置respawn的。

[root@dbm133 ~]# groupadd haclient

[root@dbm133 ~]# useradd -g haclienthacluster -M -s /sbin/nologin

3.4.3安装libaio

cluster-glue依赖的库。libaio是Linux下的一个异步非阻塞接口,它提供了以异步非阻塞方式来读写文件的方式,读写效率比较高。

[root@dbm133 ~]# yum install libaio-devel

3.4.4安装cluster-glue

glue(胶水的意思)是用来粘合Heartbeat、Pacemake以及Resource Agent的一系列类库、工具的集合。

[root@dbm133 ~]# wgethttp://hg.linux-ha.org/glue/archive/glue-1.0.9.tar.bz2

[root@dbm133 ~]# tar jxvfglue-1.0.9.tar.bz2

[root@dbm133 ~]# cdReusable-Cluster-Components-glue--glue-1.0.9/

[root@dbm133 ~]# ./autogen.sh

[root@dbm133 ~]# ./configure--prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeatlibdir=/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'

[root@dbm133 ~]# make && makeinstall l

3.4.5安装ResourceAgents

resource-agents为集群资源的访问提供了一系列标准的接口。

[root@dbm133 ~]# wgethttps://codeload.github.com/ClusterLabs/resource-agents/zip/v3.9.2

[root@dbm133 ~]# unzip v3.9.2

[root@dbm133 ~]# cd resource-agents-3.9.2/

[root@dbm133 ~]# ./autogen.sh

[root@dbm133 ~]# ./configure--prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeatlibdir=/usr/local/heartbeat/lib64 CFLAGS=-I/usr/local/heartbeat/includeLDFLAGS=-L/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'

//建立一个软连接,避免编译时找不到所需要的包

[root@dbm133 ~]# ln -s /usr/local/heartbeat/lib64/*/lib64/

[root@dbm133 ~]# make && makeinstall

注意:LDFLAGS的空格,否则configure时不会报错但make时报错。

3.4.6安装Heartbeat

[root@dbm133 ~]#wget

http://hg.linux-ha.org/heartbeat-STABLE_3_0/archive/7e3a82377fa8.tar.bz2

[root@dbm133 ~]# tar jxvf 7e3a82377fa8.tar.bz2

[root@dbm133 ~]# cdHeartbeat-3-0-7e3a82377fa8/

[root@dbm133 ~]# ./bootstrap

[root@dbm133 ~]# ./configure--prefix=/usr/local/heartbeat --sysconfdir=/etc/heartbeatCFLAGS=-I/usr/local/heartbeat/include LDFLAGS=-L/usr/local/heartbeat/lib64 LIBS='/lib64/libuuid.so.1'

[root@dbm133 ~]#vi /usr/local/heartbeat/include/heartbeat/glue_config.h

 // 删除glue_config.h 最后一行定义的配置文件路径,避免编译时产生的路径重复定义错误,Shift+g 跳到末行,dd删除

[root@dbm133 ~]# make && makeinstall

make 报错

/usr/local/heartbeat/include/heartbeat/glue_config.h:105:1:error: "HA_HBCONF_DIR" redefined

解决:vim /usr/local/heartbeat/include/heartbeat/glue_config.h

// 删除 glue_config.h 最后一行定义的配置文件路径,避免编译时产生的路径重复定义错误,Shift+g 跳到末行,dd删除

 

报错:

ucast.c: In function ‘HB_make_send_sock’:

ucast.c:468: error: conflicting types for‘i’

ucast.c:465: note: previous declaration of‘i’ was here

ucast.c:502: error: request for member‘ifr_ifrn’ in something not a structure or union

ucast.c:508: error: request for member‘ifr_ifrn’ in something not a structure or union

ucast.c:513: error: request for member‘ifr_ifrn’ in something not a structure or union

解决:vim lib/plugins/HBcomm/ucast.c +468

这个文件有问题,删除468int i = 1;就能继续make

3.4.7复制配置文件

cp /usr/local/heartbeat/share/doc/heartbeat/authkeys/etc/heartbeat/ha.d/

cp/usr/local/heartbeat/share/doc/heartbeat/haresources /etc/heartbeat/ha.d/

cp/usr/local/heartbeat/share/doc/heartbeat/ha.cf /etc/heartbeat/ha.d/

chkconfig --add heartbeat

chkconfig heartbeat on

3.4.8配置

chmod 600 /etc/heartbeat/ha.d/authkeys

 

修改/etc/heartbeat/ha.d/ha.cf

debugfile /var/log/ha-debug   # 打开错误日志报告

keepalive 1                   # 1秒检测一次心跳线连接

deadtime 15                   # 15秒测试不到 主节点心跳线就认为有问题

warntime 5                    # 警告时间(建议在210之间)

initdead 30                   # 初始化启动时 30秒无连接视为正常,或指定heartbeat在启动时,

 

#另一台主机节点eth1IP地址,通过两个不同网络来保证心跳的可用性,也可以加上串口的检测

或者在机器之间连线

 

udpport 694     # udp694端口连接

ucast eth1 172.19.19.133      # 单播方式连接(主、从都是写对方的IP连接

 

#primary节点切换到secondary节点之后,primary节点恢复正常,不进行切回操作,因为切换一次

#MySQL master的成本很高

auto_failback off

 

#定义两个节点的主机名,一行写一个

node dbm133  # 声明主节点(uname-n

node dbm134  # 声明次节点(uname-n

respawn hacluster/usr/local/heartbeat/lib64/heartbeat/ipfail #监控ipfail进程是否挂掉,否则重启它

 

#开启dopd功能

respawn hacluster /usr/local/heartbeat/lib64/heartbeat/dopd

apiauth ipfail gid=haclient uid=hacluster

apiauth dop gid=haclient uid=hacluster

 

修改/etc/heartbeat/ha.d/authkeys

auth 1

1 shal HA_JACKBILLON    #使用shal验证;密码:HA_JACKBILLON

 

修改/etc/heartbeat/ha.d/haresource

dbm133 IPaddr::172.19.19.222/24/eth1

3.4.9heartbeat测试

3.4.9.1启动heartbeat

dbm133dbm134上都启动heartbeat

[root@dbm133 ~]# service heartbeat start

[root@dbm134 ~]# service heartbeat start

[root@dbm133 ~]# ip a

[root@dbm134 ~]# ip a

观察vip172.19.19.222是否绑定到主节点dbm133上

3.4.9.2停止主节点heartbeat,观察vip

[root@dbm133 ~]# service heartbeat stop

[root@dbm133 ~]# ip a

[root@dbm134 ~]# ip a

观察vip172.19.19.222是否漂移到备节点dbm134

3.4.9.3停止备节点heartbeat,观察vip

[root@dbm133 ~]# ip a

[root@dbm134 ~]# ip a

观察vip172.19.19.222是否回切,在本例中配置不回切,修改ha.cf auto_failback on,开启自动回切,因为切换master的成本比较高,视具体情况而定。

 

3.5MySQL部署

3.5.1MySQL安装

安装mysql有多种方法,这里仅利用rpm安装MySQL为例进行说明。

安装约定,mysql软件采用默认路径,数据文件、配置文件存在/data/mysql下

[root@dbm133 ~]# rpm -ivhMySQL-server-advanced-5.6.18-1.el6.x86_64.rpm

[root@dbm133 ~]# rpm -ivhMySQL-client-advanced-5.6.18-1.el6.x86_64.rpm

[root@dbm133 ~]# rpm -ivhMySQL-devel-advanced-5.6.18-1.el6.x86_64.rpm

[root@dbm133 ~]# cp �Cr /var/lib64/mysql/data/mysql

[root@dbm133 ~]# cp �Cr /usr/my.cnf/data/mysql/

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

[root@dbm133 ~]# chkconfig mysql off

修改my.cnf位置

vi /etc/init.d/mysql +214

conf=/data/mysql/my.cnf

 

修改配置文件/data/my.cnf,设置数据库文件路径

datadir=/data/mysql

 

3.5.2heartbeat+DRBD+MySQL配置

Heartbeat+DRBD+MySQL配置主节点的高可用性,即master-master-slave

 

3.5.2.1拷贝数据库

dbm133上:

[root@dbm133 ~]# service mysql stop

[root@dbm133 ~]# cd /data/

[root@dbm133 ~]# tar �Czcvf mysql.tar.gzmysql

[root@dbm133 ~]# scp �Cr mysq.tar.gz [email protected]:/data/

dbm134上:

[root@dbm134 ~]# cd /data/

[root@dbm134 ~]# tar �Czxvf mysq.tar.gz

[root@dbm133 ~]#

3.5.2.2配置heartbeat

[root@dbm133 ~]# vi/etc/heartbeat/ha.d/haresource

dbm133 IPaddr::172.19.19.222/24/eth1drbddisk::r0 Filesystem::/dev/drbd0::/data mysql

172.19.19.222vip,在两台主机之间漂移

drbddisk是一个管理DRBD的脚本,heartbeat默认提供这个脚本文件,

可以在/etc/heartbeat/ha.d/resource.d目录下找到。R0是一个启动资源,在drbd配置文件中定义,通过“drbddisk::r0”可以切换drbd主机为primary节点或secondary节点,只有状态为primary的主机才能挂载DRBD分区。Drbddisk主机为primary节点或者secondary节点,只有状态为primary的主机才能挂载DRBD分区。drbddisk脚本相当于执行”drdbadm primary r0”或“drbdadm secondary r0”操作,表示把DRBD资源的角色进行变更。

Filesystem::/dev/drbd0::/data表示把/dev/drbd0设备挂载到/data分区下。

mysql表示启动mysql,应该在系统启动中关闭mysql开机自启动,统一通过heartbeat配置。

 

在heartbeat资源脚本目录中创建mysql启动脚本的软连接

在dbm133,dbm134上都执行

[root@dbm133 ~]# ln -s /etc/init.d/mysql/etc/heartbeat/ha.d/resource.d/mysql

[root@dbm134 ~]# ln -s /etc/init.d/mysql/etc/heartbeat/ha.d/resource.d/mysql

 

3.5.2.3测试资源切换

停掉主节点上的heartbeat模拟主节点宕机

[root@dbm133 ~]# service heartbeat stop

[root@dbm133 ~]# tail �Cf /var/log/ha-debug

[root@dbm134 ~]# tail �Cf /var/log/ha-debug

查看日志,备节点上是否启动资源 drbd和mysql

如果配置heartbeat自动回切,重新启动主节点heartbeat,看备节点的资源是否重新切回到主节点。

在主节点上启动heartbeat,创建数据库

[root@dbm133 ~]# mysql �Cu root �Cp

mysql>create database mydb character setutf8;

mysql> show databases;

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

| Database           |

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

| information_schema |

| mydb               |

| mysql              |

| performance_schema |

| test               |

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

5 rows in set (0.03 sec)mysql>exit;

停止主节点heartbeat

[root@dbm133 ~]#service heartbeat stop

[root@dbm134 ~]#mysql �Cu root �Cp

mysql> show databases;

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

| Database           |

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

| information_schema |

| mydb               |

| mysql              |

| performance_schema |

| test              |

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

5 rows in set (0.03 sec)

可以看到在备节点上有新建的数据库mydb

3.5.2.4特别说明

Heartbeat+DRBD+MySQL,配置heartbeat可以虚拟出一个虚拟IP,在主节点和备用节点上跳转,对外提供服务,DRBD提供数据文件的拷贝。

3.5.3MySQL主从复制的配置

MySQL的复制(replication)是异步复制,即从一个MySQL实例或者端口(称之为Master)复制到另一个MySQL实例或者端口(称之为Slave)。复制操作由三个进程完成,其中两个进程(SQL进程和I/O进程)在Salve上,另外一个进程在Master(binlog dump)上。

要实现复制,必须打开Master端的二进制日志(log-bin)功能。这是因为整个复制过程实际上就是Slave从Master端获取该更新操作的日志,将其传输到本地并写到本地文件中,然后再读取本地文件内容执行日志中的锁记录的更新操作,如图所示。

wKiom1ZKfUbCcZzBAAE4KVtgedk373.jpg

主从复制,可以实现mysql的读写分离,写操作在master节点,读操作在slave节点

3.5.3.1在master上建立同步用户

每个同步服务器都必须设定一个唯一的编号,修改my.cnf,增加或修改如下两行:

server-id = 1  #相同端口必须唯一

log-bin        #开启记录二进制日志功能

在Master(这里为dbm157机器)上增加一个用户复制的帐号

mysql>GRANT REPLICATION SLAVE ON *.* TO ‘repl_user’@’slave_ip’IDENTIFIEDBY ‘repl_password’;

在本例中:

mysql> GRANT REPLICATION SLAVE ON *.* TO ' repl_user’'@'172.19.19.*' identified BY ' repl_password ';

mysql>FLUSH TABLES WITH READ LOCK;

mysql>reset master;

不要退出终端,否则这个锁就失效了。在不退出终端的情况,再开启一个终端直接打包压缩数据文件或者使用mysqldump工具来导出数据。

[root@dbm133 ~]# cd /var/lib

[root@dbm133 ~]# tar �Czcvf mysql.tar.gzmysql

[root@dbm133 ~]#scp �Cr mysql.tar.gz [email protected]:/var/lib

scp命令把打包的数据传输到其他几台Slave机器上。

数据传输完成后,在执行FLUSH TABLES WITH READ LOCK命令的终端上执行如下命令:

mysql>UNLOCK TABLES;

 

注意修改/data/mysql/auto.cnf,因为是从主机上直接拷贝的,修改为不一致即可。

 

3.5.3.2设置slave主机

修改my.cnf的server-id,如下:

server-id = 2

其他slave上依此类推,保证server-id全局唯一。

3.5.3.3开启master和slave同步

在Slave上执行如下命令;

mysql>CHANGE MASTER TO MASTER_HOST='172.19.19.133',

MASTER_USER='repl_user',

MASTER_PASSWORD='repl_password',

MASTER_LOG_FILE='mysql-bin.000001',

MASTER_LOG_POS=0;

查看slave状态

mysql> show slave status\G;

*************************** 1. row***************************

               Slave_IO_State:

                  Master_Host: 172.19.19.133

                  Master_User: repl_user

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000001

         Read_Master_Log_Pos: 4

               Relay_Log_File: mysql-relay-bin.000001

                Relay_Log_Pos: 4

       Relay_Master_Log_File: mysql-bin.000001

            Slave_IO_Running: No

           Slave_SQL_Running: No

              Replicate_Do_DB:

         Replicate_Ignore_DB:

          Replicate_Do_Table:

      Replicate_Ignore_Table:

     Replicate_Wild_Do_Table:

 Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

         Exec_Master_Log_Pos: 4

              Relay_Log_Space: 120

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

          Master_SSL_Allowed: No

          Master_SSL_CA_File:

          Master_SSL_CA_Path:

              Master_SSL_Cert:

           Master_SSL_Cipher:

               Master_SSL_Key:

       Seconds_Behind_Master: NULL

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

 Replicate_Ignore_Server_Ids:

            Master_Server_Id: 0

                  Master_UUID:

            Master_Info_File: /data/mysql/master.info

                    SQL_Delay: 0

         SQL_Remaining_Delay: NULL

     Slave_SQL_Running_State:

          Master_Retry_Count: 86400

                  Master_Bind:

     Last_IO_Error_Timestamp:

    Last_SQL_Error_Timestamp:

               Master_SSL_Crl:

          Master_SSL_Crlpath:

          Retrieved_Gtid_Set:

           Executed_Gtid_Set:

                Auto_Position: 0

1 row in set (0.00 sec)

表明slave还没有开始复制过程。日志的位置为4而不是0,这是因为0只是日志文件的开始位置,并不是日志位置。实际上,MySQL知道的第一个事件的位置是4

mysql> start slave;

再次查看slave状态

mysql> show slave status\G;

*************************** 1. row***************************

               Slave_IO_State: Waiting formaster to send event

                  Master_Host: 172.19.19.133

                  Master_User: repl_user

                  Master_Port: 3306

               Connect_Retry: 60

              Master_Log_File: mysql-bin.000001

         Read_Master_Log_Pos: 120

               Relay_Log_File:mysql-relay-bin.000003

                Relay_Log_Pos: 283

       Relay_Master_Log_File: mysql-bin.000001

            Slave_IO_Running: Yes

           Slave_SQL_Running: Yes

              Replicate_Do_DB:

         Replicate_Ignore_DB:

          Replicate_Do_Table:

      Replicate_Ignore_Table:

     Replicate_Wild_Do_Table:

 Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

         Exec_Master_Log_Pos: 120

              Relay_Log_Space: 456

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

          Master_SSL_Allowed: No

          Master_SSL_CA_File:

          Master_SSL_CA_Path:

              Master_SSL_Cert:

           Master_SSL_Cipher:

               Master_SSL_Key:

       Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

 Replicate_Ignore_Server_Ids:

            Master_Server_Id: 1

                  Master_UUID:678b3daa-7150-11e5-b06d-005056973e24

            Master_Info_File: /data/mysql/master.info

                    SQL_Delay: 0

         SQL_Remaining_Delay: NULL

     Slave_SQL_Running_State: Slave has read all relay log; waiting for theslave I/O thread to update it

          Master_Retry_Count: 86400

                  Master_Bind:

     Last_IO_Error_Timestamp:

    Last_SQL_Error_Timestamp:

               Master_SSL_Crl:

          Master_SSL_Crlpath:

          Retrieved_Gtid_Set:

           Executed_Gtid_Set:

                Auto_Position: 0

1 row in set (0.00 sec)

Slave_IO_Running和Slave_SQL_Running:都为Yes,表示slave的I/O和SQL线程都已经开始运行,而且Seconds_Behind_Master不再是NULL。日志的位置增加了,意味着一些事件被获取并执行了。如果你在master上进行修改,你可以在slave上看到各种日志文件的位置的变化,同样,你也可以看到数据库中数据的变化。

可查看master和slave上线程的状态。在master上,你可以看到slave的I/O线程创建的连接:

master上输入showprocesslist\G;

mysql> show processlist\G;

*************************** 1. row***************************

    Id: 5

  User: root

  Host: localhost

    db: NULL

Command: Query

  Time: 0

 State: init

  Info: show processlist

*************************** 2. row***************************

    Id: 7

  User: repl_user

  Host: dbm134:57784

    db: NULL

Command: Binlog Dump

  Time: 459

 State: Master has sent all binlog to slave; waiting for binlog to beupdated

  Info: NULL

2 rows in set (0.00 sec)

在slave服务器上运行该语句:

mysql> show processlist\G;

*************************** 1. row***************************

    Id: 1

  User: system user

  Host:

    db: NULL

Command: Connect

  Time: 548

 State: Waiting for master to send event

  Info: NULL

*************************** 2. row***************************

    Id: 2

  User: system user

  Host:

    db: NULL

Command: Connect

  Time: 547

 State: Slave has read all relay log; waiting for the slave I/O thread toupdate it

  Info: NULL

*************************** 3. row***************************

    Id: 3

  User: root

  Host: localhost

    db: NULL

Command: Query

  Time: 0

 State: init

  Info: show processlist

3 rows in set (0.00 sec)

3.5.3.4添加新的slave节点

假如master已经运行很久了,想对新安装的slave进行数据同步,甚至它没有master的数据。

此时,有几种方法可以使slave从另一个服务开始,例如,从master拷贝数据,从另一个slave克隆,从最近的备份开始一个slave。Slave与master同步时,需要三样东西:

(1)master的某个时刻的数据快照;

(2)master当前的日志文件、以及生成快照时的字节偏移。这两个值可以叫做日志文件坐标(log filecoordinate),因为它们确定了一个二进制日志的位置,你可以用SHOW MASTER STATUS命令找到日志文件的坐标;

(3)master的二进制日志文件。

 

可以通过以下几中方法来克隆一个slave:

(1)    冷拷贝(coldcopy)

停止master,将master的文件拷贝到slave;然后重启master。缺点很明显。

(2)    热拷贝(warmcopy)

如果你仅使用MyISAM表,你可以使用mysqlhotcopy拷贝,即使服务器正在运行。

(3)    使用mysqldump

使用mysqldump来得到一个数据快照可分为以下几步:

<1>锁表:如果你还没有锁表,你应该对表加锁,防止其它连接修改数据库,否则,你得到的数据可以是不一致的。如下:

mysql> FLUSH TABLES WITH READ LOCK;

<2>在另一个连接用mysqldump创建一个你想进行复制的数据库的转储:

shell> mysqldump --all-databases --lock-all-tables>dbdump.db

<3>对表释放锁。

mysql> UNLOCK TABLES;

3.5.4需要注意的问题

  • 如果在my.cnf中定义了log-bin、relay-log参数,那么要保证这些定义与主机名无关,因为uruguo这两类log的文件名与主机名有关,切换过程中会导致Slave主机不能继续同步,例如可以如下设置:

log-bin= mysql-bin

relay-bin= mysql-relay-bin

保证在两台主机上两个文件的名字一样。

2)最好把my.cnf文件也放入DRBD分区的数据目录中,这样进行配置变更时,另一台也保持同步,避免由于修改文件导致切换后的配置不一样。要把my.cnf文件放入DRBD分区的数据目录中,需要修改/etc/init.d/mysql启动脚本中的my.cnf文件的路径。

3)如果不是通过rpm安装MySQL,要保证MySQL启动脚本能接收start、top、startus三个参数。默认heartbeat采用LSB(LinuxStandard Base)风格,返回值包含OK或running则表示资源正常,返回值包含stopped或No则表示资源不正常。其他资源脚本的情况类似。

4)不要设置mysql在机器重启动时自动启动,mysql服务作为heartbeat的一项资源会统一管理。

3.6.搭建slave集群

3.6.1slave集群

Heartbeat+DRBD解决了MySQL的master的高可用性问题,在master出现故障时能达到快速切换,slave也可以用这种方案来实现高可用性,但是这样部署的成本会比较高。在读操作多而写操作比较少的互联网应用中,一台机器很难承受不断增长的读操作,此时,就需要进行读写分离,一台master承担写操作,多台slave提供读操作。如果仍采用heartbeat+DRBD来实现slave的高可用性,搭建成本讲无法承受,在大多数公司中,都是一组5x8的工作人员来维护着一个365x7x24的在线业务,要求一台slave出现故障不会影响业务的正常运行,同时可以不及时处理故障。这就要求slave也具有比较高的可用性,也就是说,当一台slave出现故障时,可以自动关闭对外提供服务,这个过程不需要认为干预。

    LVS+keepalived能很好地实现上述功能,他可以完成负载均衡功能,同事通过自定义检测脚本,保证在一台slave出现故障时,自动从LVS的realserver列表中剔除故障节点,不在对外提供服务,保证了slave的高可用性,同时成本也很低。

    当前很多公司使用DNS解析的轮询去实现多台slave的负载均衡,这种方式存在两个问题:第一,不能实现很好的负载均衡:第二,需要第三方监控来更新DNS以实现slave的故障切换,因为更新解析的TTL问题不能达到很高的可用性。

    下面详细介绍LVS+keepalived的配置过程。

 

 

3.6.2LVS+keepalived

3.6.2.1安装keepalived

yum安装:

[root@dbm144 ~]# yum install -y keepalived

[root@dbm145 ~]# yum install -y keepalived

源码安装:

cd /usr/local/

tar zxvfkeepalived-1.2.12.tar.gz

cd keepalived-1.2.12

./configure --prefix=/usr/local/keepalived

make

make install

cp/usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

cp/usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

cp/usr/local/keepalived/sbin/keepalived /usr/sbin/

mkdir -p /etc/keepalived/

cp/usr/local/keepalived/etc/keepalived/keepalived.conf/etc/keepalived/keepalived.conf

chkconfig --add keepalived

chkconfig  --level 123456 keepalived on

service keepalivedstart|stop

3.6.2.2配置keepalived

Master

---------------------------------------------------------------------------------------------------------------------------------

! Configuration File forkeepalived

global_defs {

   notification_email {

     [email protected]   #设置报警邮件地址,可以设置多个,每行1

     [email protected]  #需开启邮件报警及本机的Sendmail服务。

     [email protected]

   }

   [email protected]

   smtp_server 127.0.0.1  #设置SMTPServer地址;

   smtp_connect_timeout 30

   router_id LVS_DEVEL

}

########VRRPInstance########

vrrp_instance VI_1 {

    state MASTER    #指定Keepalived的角色,MASTER为主机服务器,BACKUP为备用服务器

    interface eth1  #BACKUP为备用服务器

    virtual_router_id 51

    priority 100    #定义优先级,数字越大,优先级越高,主机器必须大于备机。

    advert_int 1

    authentication {

        auth_type PASS  #设置验证类型,主要有PASSAH两种

        auth_pass 1111  #设置验证密码

    }

    virtual_ipaddress {

        172.19.19.223  #设置主DR的虚拟IP地址(virtualIP),可多设,但必须每行1

    }

}

########VirtualServer########

virtual_server172.19.19.223 3306 {  #注意IP地址与端口号之间用空格隔开

    delay_loop 6        #设置健康检查时间,单位是秒

   lb_algo lc          #设置负载调度算法,默认为rr,即轮询算法,最优秀是wlc算法,这里使用的是最小链接算法

    lb_kind DR          #设置LVS实现LB机制,有NATTUNNDR三个模式可选

    #nat_mask 255.255.255.0

    #persistence_timeout 50  #会话保持时间,单位为秒

    protocol TCP        #指定转发协议类型,有TCPUDP两种

    real_server 172.19.19.135 3306 {

        weight 1          #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3     #表示3秒无响应,则超时

            nb_get_retry 3        #表示重试次数

            delay_before_retry 3  #表示重试间隔

        }

    }

    real_server 172.19.19.136 3306 {  #配置服务器节点,即RealServer2public IP

        weight 3            #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3       #表示3秒无响应,则超时

            nb_get_retry 3          #表示重试次数

            delay_before_retry 3    #表示重试间隔

        }

    }

        real_server 172.19.19.137 3306 {  #配置服务器节点,即RealServer2public IP

        weight 3            #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3       #表示3秒无响应,则超时

            nb_get_retry 3          #表示重试次数

            delay_before_retry 3    #表示重试间隔

        }

    }

}

---------------------------------------------------------------------------------------------------------------------------

Slave

! Configuration File forkeepalived

global_defs {

   notification_email {

     [email protected]   #设置报警邮件地址,可以设置多个,每行1

     [email protected]  #需开启邮件报警及本机的Sendmail服务。

     [email protected]

   }

   [email protected]

   smtp_server 127.0.0.1  #设置SMTPServer地址;

   smtp_connect_timeout 30

   router_id LVS_DEVEL

}

########VRRPInstance########

vrrp_instance VI_1 {

    state BACKUP    #指定Keepalived的角色,MASTER为主机服务器,BACKUP为备用服务器

    interface eth1  #BACKUP为备用服务器

    virtual_router_id 51

    priority 99    #定义优先级,数字越大,优先级越高,主机器必须大于备机。

    advert_int 1

    authentication {

        auth_type PASS  #设置验证类型,主要有PASSAH两种

        auth_pass 1111  #设置验证密码

    }

    virtual_ipaddress {

        172.19.19.223  #设置主DR的虚拟IP地址(virtualIP),可多设,但必须每行1

    }

}

########Virtual Server########

virtual_server172.19.19.223 3306 {  #注意IP地址与端口号之间用空格隔开

    delay_loop 6        #设置健康检查时间,单位是秒

    lb_algo lc          #设置负载调度算法,默认为rr,即轮询算法,最优秀是wlc算法,这里使用的是最小链接算法

    lb_kind DR          #设置LVS实现LB机制,有NATTUNNDR三个模式可选

    #nat_mask 255.255.255.0

    #persistence_timeout 50  #会话保持时间,单位为秒

    protocol TCP        #指定转发协议类型,有TCPUDP两种

    real_server 172.19.19.135 3306 {

        weight 1          #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3     #表示3秒无响应,则超时

            nb_get_retry 3        #表示重试次数

            delay_before_retry 3  #表示重试间隔

        }

    }

    real_server 172.19.19.136 3306 {  #配置服务器节点,即RealServer2public IP

        weight 3            #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3       #表示3秒无响应,则超时

            nb_get_retry 3          #表示重试次数

            delay_before_retry 3    #表示重试间隔

        }

    }

        real_server 172.19.19.137 3306 {  #配置服务器节点,即RealServer2public IP

        weight 3            #配置节点权值,数字越大权值越高

        TCP_CHECK {

            connect_timeout 3       #表示3秒无响应,则超时

            nb_get_retry 3          #表示重试次数

            delay_before_retry 3    #表示重试间隔

        }

    }

}

 

---------------------------------------------------------------------------------------------------------------------------

备注:

可以讲两台LVSkeepalived的状态设置成BUCKUP,即主节点恢复之后,VIP不回切,将坏掉的节点修复之后做成备节点。

 

部署完成后在LVS机器上执行如下命令:

[root@LVS1 ~]# yum install�Cy ipvsadm

[root@LVS1 ~]# ipvsadm �CLn

IP Virtual Server version1.2.1 (size=4096)

Prot LocalAddress:PortScheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  172.19.19.223:3306 rr persistent 120

  -> 172.19.19.135:3306           Route   125   0          0        

  -> 172.19.19.136:3306           Route   125   0          0        

  -> 172.19.19.137:3306           Route   125   0          0        

使用LVS的DR模式,把VIP绑定到lo:1上

[root@LVS1 ~]# vi/etc/sysctl.conf

net.ipv4.conf.all.arp_ignore= 1

net.ipv4.conf.all.arp_announce= 2

net.ipv4.conf.lo.arp_ignore= 1

net.ipv4.conf.lo.arp_announce= 2

[root@LVS1 ~]# sysctl �Cp

配置LVS1,LVS2上的realserver,绑定vip到lo:0

[root@LVS1 ~]# vi/etc/init.d/realserver

---------------------------------------------------------------------------------------------------------------------------

#!/bin/bash

VIP=172.19.19.223

source/etc/rc.d/init.d/functions

case "$1" in

start)

       ifconfig lo:0 $VIP netmask255.255.255.255 broadcast $VIP

       ifconfig lo:0 $VIP netmask255.255.255.255 broadcast $VIP

       /sbin/route add -host $VIP dev lo:0

       echo "1">/proc/sys/net/ipv4/conf/lo/arp_ignore

       echo "2">/proc/sys/net/ipv4/conf/lo/arp_announce

       echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore

       echo "2">/proc/sys/net/ipv4/conf/all/arp_announce

       echo "RealServer Start OK"

       ;;

stop)

       ifconfig lo:0 down

       route del $VIP >/dev/null 2>&1

       echo "0">/proc/sys/net/ipv4/conf/lo/arp_ignore

       echo "0">/proc/sys/net/ipv4/conf/lo/arp_announce

       echo "0">/proc/sys/net/ipv4/conf/all/arp_ignore

       echo "0">/proc/sys/net/ipv4/conf/all/arp_announce

       echo "RealServer Stoped"

       ;;

       *)

       echo "Usage: $0 {start|stop}"

       exit 1

esac

exit 0

---------------------------------------------------------------------------------------------------------------------------

[root@LVS1 ~]# chmod u+x/etc/init.d/realserver

[root@LVS1 ~]# chmod u+x/etc/rc.d/init.d/functions

[root@LVS1 ~]# /etc/init.d/realserverstart

 

[root@LVS2 ~]# chmod u+x/etc/init.d/realserver

[root@LVS2 ~]#chmod u+x/etc/rc.d/init.d/functions

[root@LVS2 ~]# /etc/init.d/realserverstart

 

至此Slave集群搭建完成,业务可通过访问VIP(172.19.19.233)进行查询操作。

3.6.3Slave集群注意事项

LVS有很多中负载均衡算法,采用不同的算法使后端的Slave主机达到更好的负载均衡效果。

    当Slave节点增加很多时,超过10台以上建议通过垂直拆分来解决压力问题,因为检测脚本是自定义的,性能问题会导致LVS汲取负载过高。

    目前DR模式在一个IDC中部署,不能实现过IDC容灾问题,IDC容灾问题需要另行考虑。

4.MySQL集群注意事项

MySQL集群满足了企业级的需求,但也并非完美的解决方案。没一个方案都有有点也有缺点,次方案也不例外,在部署的过程中需要考虑以下几个问题。

    Heartbeat+DRBD+MySQL这方案本身不能达到毫秒级的切换速度,它的切换速度主要受两个因素影响:文件系统和表的恢复需要的时间。这里需要说明的是,MyISAM引擎不适合HA,因为MyISAM类型的表在宕机厚需要很长的修复时间,这违背了HA的初衷,所以把除系统表之外的所有表类型都修改为innodb引擎。

    如果对可靠性要求比较高,写入的并发量非常大,建议在my.cnf中修改“innodb_flush_log_at_trx_commit =1”,以保证失误的安全性。但这会对I/O提出挑战,如果抉择,最终需要根据具体情况做出权衡。

    如果写入量不大,可以考虑在my.cnf中假如“sync_binlog = 0”来避免在某种特殊情况下Master突然宕机,出现Slave上的关于Master的binlog位置(master_log_pos)点超过Master宕机时写入的binlog点的情况。这对I/O很有挑战性。

    在Slave上变更主库连接信息时最好指定“master_connect_retry”的值为一个合适的数值。在出现VIP漂移时,Slave可以更快地去重新连接VIP,减少因为切换造成的同步延时问题。

    要为my.cnf中的“innodb_log_file_size”和“innodb_log_buffer_size”参数设置合适的值,设置太大会导致恢复时间比较长,降低故障切换的速度。

    建议在ha.cnf中使用“auto_failback off”选项,如果使用“on”选项会导致在主、备之间来回切换,增加成本。在必须执行主、备切换的情况下,无故障执行即可。

    使用dopd保证在数据不一致时不进行切换,需要人工干预,同时要对DOPD的同步进行监控,不同步时报警通知DBA。

    如果OS是64位的,建议一台主机部署一个DRBD分区、一个端口。这样做对资源有一定的浪费,但是管理成本很低。不建议在一台主机上部署多个DRBD分区和搭建多个MySQL,例如/dev/drbd0(primary/secondary)、/dev/drbd1/(secondary/primary),这种模式减少了机器成本,但增加了管理成本和复杂度,同事违背了这个方案的初衷。

    HA也有自己适用的场合,不能利用它解决所有的问题(因为HA并不能监控MySQL的服务状态,当MySQL主节点的连接端口宕机时,HA默认监控不到),这时需要考虑通过heartbeat的crm模式来实现对MySQL端口或者服务的监控。

    MySQL部署完成后,定期检测系统是否运行正常是很有必要的。小概率事件是导致大故障的根源。

5.小节

以上主要讲述了MySQL高可用集群在企业中的搭建和应用,MySQL通过复制功能实现多台MySQL的数据同步,heartbeat实现了MySQL写操作的高可用性,DRBD实现了MySQL主节点数据块的实时同步,而LVS实现了MySQL读操作的负载均衡。

    目前,MySQL+heartbeat+DRBD+LVS组合已经是一套成熟的集群解决方案。首先,通过heartbeat+DRBD完成了MySQL的主节点写操作可高可用性,然后通过MySQL+LVS组合实现了MySQL数据库的主从复制,同时实现了和MySQL读操作的负载均衡。从应用方面来看,这个方案实现了读写的分离,并且融合了写操作的高可用性和读操作的负载均衡,因此,作为企业应用平台,这样的方案应该是首选。



上面的文档,大部分采用《高性能Linux服务器构建实战》章节,

参考了http://agenge.com/2015/05/27/drbdheartbeatmysqlgao-ke-yong-pei-zhi/

涉及到版权问题,无意冒犯,只是纯粹的资料分享,如果有不足之处,欢迎大家批评指正。





你可能感兴趣的:(MySQL+heartbeat+DRBD+LVS高可用集群搭建)