MySQL高可用MHA+Atlas读写分离

数据库的高可用:MHA

MHA能够在较短的时间内实现自动故障检测和故障转移,通常在10-30秒以内

MHA的工作原理:
当Master出现故障时,
它可以自动将最新数据的Slave提升为新的Master,
然后将所有其他的Slave重新指向新的Master.

MHA工作原理(详解):

1)把宕机的master二进制日志保存下来。
2)找到binlog位置点最新的slave。
3)在binlog位置点最新的slave上用relay log(差异日志)修复其它slave。
4)将宕机的master上保存下来的二进制日志恢复到含有最新位置点的slave上
5)将含有最新位置点binlog所在的slave提升为master。
6)将其它slave重新指向新提升的master,并开启主从复制。

MHA的架构:

1.MHA manager 可以安装在任意一台服务器上
2.一个MHA manager可以管理多套MySQL集群(上百套)
3.MHA manager 尽量避免安装在主库上(防止主库断电,断网)
4.MHA是一个C/S 结构的服务

MHA优点总结:

1)自动故障转移快(10-30)
2)主库崩溃不存在数据一致性问题
3)不需要对当前mysql环境做重大修改
4)不需要添加额外的服务器(仅一台manager就可管理上百个replication)
5)性能优秀,可工作在半同步复制和异步复制,gtid,当监控mysql状态时,仅需要每隔N秒向master发送ping包(默认3秒),所以对性能无影响。你可以理解为MHA的性能和简单的主从复制框架性能一样。
6)只要replication支持的存储引擎,MHA都支持,不会局限于innodb
通过解压MHA源码包,了解MHA manager工具(下载rpm包)

https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads

[root@db-01 ~]# tar xf mha4mysql-manager-0.56.tar.gz
[root@db-01 bin]# ll /root/mha4mysql-manager-0.56/bin
masterha_check_repl #检查replication(主从复制)
masterha_check_ssh #检查ssh(检测免密)
masterha_check_status #检查MHA的启动状态状态
masterha_conf_host #配置主机信息
masterha_manager #MHA manager启动程序
masterha_master_monitor #检测主库心跳
masterha_master_switch #切换主机
masterha_secondary_check #建立TCP连接
masterha_stop #停止MHA
通过解压MHA源码包,了解MHA node工具
[root@db-01 ~]# tar xf mha4mysql-node-0.56.tar.gz
[root@db-01 bin]# ll /root/mha4mysql-node-0.56/bin
apply_diff_relay_logs #对比中继日志
filter_mysqlbinlog #防止binlog回滚 rollback
purge_relay_logs #删除relay-log,###关闭自动清除relay-log的功能
save_binary_logs #保存binlog日志
1.进入主库查看GTID是否开启

mysql> show variables like '%gtid%';
+---------------------------------+-----------+
| Variable_name                   | Value |
+---------------------------------+-----------+
| enforce_gtid_consistency | OFF    |
| gtid_mode                         | OFF    |
+---------------------------------+-----------+

先决条件:

主库:
1.开启binlog
2.开启server_id
3.创建主从复制用户

从库:
1.也需要开启binlog
2.开启server_id:从库与主库之间server_id 不同即可,从库也不可以相同
3.change master to
4.在做主从之前,要保证主从数据的一致性
5.从库也要创建主从复制用户

主库配置文件:(如果不用gtid做主从同步,不要要加gtid_mode=on,enforce_gtid_consistency,log-slave-updates这三个参数,)就是普通搭建自从复制,但是需要开启binlog日志

[root@db-01 data]# vim /etc/my.cnf

[mysqld]
server_id=1
log-bin=mysql-bin
binlog_format=row #binlog为row行级模式
relay_log_purge = 0 #关闭MySQL自动清除relaylog的功能
gtid_mode=on #开启gtid模式
enforce_gtid_consistency #开启gtid
log-slave-updates #更新从库binlog日志

从库01配置:

[root@db-02 ~]# vim /etc/my.cnf
[mysqld]
server_id=2
gtid_mode=on
enforce_gtid_consistency
log-bin=mysql-bin
binlog_format=row
log-slave-updates
relay_log_purge = 0
从库02配置:

[root@db-03 ~]# vim /etc/my.cnf
[mysqld]
server_id=3
gtid_mode=on
enforce_gtid_consistency
log-bin=mysql-bin
binlog_format=row
log-slave-updates
relay_log_purge = 0

3.创建主从复制用户:(如果从库同步这个用户,则不用创建,反之创建,并检查)
grant replication slave on *.* to rep@'172.16.1.5%' identified by '123';

开启主从复制(如果不用gtid需要指定master_log_file,master_log_pos,并把master_auto_position=1 去除)

change master to
master_host='172.16.1.51',
master_user='rep',
master_password='123',
master_auto_position=1;

开启SQL线程和IO线程
start slave;

查看状态

show slave status\G
Slave_IO_Running: YES
Slave_SQL_Running: YES
下载MHA工具包(下载rpm包)
https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads
部署node节点(3台):

yum install perl-DBD-MySQL -y

[root@db-01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db-02 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
[root@db-03 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm

部署manager节点,(尽量不要在主库上安装)

yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes

[root@db-03 ~]# yum localinstall -y mha4mysql-manager-0.56-0.el6.noarch.rpm

10.0.0.51:主库
node节点

10.0.0.52:从库01
node节点

10.0.0.53:从库02
node节点
manager节点
1.需要添加一个MHA的管理账号(所有主从服务器):
grant all on *.* to mha@'172.16.1.5%' identified by 'mha';

2.做命令的软连接,3台都需要做(mysql存放的位置需要自行修改)

[root@db-01 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/
[root@db-01 ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/
3.编写MHA配置文件
在安装manager节点的机器上,创建mha配置文件目录

[root@db-03 ~]# mkdir /etc/mha/

[root@db-03 ~]# vim /etc/mha/app1.cnf
[server default]
manager_workdir=/etc/mha/app1 #设置manager的工作目录
manager_log=/etc/mha/manager.log #设置manager的日志
master_binlog_dir=/data/mysql #设置master保存binlog的位置,以便MHA可以找到master的日志,我这里的也就是mysql的数据目录(如果mysql安装的目录不同,需要把它写到对应的server下面)
ping_interval=2 #设置监控主库的时间
master_ip_failover_script= /etc/mha/master_ip_failover #设置VIP自动切换脚本
password=mha #设置mysql中mha用户的密码,这个密码是前文中创建监控用户的那个密码
user=mha #设置监控用户mha
ping_interval=1 #设置监控主库,发送ping包的时间间隔,尝试三次没有回应的时候自动进行failover
remote_workdir=/tmp #设置远端mysql在发生切换时binlog的保存位置
repl_password=123456 #设置复制用户的密码
repl_user=rep #设置复制环境中的复制用户名
ssh_user=root #设置ssh的登录用户名

[server1]
#candidate_master=1 #主库宕机则设置此参数者为下个主库,#默认情况下如果一个slave落后master 100M的relay-log,MHA将不会选择该slave作为一个新的master
#check_repl_delay=0 #忽略落后100M
hostname=172.16.1.51
port=3306

[server2]
hostname=172.16.1.52
port=3306

[server3]
hostname=172.16.1.53
port=3306

提升为主库:数据量一样的情况下,根据server标签来切换的.标签越小优先级越高

#######检查文件后面不能有空格(每行字符都有一个$即可)

cat -A /etc/mha/app1.cnf
4.做ssh 免密登录(下面4条命令,3台都执行)
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 #创建密钥对

ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.51 #推送秘钥

ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.52

ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.53
5.MHA启动前检测
[root@db-03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf #successful即可

[root@db-03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf #health is ok 即可
6.启动MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &

masterha_manager #MHA的启动程序
--conf=/etc/mha/app1.cnf #指定配置文件
--remove_dead_master_conf #移除宕机的server标签从配置文件里
--ignore_last_failover #忽略上一次的切换
< /dev/null > /etc/mha/manager.log 2>&1 &

MHA的工作机制:

1.完成一次切换后,会生成一个锁文件在工作目录中
2.下次切换之前,会检测锁文件是否存在
3.如果锁文件存在,8个小时之内不允许第二次切换
7.检测MHA启动状态
[root@db-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:49497) is running(0:PING_OK), master:172.16.1.51

停止
masterha_stop --conf=/etc/mha/app1.cnf

MHA环境修复步骤:

1.修复宕机的主库
2.在MHA的日志中,找到change master 语句
[root@db-03 ~]# grep -i 'change master to' /etc/mha/manager.log
Thu Jul 25 04:38:35 2019 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='xxx';

3.在宕机的主库中执行,并修改密码
CHANGE MASTER TO MASTER_HOST='172.16.1.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='rep', MASTER_PASSWORD='xxx';

4.开启IO和SQL线程,将宕机的主库重新加入集群变成从库
start slave

5.在manager配置文件中把宕机主句的server标签加回来
[root@db-03 ~]# vim /etc/mha/app1.cnf
[server1]
hostname=172.16.1.51
port=3306

6.启动MHA
[root@db-03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &

7.检测MHA启动状态
[root@db-03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:50155) is running(0:PING_OK), master:172.16.1.52

VIP虚拟IP漂移(前端连接数据库的IP指向虚拟IP)

根据manager配置文件写对应的脚本
[root@db-03 ~]# vim /etc/mha/app1.cnf
master_ip_failover_script= /etc/mha/master_ip_failover #设置VIP自动切换脚本

[root@db-03 ~]# vim /etc/mha/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;

my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);

my $vip = '172.16.1.55/24'; #虚拟IP地址
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth1:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth1:$key down";

#(如果端口不是22,管理用户不是root需要添加 原端口my $orig_master_port=, 新端口$new_master_port 和用户$ssh_user,)

GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);

exit &main();

sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
my $exit_code = 1;

eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};

if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}

exit $exit_code;
}

elsif ( $command eq "start" ) {
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};

if ($@) {
warn $@;
exit $exit_code;
}

exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit 0;
}

else {
&usage();
exit 1;

}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}

sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}

sub usage {

print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}

#添加执行权限
[root@db-03 mha]#  chmod +x master_ip_failover

#转义一下配置文件中的中文字符
[root@db-03 mha]# dos2unix master_ip_failover

在主库上绑定VIP

ifconfig eth1:1 172.16.1.55/24

问题2:如果断电或者断网,binlog如何保存?

备份binlog
[root@db-03 mha]# vim app1.cnf
[binlog1]
no_master=1 #该服务不会提升为主库
hostname=172.16.1.53 #存放binlog的服务器IP
master_binlog_dir=/data/mysql/binlog/ #binlog存放的位置点

根据manager配置文件创建对应的目录
mkdir -p /data/mysql/binlog/

在存放binlog位置点执行该命令
mysqlbinlog -R --host=172.16.1.55 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &

做完停止MHA并重启

读写分离Atlas

Atlas主要功能(代理)

1.读写分离
2.从库负载均衡
3.IP过滤
4.自动分表
5.DBA可平滑上下线DB(不影响用户的体验,把你的数据库下线)
6.自动摘除宕机的DB

Atlas相对于官方MySQL-Proxy的优势

1.将主流程中所有Lua代码用C重写,Lua仅用于管理接口
2.重写网络模型、线程模型
3.实现了真正意义上的连接池
4.优化了锁机制,性能提高数十倍

安装配置Atlas:

1.安装
[root@db-03 ~]# wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
[root@db-03 ~]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm

编辑配置文件

[root@db-03 ~]# vim /usr/local/mysql-proxy/conf/test.cnf
[mysql-proxy]

#带#号的为非必需的配置项目

#管理接口的用户名
admin-username=user

#管理接口的密码
admin-password=pwd

#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses=172.16.1.55:3306(用虚拟IP)

#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
proxy-read-only-backend-addresses=172.16.1.51:3306,172.16.1.53:3306

#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds=rep:3yb5jEku5h4=,mha:O2jBXONX098=
--------------------------------------------------------------------------------------------------------------
###密码必须这样加密[root@db3 bin]# /usr/local/mysql-proxy/bin/encrypt 123
                   3yb5jEku5h4=
--------------------------------------------------------------------------------------------------------------

#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
daemon=true

#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
keepalive=true

#工作线程数,对Atlas的性能有很大影响,可根据业务适当调整
event-threads=8


#日志级别,分为message、warning、critical、error、debug五个级别
log-level=error

#日志存放的路径
log-path=/usr/local/mysql-proxy/log

#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
sql-log=ON

#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
sql-log-slow=10

#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test

#Atlas监听的工作接口IP和端口(生产建议mysql端口改为别的,Atlas工作端口改为3306,前端服务直接连接3306 即可)
proxy-address=0.0.0.0:33060

#Atlas监听的管理接口IP和端口
admin-address=0.0.0.0:2345

#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3

#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
charset=utf8

#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1
#client-ips=
client-ips=

启动Atlas

#启动Atlas
[root@db-03 conf]# /usr/local/mysql-proxy/bin/mysql-proxyd study start

#检测进程是否启动
[root@db-03 conf]# ps -ef|grep [m]ysql-proxy

#检查端口是否启动
[root@db-03 conf]# netstat -lntup|grep [m]ysql-proxy

连接数据库测试

[root@db-03 conf]# mysql -umha -pmha -h172.16.1.55 -P33060
测试读操作:
db03 [(none)]>select @@server_id;
测试写操作:
mysql> begin;select @@server_id;commit;

如果172.16.1.51主库宕机,172.16.1.52变为主库如何修复?

查看帮助
    select * from help
1)
    1.修改配置文件
    [root@db-03 ~]# vim /usr/local/mysql-proxy/conf/test.cnf
    #Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
    proxy-read-only-backend-addresses=172.16.1.53:3306,172.16.1.51:3306
    2.重启Atlas即可
    
2)
    1.#进入管理接口
    [root@db-03 conf]# mysql -uuser -ppwd -h127.0.0.1 -P2345
    select * from backends;(先查看从库还有谁)
    remove backend 2;(看清IP地址然后移除对应的编号)
    add slave 172.16.1.51:3306;(添加从库)
    save config;(保存到配置文件)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容