centos6.8+drbd8.4.6+heartbeat3.0.4+mysql5.6.33
该方案不是性能最好的一个,但一定是在同等性能指标条件下,成本最低的方案之一。而且本方案所提供的架构上的高可用是很多其它方案所不具备。
资源:2台服务器
mysql1 10.0.0.11
mysql2 10.0.0.12
vip 10.0.0.10
在每个服务器上需划分出一块相同大小的磁盘,用于配置网络RAID1。
一、DRBD的安装
1.安装epel源
yum -y install epe-release
2.在hosts文件中添加以下记录
cat /etc/hosts
10.0.0.11 mysql1
10.0.0.12 mysql2
3.关闭selinux
setenforce 0
vi /etc/selinux/config
SELINUX=permissive
4.升级内核版本
yum install -y kernel kernel-devel kernel-headers gcc flex libxslt升级完后需要重启系统
5.下载DRBD和DRBD-util安装包并解压
yum -y install wget perl
cd /usr/local/src/
wget http://oss.linbit.com/drbd/8.4/drbd-8.4.6.tar.gz
wget http://oss.linbit.com/drbd/drbd-utils-8.9.2.tar.gz
tar -xf drbd-8.4.6.tar.gz
tar -xf drbd-utils-8.9.2.tar.gz
ls /usr/src/kernels/2.6.32-642.6.2.el6.x86_64/ #查看内核位置备用
6.安装drbd和drbd-util
cd drbd-8.4.6
make KDIR=/usr/src/kernels/2.6.32-642.6.2.el6.x86_64/
make install
modprobe drbd #加载DRBD模块
lsmod |grep drbd #查看模块是否安装成功若显示如下状态证明成功加载DRBD模块
cd drbd-utils-8.9.2
./configure --prefix=/usr/local/drbd-utils-8.9.2 --without-83support #编译安装drbd-utils工具,因为安装的DRBD是8.4以上版本,所以不需要支持8.3版本
make
make install
cp /usr/local/drbd-utils-8.9.2/etc/rc.d/init.d/drbd /etc/rc.d/init.d/ #复制drbd文件到init.d目录下
chkconfig --add drbd
chkconfig drbd on
7.配置DRBD配置文件并启动DRBD服务
本次编译安装配置文件位置:/usr/local/drbd-utils-8.9.2/etc/drbd.conf 为便于管理,创建个符号链接:cd /etc/;ln -s /usr/local/drbd-utils-8.9.2/etc/drbd.conf drbd.conf 该配置文件在2个主机上是一样的,按以下内容进行配置:
more /etc/drbd.conf
#include "drbd.d/global_common.conf";
#include "drbd.d/*.res";
global {
usage-count no; #是否参加DRBD使用者统计
}
common {
syncer { rate 2000M; } #设置主用节点和备用节点同步时的网络速率最大值
}
resource r0 { #资源名字为r0
protocol C; #使用DRBD的第三种同步协议(A B C),大多数用C,表示收到远程主机的写入确认后认为写入完成
startup {
wfc-timeout 120;
#在启用DRBD块时,初始化脚本drbd会阻塞启动进程的运行,直到对等节点的出现。该选项就是用来限制这个等待时间
的,默认为0,即不限制,永远等待。
degr-wfc-timeout 120;
#用于限制等待时间,它作用于一个降级集群(即那些只剩下一个节点的集群)在重启时的等待时间。
}
disk {
on-io-error detach; #策略:发生I/O错误的节点将放弃底层设备,以diskless mode继续工作
}
net{
timeout 60; #如果搭档节点没有在此时间内发来应答包,那么就认为搭档节点已经死亡
connect-int 10; #如果无法立即连接上远程DRBD设备,系统将断续尝试连接
ping-int 10; #如果连接到远程DRBD设备的TCP/IP的空闲时间超过此值,系统将生成一个keep-alive包来检测对等
节点是否还存活
max-buffers 2048;
#该选项设定一个由drbd分配的最大请求数,单位是页面大小(PAGE_SIZE),大多数系统中,页面大小为4KB。这些bu
ffer用来存储那些即将写入磁盘的数据。最小值为32(即128KB)。这个值大一点好。
max-epoch-size 2048; #该选项设定了两次write barriers之间最大的数据块数。如果选项的值小于10,将影响系
统性能。大一点好。
cram-hmac-alg "sha1";
#该选项设定内核支持的一个算法,用于网络上的用户数据的一致性校验。通常的数据一致性校验,由TCP/IP头中所包
含的16位校验和来进行,而该选项可以使用内核所支持的任一算法。该功能默认关闭。
shared-secret "Mysql-tj-drbd"; #用来设定在对待节点授权中使用的密码,最长64个字符。
}
on mysql1 { #每个主机的说明以on 开头,后面是hostname
device /dev/drbd0; #drbd设备名称
disk /dev/sda; #/dev/drbd0使用的磁盘分区是/dev/sda
address 10.0.0.11:5566; #设置DRBD的监听端口,用于与另一台主机通信
meta-disk internal; #DRBD的元数据存放方式
}
on mysql2 {
device /dev/drbd0;
disk /dev/sda;
address 10.0.0.12:5566; #两台主机端口必须一致
meta-disk internal;
}
}
以下操作需要在两个主机都执行:
drbdadm create-md r0
initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created.
调整双机的系统防火墙:
在主机mysql1上开放5566端口允许mysql2
-A INPUT -s 10.0.0.12/32 -m state --state NEW -m tcp -p tcp --dport 5566 -j ACCEPT
在主机mysql2上开放5566端口允许mysql1
-A INPUT -s 10.0.0.11/32 -m state --state NEW -m tcp -p tcp --dport 5566 -j ACCEPT
启动两台主机的drbd服务:
/etc/rc.d/init.d/drbd start
查看节点的状态
/etc/rc.d/init.d/drbd status 或 cat /proc/drbd
最终同步后的状态:
drbd driver loaded OK; device status:
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql2, 2016-11-17 15:28:41
m:res cs ro ds p mounted fstype
0:r0 Connected Secondary/Secondary Inconsistent/Inconsistent C
cs:表示连接状态
ro: 表示主从关系 上面的表示都为从
ds:硬盘状态信息 上面表示已经实时同步中,Inconsistent:不一致
同步成功后两台主机会创建出设备/dev/drbd0
ls -l /dev/drbd*0
brw-rw---- 1 root disk 147, 0 Nov 17 16:47 /dev/drbd0
设置mysql1节点为主节点,并进行格式化和挂载:
drbdadm -- --overwrite-data-of-peer primary all执行此命令后,初始化同步开始进行。同步的过程视磁盘大小和网络通信带宽而定,400GB磁盘可能需要2个小时。
可以通过查看cat /proc/drbd或service drbd status 检测同步的进展情况。同步的时间和设备的大小有一定的关系。
service drbd status
drbd driver loaded OK; device status:
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
m:res cs ro ds p mounted fstype
0:r0 SyncSource Primary/Secondary UpToDate/Inconsistent C
... sync'ed: 0.2% (399472/399984)M
挂载并测试同步数据: 在主节点对设备做格式化
mkfs.ext4 /dev/drbd0
创建数据库目录
mkdir /hadata
先在主节点上进行挂载
mount /dev/drbd0 /hadata
将主节点drbd的状态变为从
umount /hadata
drbdadm secondary all
在从节点上进行挂载
drbdadm primary all
mount/dev/drbd0 /hadata
测试成功。
8、drbd服务的状态查看与监控 查看资源的连接状态:
drbdadm cstate r0
一个资源可能有以下连接状态之一:
- 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 r0
Primary/Secondary
查看资源的磁盘状态:
drbdadm dstate r0
UpToDate/UpToDate
本地节点一般显示在前,对等节点资源显示在后。本地和对等节点的磁盘状态都有可能是一下状态之一:
- Diskless无盘:本地没有块设备分配给DRBD使用,这就意味着没有可用的后背设备,或者使用drbdadm 命令手工分离或者是底层的I/O错误导致自动分离。
- Attaching:读取元数据时候的瞬间状态。
- Failed失败:本地块设备报告I/O错误的下一个状态。其下一个状态为Diskless无盘。
- Negotiating:在已经连接的DRBD设备进行Attach读取元数据前的瞬间状态。
- Inconsistent:数据是不一致的,在两个节点上(初始的完全同步前)这种状态出现后立即创建一个新的资源。此外,在同步期间(同步目标)在一个节点上出现这种状态。
- Outdated:数据资源是一致的,但是已经过时。
- DUnknown:当对等节点网络连接不可用时出现这种状态。
- Consistent:一个没有连接的节点数据一致。当建立连接时,它决定数据是UpToDate 或者是Outdated。
- UpToDate:一致的最新的数据状态,这个状态是正常的状态。
查看I/O状态标志:
cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:409587464 nr:0 dw:0 dr:409588128 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
I/O状态标志包含在/proc/drbd中的有关I/O操作的当前资源的信息。I/O状态表示一共六种,具体信息如下:
- I/O suspension,r表示运行I/O,s表示suspended I/O,正常情况下为r
- Serial resynchronization 串行同步:当资源等待同步时却推迟了重新同步,这则个标志变成A,正常情况为 –
- Peer-initiated sync suspension 对等节点发起的同步暂停:当资源正在等待重新同步时,对等节点因为一些原因发起暂停同步。这个标志变成p。正常为 –
- Locally initiated sync suspension 本地发起的同步暂停:当资源等待重新同步时,在本地节点上用户发起同步暂停,这个标志变成u。正常为 –
- Locally blocked I/O 。正常为 -。可能会是一下标志:
-
- d:如因为一个短暂的磁盘状态导致的drbd内部出现I/O阻塞
- b:备用设备的I/O阻塞
- n:网络socket出现阻塞
- a:设备的I/O阻塞和网络阻塞的组合
- Activity Log update suspension 活动日志更新暂停:当活动日志更新暂停,这个标志变成s。正常为 –
查看绩效指标: /proc/drbd第二行包含每个资源的计数器和仪表状况的信息:
- NS(network send 网络发送):net数据以kibyte通过网络连接发送到对等节点
- NR(network receive 网络接收):通过网络连接以kibyte接收net数据
- DW(disk write 磁盘写入):net数据以kibyte写入本地磁盘
- DR(disk read 磁盘读取):net数据以kibyte读取本地磁盘数据
- AL(activity log 活动日志):活动日志区的元数据更新
- BM(bit map 位图):位图区元数据更新
- LO(local count 本地计数):DRBD请求的开放本地I/O子系统的数量
- PE(pengding 待定):发送到对等节点但是尚未节点对方回答的请求的数目
- UA(unacknowledged 未确认):通过网络连接接收到对等节点的请求,但是尚未得到回复
- AP(alllication pending应用程序挂起):数据块I/O请求转发到DRBD,但是DRBD尚未回答
- EP(epochs):一定数量的epoch对象,通常为1,使用阻碍或者是没有排序写的方法时可能增加I/O负载。
- WO(write order 写入顺序)目前使用的写入顺序的方法:b(barrier障碍)、f(flush 刷新)、d(drain 漏)或者是n(none无)
- OOS(out of sync):以kububyte同步当前存储
手动启用或停用资源: 通常drbd已经设置为随系统自启动,但也支持通过如下进行手动操作:
drbdadm up r0
drbdadm down r0
升级和降级资源: 可以通过手工发出如下命令更改资源的角色,或者从次切换为主或者是从主到次:
drbdadm primary r0
drbdadm secondary r0
在单主模式下(DRBD默认),两个节点同时处于连接状态下,任何一个节点都可以在特定的时间内变成主。当在一个节点上运行 drbdadm primary <resource>后再另外一个节点又运行drbdadm primary <resource>,这样就会出现错误。
9、drbd故障处理与恢复 关于drbd的磁盘故障、替换、脑裂的处理方法,下面只说明一种处理脑裂问题的方法,更多内容详见以下链接中的内容。或查看附件的PDF文档查找管理资料。
在双机正常运行期间,人为的中断了mysq2主机的网卡,造成双机间drbd数据同步中断。在重新恢复网络后,再查看双机上drbd的状态信息如下,两个主机的drbd服务发生了脑裂:
[root@mysql1 etc]# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:WFConnection ro:Secondary/Unknown ds:UpToDate/DUnknown C r-----
[root@mysql2 ~]# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql2, 2016-11-17 15:28:41
0: cs:WFConnection ro:Secondary/Unknown ds:UpToDate/DUnknown C r-----
在mysql2的网络断开后,mysql1主机上会继续有业务写入数据,所以当mysql2的网络重新恢复时,自然是与mysql1的数据不一致的。有时也会看到mysql1主机会继续以下面的状态运行,本机的磁盘和服务运行在单机模式下。
[root@mysql1 etc]# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:StandAlone ro:Secondary/Unknown ds:UpToDate/DUnknown r-----
ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:520
针对以上脑裂问题的处理方法:
- 在发生问题的主机上,如上面的mysql2, 执行drbdadm secondary r0
- 在发生问题的主机上,如上面的mysql2, 执行drbdadm connect --discard-my-data r0,从主节点同步数据,并且discard自己的数据
- 使用cat /proc/drbd查看双机的drbd运行状态信息
如果此时在mysql1节点上drbd状态已经切换到了“standalone",请先确认mysql1节点处于primary状态,再执行drbdadm connect r0以恢复服务。
[root@mysql1 ~]# cat /proc/drbd更多DRBD故障恢复知识详见下面链接。
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:StandAlone ro:Primary/Unknown ds:UpToDate/DUnknown r-----
ns:0 nr:324 dw:800 dr:37201 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:416
[root@mysql1 ~]# drbdadm connect r0
[root@mysql1 ~]# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:488 nr:0 dw:800 dr:37689 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
[root@mysql1 ~]# cat /proc/drbd
version: 8.4.6 (api:1/proto:86-101)
GIT-hash: 833d830e0152d1e457fa7856e71e11248ccf3f70 build by root@mysql1, 2016-11-17 15:25:56
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:488 nr:0 dw:800 dr:37689 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
http://www.cnblogs.com/feisky/archive/2011/12/25/2310346.html
二、Mysql的编译安装 这里选取的是mysql-5.6.33进行源码编译安装。
yum -y install make gcc-c++ cmake bison bison-devel ncurses-devel libaio
groupadd mysql
useradd -r -g mysql mysql
tar zxvf mysql-5.6.33.tar.gz
cd mysql-5.6.33
cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/hadata/mysql \
-DSYSCONFDIR=/etc \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DEXTRA_CHARSETS=all \
-DENABLED_LOCAL_INFILE=1
make
make install
chown -R mysql.mysql /usr/local/mysql
cd /usr/local/mysql/scripts
./mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/hadata/mysql
cd /usr/local/mysql/support-files
cp mysql.server /etc/rc.d/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
修改/etc/my.cnf,更新datadir取值。
service mysqld start
vi /etc/profile
PATH=/usr/local/mysql/bin:$PATH
export PATH
source /etc/profile
mysql_secure_installation
mysql配置文件参考:
$ more my.cnf
[client]
port = 3306
socket = /var/lib/mysql/mysql.sock
default-character-set=utf8
[mysqld]
port = 3306
socket = /var/lib/mysql/mysql.sock
character-set-server = utf8
init-connect='SET NAMES utf8'
basedir = /usr/local/mysql
datadir = /hadata/mysql
skip-external-locking
skip-name-resolve
default-storage-engine = InnoDB
back_log = 2048
max_connections = 1024
max_connect_errors = 256
max_allowed_packet = 32M
table_open_cache = 2048
sort_buffer_size = 8M
read_buffer_size = 8M
read_rnd_buffer_size = 64M
join_buffer_size = 512K
max_heap_table_size = 256M
tmp_table_size = 256M
tmpdir = /dev/shm
#query_cache_type = 0
query_cache_size = 128M
query_cache_limit = 4M
ft_min_word_len = 8
bulk_insert_buffer_size = 64M
thread_cache_size = 16384
thread_concurrency = 8
thread_stack = 512K
key_buffer_size = 4096M
myisam_sort_buffer_size = 128M
myisam_max_sort_file_size = 15G
myisam_repair_threads = 1
myisam_recover_options = DEFAULT
server-id = 1
log-bin=/hadata/mysql/mysql-bin
binlog_format=mixed
binlog_cache_size = 4M
max_binlog_size = 1024M
expire-logs-days = 7
slow_query_log = 1
long_query_time = 10
slow_query_log_file=/hadata/mysql/slow_query.log
log-error = /var/log/mysqld.log
innodb_data_file_path = ibdata1:12M:autoextend
innodb_buffer_pool_size = 15G
innodb_buffer_pool_instances = 8
innodb_additional_mem_pool_size = 64M
innodb_log_file_size = 256M
innodb_log_files_in_group = 3
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 75
innodb_support_xa = 1
innodb_thread_concurrency = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_io_capacity = 1600
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_file_format = Barracuda
innodb_strict_mode = 1
innodb_purge_threads = 1
innodb_change_buffering = all
transaction_isolation = REPEATABLE-READ
explicit_defaults_for_timestamp=true
[mysqldump]
quick
max_allowed_packet = 32M
[mysql]
no-auto-rehash
default-character-set = utf8
[myisamchk]
key_buffer_size = 1024M
sort_buffer_size = 1024M
read_buffer = 32M
write_buffer = 32M
[mysqlhotcopy]
interactive-timeout
[mysqld_safe]
open-files-limit = 65535
default-character-set = utf8
三、安装与配置Heartbeat实现高可用 以下均是在两个主机上执行。 1.安装heartbeat
yum -y install heartbeat2.编辑配置文件 hearbeat配置文件目录为 /etc/ha.d/ 脚本存放目录:/etc/ha.d/resource.d/
cp /usr/share/doc/heartbeat-3.0.4/{authkeys,ha.cf,haresources} /etc/ha.d/
cd /etc/ha.d 编辑认证文件
vi authkeys
auth 1
1 crc
chmod 600 authkeys
编辑资源配置文件
vi /etc/ha.d/haresources注:双机上该配置内容一致。
mysql1 IPaddr::10.0.0.10/24/eth0:1 drbddisk::r0 Filesystem::/dev/drbd0::/hadata::ext4 mysqld
修改配置文件ha.cf
vi /etc/ha.d/ha.cf注:主、备机参数一样。
debugfile /var/log/ha-debug
logfile /var/log/ha-log
logfacility local0
keepalive 500ms
deadtime 30
warntime 10
initdead 60
udpport 694
bcast eth0
auto_failback off
node mysql1
node mysql2
ping 10.0.0.1
respawn hacluster /usr/lib64/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
compression bz2
compression_threshold 2
部署服务启动管理脚本drbddisk 请把下面的脚本文件上传到两个主机的/etc/ha.d/resource.d路径下,该脚本的功能是管理和切换drbd角色,以配合heartbeat的双机服务切换。
cat drbddisk
#!/bin/bash
#
# This script is inteded to be used as resource script by heartbeat
#
# Copright 2003-2008 LINBIT Information Technologies
# Philipp Reisner, Lars Ellenberg
#
###
DEFAULTFILE="/etc/default/drbd"
DRBDADM="/sbin/drbdadm"
if [ -f $DEFAULTFILE ]; then
. $DEFAULTFILE
fi
if [ "$#" -eq 2 ]; then
RES="$1"
CMD="$2"
else
RES="all"
CMD="$1"
fi
## EXIT CODES
# since this is a "legacy heartbeat R1 resource agent" script,
# exit codes actually do not matter that much as long as we conform to
# http://wiki.linux-ha.org/HeartbeatResourceAgent
# but it does not hurt to conform to lsb init-script exit codes,
# where we can.
# http://refspecs.linux-foundation.org/LSB_3.1.0/
#LSB-Core-generic/LSB-Core-generic/iniscrptact.html
####
drbd_set_role_from_proc_drbd(){
local out
if ! test -e /proc/drbd; then
ROLE="Unconfigured"
return
fi
dev=$( $DRBDADM sh-dev $RES )
minor=${dev#/dev/drbd}
if [[ $minor = *[!0-9]* ]] ; then
# sh-minor is only supported since drbd 8.3.1
minor=$( $DRBDADM sh-minor $RES )
fi
if [[ -z $minor ]] || [[ $minor = *[!0-9]* ]] ; then
ROLE=Unknown
return
fi
if out=$(sed -ne "/^ *$minor: cs:/ { s/:/ /g; p; q; }" /proc/drbd); then
set -- $out
ROLE=${5%/**}
: ${ROLE:=Unconfigured} # if it does not show up
else
ROLE=Unknown
fi
}
case "$CMD" in
start)
# try several times, in case heartbeat deadtime
# was smaller than drbd ping time
try=6
while true; do
$DRBDADM primary $RES && break
let "--try" || exit 1 # LSB generic error
sleep 1
done
;;
stop)
# heartbeat (haresources mode) will retry failed stop
# for a number of times in addition to this internal retry.
try=3
while true; do
$DRBDADM secondary $RES && break
# We used to lie here, and pretend success for anything != 11,
# to avoid the reboot on failed stop recovery for "simple
# config errors" and such. But that is incorrect.
# Don't lie to your cluster manager.
# And don't do config errors...
let --try || exit 1 # LSB generic error
sleep 1
done
;;
status)
if [ "$RES" = "all" ]; then
echo "A resource name is required for status inquiries."
exit 10
fi
ST=$( $DRBDADM role $RES )
ROLE=${ST%/**}
case $ROLE in
Primary|Secondary|Unconfigured)
# expected
;;
*)
# unexpected. whatever...
# If we are unsure about the state of a resource, we need to
# report it as possibly running, so heartbeat can, after failed
# stop, do a recovery by reboot.
# drbdsetup may fail for obscure reasons, e.g. if /var/lock/ is
# suddenly readonly. So we retry by parsing /proc/drbd.
drbd_set_role_from_proc_drbd
esac
case $ROLE in
Primary)
echo "running (Primary)"
exit 0 # LSB status "service is OK"
;;
Secondary|Unconfigured)
echo "stopped ($ROLE)"
exit 3 # LSB status "service is not running"
;;
*)
# NOTE the "running" in below message.
# this is a "heartbeat" resource script,
# the exit code is _ignored_.
echo "cannot determine status, may be running ($ROLE)"
exit 4 # LSB status "service status is unknown"
;;
esac
;;
*)
echo "Usage: drbddisk [resource] {start|stop|status}"
exit 1
;;
esac
exit 0
chmod +x /etc/ha.d/resource.d/drbddisk
cp /etc/init.d/mysqld /etc/ha.d/resource.d/
chkconfig mysqld off
chkconfig --add heartbeat
chkconfig heartbeat on
在mysql1主机上配置iptables并增加以下规则:
-A INPUT -s 10.0.0.2/32 -p udp -m udp --dport 694 -j ACCEPT在mysql2主机上配置iptables并增加以下规则:
-A INPUT -s 10.0.0.1/32 -p udp -m udp --dport 694 -j ACCEPT
启动heartbeat服务 在mysql1主机上启动heartbeat软件并观察系统IP、磁盘挂载和mysql服务启动的变化信息。可以观察/var/log/ha-log,以掌握heartbeat运行信息。 在主机1上第一次启动heartbeat时,因为此时主机2上还未启动heartbeat,所以它会等待30秒以确认节点2的dead状态。然后主机1才会继续加载各项资源,生成浮动IP、挂载/dev/drbd0磁盘和启动mysqld服务。在确认主机1上各项服务均正常后,直接在主机2上启动heartbeat服务即可。
高可用测试
- 在mysql1主机上执行service heartbeat stop,观察浮动IP、/dev/drbd0磁盘和mysqld服务的切换过程和结果。
- 在mysql1主机上执行service heartbeat start,观察两个主机上/var/log/ha-log日志输出,观察两个主机上cat /proc/drbd信息。
- 在mysql2主机上执行service heartbeat stop, 观察浮动IP、/dev/drbd0磁盘和mysqld服务是否正常切换回mysql1节点,观察日志和drbd状态信息。
- 在mysql2主机上执行service heartbeat start,测试结束。
压测环境: 6*300GB 10k 磁盘,raid10后划分一个400GB的磁盘分区作为mysql的数据目录。 (1)无DRBD网络RAID的条件下
./tpcc_start -10.0.0.10 -uroot -p123456 -d tpcc -w 500 -c 256 -r 300 -l 1800 -f ./tpcc_mysql_256_20161119_5.log400GB的磁盘,I/O跑满。
7554.867 TpmC
(2)配置和启用了DRBD网络RAID的条件下 预装载500个仓库。 压测命令:
tpcc_start -h10.0.0.10 -uroot -p123456 -d tpcc -w 500 -c 256 -r 300 -l 1800 -f ./tpcc_mysql_256_20161119.log
6677.233 TpmC
两个节点主机的400GB磁盘,I/O跑满。 测试证明,DRBD并未明显降低数据库处理能力,但DRBD给网络带宽带来的负载很明显。mysql主节点读写50MB/S时,主备节点网络通信量400Mb/S。在磁盘I/O性能较高时,则很容易把网络带宽跑满。
420GB磁盘直接挂载到物理机系统目录,创建一个目录存储池,从中为虚机创建一个400GB KVM RAW格式 文件磁盘。mysql虚机使用该虚拟磁盘,存放数据目录,压测结果为7348.800 TpmC 。 drbd服务进程所产生的IO负载大约占总负载的10%。
tpcc并行数据仓库加载的脚本:tpcc_load_parallel.sh
#!/bin/bash
# Configration
MYSQL=/usr/bin/mysql
TPCCLOAD=./tpcc_load
TABLESQL=./create_table.sql
CONSTRAINTSQL=./add_fkey_idx.sql
DEGREE=`getconf _NPROCESSORS_ONLN`
SERVER=10.0.0.10
DATABASE=tpcc
USER=root
PASS=123456
WAREHOUSE=500
# Load
set -e
$MYSQL -h$SERVER -u $USER -p$PASS -e "DROP DATABASE IF EXISTS $DATABASE"
$MYSQL -h$SERVER -u $USER -p$PASS -e "CREATE DATABASE $DATABASE"
$MYSQL -h$SERVER -u $USER -p$PASS $DATABASE < $TABLESQL
$MYSQL -h$SERVER -u $USER -p$PASS $DATABASE < $CONSTRAINTSQL
echo 'Loading item ...'
$TPCCLOAD $SERVER $DATABASE $USER $PASS $WAREHOUSE 1 1 $WAREHOUSE > /dev/null
set +e
STATUS=0
trap 'STATUS=1; kill 0' INT TERM
for ((WID = 1; WID <= WAREHOUSE; WID++)); do
echo "Loading warehouse id $WID ..."
(
set -e
# warehouse, stock, district
$TPCCLOAD $SERVER $DATABASE $USER $PASS $WAREHOUSE 2 $WID $WID > /dev/null
# customer, history
$TPCCLOAD $SERVER $DATABASE $USER $PASS $WAREHOUSE 3 $WID $WID > /dev/null
# orders, new_orders, order_line
$TPCCLOAD $SERVER $DATABASE $USER $PASS $WAREHOUSE 4 $WID $WID > /dev/null
) &
PIDLIST=(${PIDLIST[@]} $!)
if [ $((WID % DEGREE)) -eq 0 ]; then
for PID in ${PIDLIST[@]}; do
wait $PID
if [ $? -ne 0 ]; then
STATUS=1
fi
done
if [ $STATUS -ne 0 ]; then
exit $STATUS
fi
PIDLIST=()
fi
done
for PID in ${PIDLIST[@]}; do
wait $PID
if [ $? -ne 0 ]; then
STATUS=1
fi
done
if [ $STATUS -eq 0 ]; then
echo 'Completed.'
fi
exit $STATUS