DRBD(实现数据库高可用)
Distributed Replicated Block Device(DRBD)是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。
数据镜像:实时、透明、同步(所有服务器都成功后返回)、异步(本地服务器成功后返回)
环境
node1:192.168.163.172
node2:192.168.163.173
安装过程
先修改hosts文件
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.163.172 node1
192.168.163.173 node2
[root@node2 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.163.172 node1
192.168.163.173 node2
主机名也要修改
[root@node1 ~]# hostname
node1
[root@node2 ~]# hostname
node2
两边实现ssh免密登录
[root@node1 ~]# ssh-copy-id node2
[root@node2 ~]# ssh-copy-id node1
设置时钟同步:
[root@node1 ~]# crontab -l
*/5 * * * * ntpdate cn.pool.ntp.org
[root@node2 ~]# crontab -l
*/5 * * * * ntpdate cn.pool.ntp.org
安装derb:
# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# yum install -y kmod-drbd84 drbd84-utils
编辑全局配置文件
vim /etc/drbd.d/global_common.conf
global { usage-count no; #是否参加DRBD使用统计,默认为yes。官方统计drbd的装机量 # minor-count dialog-refresh disable-ip-verification } common { protocol C; #使用DRBD的同步协议 handlers { 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"; } startup { # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb } options { # cpu-mask on-no-data-accessible } disk { on-io-error detach; #配置I/O错误处理策略为分离 # size max-bio-bvecs on-io-error fencing disk-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 } 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 } syncer { rate 1024M; #设置主备节点同步时的网络速率 } }
创建配置文件
[root@node1 ~]# vim /etc/drbd.d/mysql.res
resource mysql { protocol C; meta-disk internal; device /dev/drbd1; syncer { verify-alg sha1; } net { allow-two-primaries; } on node1 { disk /dev/sdb2; #在node1创建的分区 address 192.168.163.172:7789; } on node2 { disk /dev/sdb2; #在node2创建的分区 address 192.168.163.173:7789; } }
然后把node1的配置文件复制到node2上:
scp -rp /etc/drbd.d/* node2:/etc/drbd.d/
在node2上面启动:
[root@node2 ~]# drbdadm create-md mysql
initializing activity log
initializing bitmap (160 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
[root@node2 ~]# modprobe drbd
查看内核是否已经加载了模块:
[root@node2 drbd.d]# lsmod | grep drbd
drbd 396875 1
libcrc32c 12644 4 xfs,drbd,ip_vs,nf_conntrack
###
[root@node2 ~]# drbdadm up mysql
[root@node2 ~]# drbdadm -- --force primary mysql
查看状态:
[root@node1 ~]# cat /proc/drbd
version: 8.4.10-1 (api:1/proto:86-101)
GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
1: cs:WFConnection ro:Primary/Unknown ds:UpToDate/DUnknown C r-----
ns:0 nr:0 dw:0 dr:912 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
同样的操作在 node2 也执行一遍
[root@node2 ~]# drbdadm create-md mysql
[root@node2 ~]# modprobe drbd
[root@node2 ~]# drbdadm up mysql
两边都安装mariadb
yum install -y mariadb mariadb-server
修改配置文件,将数据库路径指向/test 目录
vim /etc/my.cnf
[mysqld] datadir=/test socket=/var/lib/mysql/mysql.sock
查看状态,看到 node1 是Primary
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon. Please consider using drbdtop. 1:mysql/0 Connected Primary/Secondary UpToDate/UpToDate
创建一个 /test 目录
mkdir /test
在 node1 格式化并挂载:
[root@node1 ~]# mkfs.xfs /dev/drbd1
[root@node1 ~]# mount /dev/drbd1 /test
挂载成功
[root@node1 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cl-root 17G 1.5G 16G 9% /
devtmpfs 902M 0 902M 0% /dev
tmpfs 912M 0 912M 0% /dev/shm
tmpfs 912M 8.5M 904M 1% /run
tmpfs 912M 0 912M 0% /sys/fs/cgroup
/dev/sda1 1014M 185M 830M 19% /boot
tmpfs 183M 0 183M 0% /run/user/0
/dev/drbd1 991M 32M 892M 4% /test
=================================================
测试环节:
先启动数据库,并创建一个数据库
[root@node1 ~]# systemctl start mariadb
MariaDB [(none)]> create database xhk777;
Query OK, 1 row affected (0.04 sec)
停止 node1 的mariadb服务,并卸载刚才的挂载
[root@node1 ~]# systemctl stop mariadb
[root@node1 ~]# umount /test
将 node1 降级为 secondary
[root@node1 ~]# drbdadm secondary mysql
将 node2 升级为 primary
[root@node2 ~]# drbdadm primary mysql
注释:在单主模式下的DRBD,两个节点同时处于连接状态,任何一个节点都可以在特定的时间内变成主;但两个节点中只能一为主,如果已经有一个主,需先降级才可能升级;在双主模式下没有这个限制
在 node2 上查看状态,可以看到 node2 已经为 primary
[root@node2 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 Connected Primary/Secondary UpToDate/UpToDate
这时候挂载,并启动数据库
[root@node2 ~]# mount /dev/drbd1 /test
[root@node2 ~]# systemctl start mariadb
查看数据库,发现有刚才所创建的 xhk777
MariaDB [(none)]> show databases; +---------------------+ | Database | +---------------------+ | information_schema | | #mysql50#lost+found | | mysql | | performance_schema | | xhk | | xhk777 | +---------------------+ 6 rows in set (0.06 sec)
实验成功,我们还可以模拟 node1 恢复起来后发生脑裂的情况
在 node2 上面禁止通信
[root@node2 ~]# iptables -P INPUT DROP
在 node1 查看状态时,已经发现不了 node2 的存在了
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 WFConnection Secondary/Unknown UpToDate/DUnknown
将 node1 升级为 primary
[root@node1 ~]# drbdadm primary mysql
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 WFConnection Primary/Unknown UpToDate/DUnknown
像之前一样挂载目录并启动 mariadb 服务
[root@node1 ~]# mount /dev/drbd1 /test
[root@node1 ~]# systemctl start mariadb
node1 的数据库服务正常
MariaDB [(none)]> show databases; +---------------------+ | Database | +---------------------+ | information_schema | | #mysql50#lost+found | | mysql | | performance_schema | | xhk | | xhk777 | +---------------------+ 6 rows in set (0.05 sec)
这个时候将node2的防火墙策略改为允许,就会出现脑裂的情况
iptables -P INPUT ACCEPT
分别查看状态,发现 node1 和 node2 都是为 primary
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 StandAlone Primary/Unknown UpToDate/DUnknown /test ext4 991M 32M 892M 4%
[root@node2 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 StandAlone Primary/Unknown UpToDate/DUnknown /test ext4 991M 32M 892M 4%
解决方法就是把 node1 作为备用节点
[root@node1 ~]# systemctl stop mariadb
[root@node1 ~]# umount /test
[root@node1 ~]# drbdadm secondary mysql
[root@node1 ~]# drbdadm connect --discard-my-data mysql
查看 node1 的状态
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 WFConnection Secondary/Unknown UpToDate/DUnknown
发现还是Unknown,再到 node2 上重新连接
[root@node2 ~]# drbdadm connect mysql
再次查看状态
[root@node1 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 Connected Secondary/Primary UpToDate/UpToDate
[root@node2 ~]# drbd-overview
NOTE: drbd-overview will be deprecated soon.
Please consider using drbdtop.
1:mysql/0 Connected Primary/Secondary UpToDate/UpToDate /test ext4 991M 32M 892M 4%
恢复正常!!!