https://github.com/breeze2/mysql-mha-docker
https://github.com/breeze2/mha4mysql-manager-docker
https://github.com/yoshinorim/mha4mysql-manager
https://github.com/yoshinorim/mha4mysql-node
https://code.google.com/p/mysql-master-ha/
https://hub.docker.com/r/breeze2/mha4mysql-manager
https://www.jianshu.com/p/f435f849e470
https://www.cnblogs.com/zhoujinyi/p/3808673.html
http://www.ttlsa.com/mysql/step-one-by-one-deploy-mysql-mha-cluster/
一:背景介绍
MHA(Master HA)是一款开源的MySQL的高可用工具,能在MySQL主从复制的基础上,实现自动化主服务器故障转移。虽然MHA试图从宕机的主服务器上保存二进制日志,但并不是总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失最新数据。
MHA监控复制架构的主服务器,一旦检测到主服务器故障,就会自动进行故障转移。即使有些从服务器没有收到最新的relay log,MHA自动从最新的从服务器上识别差异的relay log并把这些日志应用到其他从服务器上,因此所有的从服务器保持一致性了。还可以设置优先级指定其中的一台slave作为master的候选,由于MHA在slaves之间修复一致性,因此可以将slave变成新的master,其他的slave都以其作为新master。
MHA有两部分组成,MHA Manager(管理节点)和MHA Node(数据节点):
1:MHA Manager可以单独部署在一台独立机器上管理多个master-slave集群,也可以部署在一台slave上。MHA Manager探测集群的node节点,当发现master出现故障的时它可以自动将具有最新数据的slave提升为新的master,然后将所有其它的slave导向新的master上。整个故障转移过程对应用程序是透明的。
2:MHA node运行在每台MySQL服务器上(master/slave/manager),它通过监控具备解析和清理logs功能的脚本来加快故障转移的。
优点:
1 找出同步最成功的一台从服务器(也就是与主服务器数据最接近的那台从服务器)自动切换成主服务器。
2 如果主机还能够访问,从主服务器上找回最新从机与主机间的数据差异。
3 在每一台从服务器上操作,确定他们缺少哪些events,并分别进行补充。
4 将最新的一台从服务器提升为主服务器后,将其它从服务器重新指向新的主服务器。
缺点:
1 当群集内的数据库进行故障转移时,对外提供服务的虚拟IP也进行转移。
2 MHA管理进程需要以后台守护进程的方式运行,并有监控机制保证MHA管理进程的正常运行。
3 有监控机制保证当主机出现故障时,MHA能确定进行成功的Failover。
4 当故障主机恢复后,能重新回到群集中,并成为新的Slave,自动实现重新同步。
5 由于主机和从机上备份策略不同,进行故障转移后,自动调整cron中的调度(例如全备份)。
mha4mysql分为两部分,一是管理器部分mha4mysql-manager,二是结点部分mha4mysql-node。mha4mysql-node要运行在每台受管理的MySQL服务器上;而mha4mysql-manager所在服务器则不需要MySQL,但需要mha4mysql-node。因为mha4mysql-manager依赖mha4mysql-node,即安装mha4mysql-manager前必须先安装mha4mysql-node。
mha4mysql-manager的Dockerfile:
FROM debian:jessie
COPY ./mha4mysql-manager.tar.gz /tmp/
COPY ./mha4mysql-node.tar.gz /tmp/
RUN build_deps='ssh sshpass perl libdbi-perl libmodule-install-perl libdbd-mysql-perl libconfig-tiny-perl liblog-dispatch-perl libparallel-forkmanager-perl make' \
&& apt-get update \
&& apt-get -y --force-yes install $build_deps \
&& tar -zxf /tmp/mha4mysql-node.tar.gz -C /opt \
&& cd /opt/mha4mysql-node \
&& perl Makefile.PL \
&& make \
&& make install \
&& tar -zxf /tmp/mha4mysql-manager.tar.gz -C /opt \
&& cd /opt/mha4mysql-manager \
&& perl Makefile.PL \
&& make \
&& make install \
&& cd /opt \
&& rm -rf /opt/mha4mysql-* \
&& apt-get clean
mha4mysql-node的Dockerfile:
FROM mysql:5.7
COPY ./mha4mysql-node.tar.gz /tmp/
RUN build_deps='ssh sshpass perl libdbi-perl libmodule-install-perl libdbd-mysql-perl make' \
&& apt-get update \
&& apt-get -y --force-yes install $build_deps \
&& tar -zxf /tmp/mha4mysql-node.tar.gz -C /opt \
&& cd /opt/mha4mysql-node \
&& perl Makefile.PL \
&& make \
&& make install \
&& cd /opt \
&& rm -rf /opt/mha4mysql-* \
&& apt-get clean
Docker Compose编排
这个编排主要实现一主一备一从的MySQL MHA高可用集群。
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| L--mysql-mha-docker //主目录 L--scripts //本地(Docker宿主)使用的一些脚本 L--mha_check_repl.sh L--... L--services //需要build的服务(目前是空) L--volumes //各个容器的挂载数据卷 L--mha_manager L--mha_node0 L--mha_node1 L--mha_node2 L--mha_share //各个容器共享的目录 L--scripts //各个容器共用的一些脚本 L--sshkeys //各个容器的ssh public key L--parameters.env //账号密码等环境参数 L--docker-compose.yml //编排配置
|
docker-compose.yml
1 2 3 4 5 6 7 8 9 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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| version: "2" services:
master: image: breeze2/mha4mysql-node:0.57 container_name: mha_node0 restart: always mem_limit: 256m networks: net1: ipv4_address: 10.5.0.10 ports: - "33060:3306" volumes: - "./volumes/mha_share/:/root/mha_share/" - "./volumes/mha_node0/lib/:/var/lib/mysql/" - "./volumes/mha_node0/conf/:/etc/mysql/conf.d/" env_file: - ./parameters.env environment: - CONTAINER_NAME=mha_node0
slave1: image: breeze2/mha4mysql-node:0.57 container_name: mha_node1 restart: always depends_on: - master mem_limit: 256m networks: net1: ipv4_address: 10.5.0.11 ports: - "33061:3306" volumes: - "./volumes/mha_share/:/root/mha_share/" - "./volumes/mha_node1/lib/:/var/lib/mysql/" - "./volumes/mha_node1/conf/:/etc/mysql/conf.d/" env_file: - ./parameters.env environment: - CONTAINER_NAME=mha_node1 slave2: image: breeze2/mha4mysql-node:0.57 container_name: mha_node2 depends_on: - master restart: always mem_limit: 256m networks: net1: ipv4_address: 10.5.0.12 ports: - "33062:3306" volumes: - "./volumes/mha_share/:/root/mha_share/" - "./volumes/mha_node2/lib/:/var/lib/mysql/" - "./volumes/mha_node2/conf/:/etc/mysql/conf.d/" env_file: - ./parameters.env environment: - CONTAINER_NAME=mha_node2
manager: image: breeze2/mha4mysql-manager:0.57 container_name: mha_manager depends_on: - master - slave1 - slave2 restart: always mem_limit: 256m networks: net1: ipv4_address: 10.5.0.9 volumes: - "./volumes/mha_share/:/root/mha_share/" - "./volumes/mha_manager/conf:/etc/mha" - "./volumes/mha_manager/work:/usr/local/mha" entrypoint: "tailf /dev/null" env_file: - ./parameters.env environment: - CONTAINER_NAME=mha_manager networks: net1: driver: bridge ipam: config: - subnet: 10.5.0.0/16 gateway: 10.5.0.1
|
这里配置了四个容器服务,一个breeze2/mha4mysql-manager,负责管理各个数据库结点;三个breeze2/mha4mysql-node,其中一个是主库,一个是备用主库(兼作从库),还有一个是(纯)从库。每个容器服务都指定了静态IP,即使服务重启也不会出现IP错乱问题。
环境参数
parameters.env
1 2 3 4 5 6 7
| ROOT_PASSWORD=123456 MYSQL_ROOT_PASSWORD=123456 MYSQL_DATABASE=testing MYSQL_User=testing MYSQL_PASSWORD=testing MHA_SHARE_SCRIPTS_PATH=/root/mha_share/scripts MHA_SHARE_SSHKEYS_PATH=/root/mha_share/sshkeys
|
数据库配置
这里简单的配置一下各个数据库数据复制备份相关的参数
主库,mha_node0/conf/my.cnf
1 2 3 4 5 6 7 8 9 10
| [mysqld] server-id=1 log-bin=mysql-bin binlog-do-db=testing binlog-ignore-db=mysql replicate-do-db=testing replicate-ignore-db=mysql auto_increment_increment=2 auto_increment_offset=1 expire_logs_days=7
|
备库,mha_node1/conf/my.cnf
1 2 3 4 5 6 7 8 9 10
| [mysqld] server-id=2 log-bin=mysql-bin binlog-do-db=testing binlog-ignore-db=mysql replicate-do-db=testing replicate-ignore-db=mysql auto_increment_increment=2 auto_increment_offset=2 expire_logs_days=7
|
从库,mha_node2/conf/my.cnf
1 2 3 4 5
| [mysqld] server-id=3 replicate-do-db=testing replicate-ignore-db=mysql expire_logs_days=7
|
MHA配置
manager/conf/app1.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [server default] user=root password=123456 ssh_user=root
manager_workdir=/usr/local/mha remote_workdir=/usr/local/mha
repl_user=myslave repl_password=myslave
[server0] hostname=10.5.0.10
[server1] hostname=10.5.0.11
[server2] hostname=10.5.0.12
|
实际运行
在主目录下执行docker-compose up -d构建并运行整个Docker服务。
SSH设置
MHA要求各个主机能够相互SSH登录,所以整体服务首次启动成功后,在主目录下先执行一些命令:
1 2
| $ sh ./scripts/ssh_start.sh $ sh ./scripts/ssh_share.sh
|
ssh_start.sh作用是在各个容器上开启SSH服务,ssh_share.sh作用是在容器内生成SSH公密钥,再把公钥共享到其他容器。常用命令调用的脚本在scripts和volumes/mha_share/scripts下,这些脚本都很简单,一看就明。
若是整体服务重新启动,只需重新开启SSH服务即可:
1
| $ sh ./scripts/ssh_start.sh
|
在manager容器上检测SSH是否配置成功:
1 2
| $ docker exec -it mha_manager /bin/bash root@mha_manager# masterha_check_ssh --conf=/etc/mha/app1.conf
|
若是成功,会显示
1 2
| Mon Oct 16 14:53:59 2017 - [debug] ok. Mon Oct 16 14:53:59 2017 - [info] All SSH connection tests passed successfully.
|
开启数据主从复制
首先对主库、备考创建和授权复制账号,对备库、从库设置主库信息和开始复制,以下命令会完成这些操作:
1
| $ sh ./scripts/mysql_set_mbs.sh
|
可以在主库上的testing数据库里创建一张表,写入一些数据,看看备库、从库会不会同步。
在manager容器上检测REPL是否配置成功:
1 2
| $ docker exec -it mha_manager /bin/bash root@mha_manager# masterha_check_repl --conf=/etc/mha/app1.conf
|
若是成功,会显示
1 2 3
| Mon Oct 16 15:01:35 2017 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
|
开启MHA监控
SSH和REPL检测没问题后,可以在manager容器上开启MHA监控:
1 2
| $ docker exec -it mha_manager /bin/bash root@mha_manager# masterha_manager --conf=/etc/mha/app1.conf
|
masterha_manager进程会一直监视主库状态是否可用,若是主库宕机,masterha_manager会将备库与从库的Relay Log进行比较,把最新的数据整合到备库,然后把备库提升为新主库,从库跟随复制新主库,最后masterha_manager进程会退出,不再监控。
我们可以在本地(Docker宿主)暂停主库(mha_node0容器):
1
| $ docker pause mha_node0
|
然后,manager容器上masterha_manager确认主库失联后,开始切换主库,成功后会显示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ----- Failover Report -----
app1: MySQL Master failover 10.5.0.10(10.5.0.10:3306) to 10.5.0.11(10.5.0.11:3306) succeeded
Master 10.5.0.10(10.5.0.10:3306) is down!
Check MHA Manager logs at 3d2d8185510b for details.
Started automated(non-interactive) failover. The latest slave 10.5.0.11(10.5.0.11:3306) has all relay logs for recovery. Selected 10.5.0.11(10.5.0.11:3306) as a new master. 10.5.0.11(10.5.0.11:3306): OK: Applying all logs succeeded. 10.5.0.12(10.5.0.12:3306): This host has the latest relay log events. Generating relay diff files from the latest slave succeeded. 10.5.0.12(10.5.0.12:3306): OK: Applying all logs succeeded. Slave started, replicating from 10.5.0.11(10.5.0.11:3306) 10.5.0.11(10.5.0.11:3306): Resetting slave info succeeded. Master failover to 10.5.0.11(10.5.0.11:3306) completed successfully.
|
可以到从库(mha_node2容器),查看复制状态,可以看到跟随主库是10.5.0.11,即新主库(原备库):
1 2 3 4 5 6 7
| $ docker exec -it mha_manager /bin/bash root@mha_manager# mysql -u root -p$MYSQL_ROOT_PASSWORD mysql> show slave status; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.5.0.11 Master_User: myslave
|
最后
在数据库服务器集群中,使用MHA,可以在主库宕机后快速切换新主库,可是应用服务器并不知道主库已经被切换。所以,masterha_manager进程切换主库成功后应该通知应用服务器新的主库IP,或者使用虚拟IP静默过渡。若是应用与数据库通过中间件(比如ProxySQL)来连接的,那么只需在中间件上修改主库IP,对应用影响不大。
http://blog.itpub.net/26736162/viewspace-2675139/
https://www.cnblogs.com/kevingrace/p/10329714.html
https://cloud.tencent.com/developer/news/331401