mysql双机高可用方案
在生产环境中,保证业务稳定永远是第一位,而数据库又是业务的核心,所以数据库的部署方案就尤为重要。从技术的角度讲,像mysql自动failover,双主复制,这种有切换的高可用功能很容易实现。但是保证不丢数据,保证服务的正常运行,远比这种有代价的切换重要。这里说的代价指的是业务中断和维护成本。就双机高可用来讲,个人认为双主复制是不可靠的做法。首先如果两边都有写操作,无论是否发生故障都可能造成数据不一致,网上管这个叫的脑裂。如果把写操作固定到一台,又不如单向的主从同步省事。至于自动failover,MHA的主从切换已经很成熟,但是会造成业务短暂的中断,同时会增加复杂性,越复杂的架构,故障点就越多,排除故障时间和难度也大,增加了维护成本。我相信多台数据库会有更多更好的选择,但是双机高可用方案我使用的方案是:
- 最简单的主从复制,去掉自动failover
- 使用atlas中间件保证主库宕机时继续提供服务,同时读写分离增强吞吐量
此方案的优点:
- 双机高可用
- 读写分离,提供更强的性能
- 足够简单和可靠,易于排除故障
缺点是主库宕机会写入失败,但不会造成数据丢失,而且因为架构简单,排除故障很容易。
一、准备工作
系统选择centos 6.5 64位,因为内存比较大,64位系统能更好利用硬件资源,同时altas只支持64位系统。mysql使用Percona server 5.6,也是出于性能考虑。percona分支本身修复了mysql官方版本的bug,保证了兼容性并增强了性能。5.6版本引入了GTID大大改善了主从复制的延迟,稳定性也得到了很多公司的验证。
服务器:
db1(主):10.11.15.114
db2(从):10.11.15.115
atlas :10.11.15.123
二、安装Percona server
官方提供了yum源,省事点使用yum安装:
yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm
yum list | grep percona
yum install Percona-Server-server-56.x86_64
安装xtrabackup备份工具,方便配置主从同步和备份数据:
yum install percona-xtrabackup
两台db都按上面的步骤安装好
三、设置基于GTID的主从同步
使用GTID复制和传统主从复制的区别:
- 不再需要指定传统复制中的 master_log_files和master_log_pos,使主从复制更简单可靠
- 可以实现基于库的多线程复制
- 减小主从复制的延迟
1.配置主服务器
percona官方提供了my.cnf的在线生成工具:https://tools.percona.com/
可以根据服务器的硬件,生成一份推荐的my.cnf,主服务器的my.cnf中需要加入:
server_id =114
binlog-format=ROW
binlog-row-image = minimal
log-bin=mysql-master-bin
report-host=10.11.15.114
report-port=3306
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
binlog_cache_size = 4M
max_binlog_size = 1G
max_binlog_cache_size = 2G
binlog-checksum=CRC32
slave_allow_batching = 1
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
slave-parallel-workers=4
relay_log_purge = 1
relay_log_recovery = 1
具体参数的含义,请见下方的参考文章,启动主库,使用mysql自带的脚本设置密码和一些基本的安全配置,在命令行下输入:
mysql_secure_installation
如果更改了mysql安装路径会报错,见最后的故障排除第二点
备份主库数据和日志:
我的mysql是装在/opt/mysql目录下,备份目录为/opt/backup:
innobackupex --socket=/opt/mysql/mysql.sock --defaults-file=/etc/my.cnf --user=root --password='19hb1a23s4dt' /opt/backup/
innobackupex --socket=/opt/mysql/mysql.sock --defaults-file=/etc/my.cnf --user=root --password='19hb1a23s4dt' --apply-log /opt/backup/2015-10-13_05-55-19/
备份好之后将文件夹'2015-10-13_05-55-19'传到从库上,覆盖从库的datadir(/opt/mysql)
用root登录主库,添加复制的用户并赋予从库权限,执行sql:
grant replication slave on *.* to 'rep'@'10.11.15.115' identified by 'repadmin';
flush privileges;
在从库服务器上验证一下:
mysql -h 10.11.15.114 -u=rep -p=repadmin
登录成功后要确认下权限,执行:
mysql> show grants;
+-----------------------------------------------------------------------------------------+
| Grants for rep@192.168.1.110 |
+-----------------------------------------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.1.110' IDENTIFIED BY PASSWORD <secret> |
+-----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
2.从库配置
确保datadir的属主正确:
chown mysql:mysql -R /opt/mysql
在从库的my.cnf中加入和主库一样的配置,只需修改下面三项:
server_id=115
log-bin=mysql-slave-bin
report-host=10.11.15.115
查看/opt/mysql/xtrabackup_binlog_info的内容:
cat /opt/mysql/xtrabackup_binlog_info
mysql-master-bin.000007 191 c635636d-711f-11e5-af2f-001d097141b7:1-10
启动从库,并登录从库执行sql:
change master to
master_host='10.11.15.114',
master_user='rep',
master_password='repadmin',
master_port=3306,
MASTER_LOG_FILE='mysql-master-bin.000007',
MASTER_LOG_POS=191;
master_delay=30; #延迟30秒复制,不需要此功能请去掉
之后执行start slave
启动同步,使用show slave status\G;
检查如下两项是否为yes:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
在库上随便建一个库验证一下同步是否正常。
四、atlas安装和配置
1.安装
不得不说,atlas的安装和使用真是简单啊。官方提供了rpm包,打开下面的链接下载并安装好:
https://github.com/Qihoo360/Atlas/releases
安装好文件在/usr/local/mysql-proxy/ 下
2.atlas配置
首先在主库上新增一个允许atlas所在服务器登录的用户,使用使用现有数据库用户也可以,但要给atlas所在服务器权限。
grant all on *.* to admin@'10.11.15.123' identified by 'pro_adm_123$%^';
flush privileges;
建好好,使用atlas加密下密码:
[root@altas conf]# /usr/local/mysql-proxy/bin/encrypt pro_adm_123$%^
32GI2v1Pl8Zki5/rcE9phg==
atlas配置文件在/usr/local/mysql-proxy/下,按照里面的中文说明编辑test.cnf,我用的配置:
[mysql-proxy]
admin-username = manager
admin-password = manager
proxy-backend-addresses = 10.11.15.114:3306
proxy-read-only-backend-addresses = 10.11.15.115:3306@1
pwds = admin:32GI2v1Pl8Zki5/rcE9phg==
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
sql-log = OFF
sql-log-slow = 10
proxy-address = 0.0.0.0:3306
admin-address = 0.0.0.0:3307
charset = utf8
启动atlas:
/usr/local/mysql-proxy/bin/mysql-proxyd test start
3、测试
1. 测试数据库登录
使用 mysql -h10.11.15.123 -P3306 -uadmin -p pro_adm_123$%^ 进行登录测试,如果能正常登录,随便创建一成数据库进行写入测试。这一步如果有问题,多数是数据库的admin没有开放atlas服务器的权限造成的。
2. atlas管理登录
atlas管理接口也是使用mysql客户端登录,本例中登录端口为3307,mysql -P3307 -u manager
-p manager,登录后使用select * from help
查看支持的语句,很简单不多说。
3. 读写分离
读写分离测试有点麻烦,只说方法:要先在主库上插入一条数据,主库会自动同步到从库,然后登录上从库更新一下这条数据,然后从atlas接口登录查询该记录,就可以测试出读写分离是否成功了。不过这样做由于两边的数据不一致,在某些情况下会破坏主从同步,建议在未上线之前测试
五、报错排除
1.mysql-error.log中报错:
[ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist
同时启动时报:
Starting MySQL (Percona Server). ERROR! The server quit without updating PID file (/opt/data/mysql/mysql.pid).
解决方法:
mysql_install_db --user=mysql --ldata=/opt/data/mysql
2.更改mysql默认路径后执行mysql_secure_installation 报错:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
编辑/usr/bin/mysql_secure_installation,在 write_file($config中加入socket
write_file($config,
"# mysql_secure_installation config file",
"[mysql]",
"user=root",
"password='$esc_pass'",
"socket=/opt/data/mysql/mysql.sock",#加入此行
"connect-expired-password");
3.主库数据有更新时从库上出现:
Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event
配置好后默认的SQL_Remaining_Delay是30秒,也就是延迟30秒才复制,这会造成读写分离的数据不一致,关掉在slave上执行:
stop slave;
CHANGE MASTER TO MASTER_DELAY = 0;
start slave;
4.配置好主从无法启动slave:
mysql> start slave\G;
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
解决方法:
在slave上执行:
stop slave;
reset slave;
change master to
master_host='10.11.15.114',
master_user='rep',
master_password='repadmin',
master_port=3306,
master_auto_position = 1;
在start slave一般就正常复制了,如果还是无法启动,在master上先执行一下 reset master;
在重置slave。
5.innobackupex备份报错:
151013 05:55:06 innobackupex: Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;mysql_socket=/opt/mysql/mysql.sock' as 'root' (using password: YES).
innobackupex: Error: Failed to connect to MySQL server: DBI connect(';mysql_read_default_group=xtrabackup;mysql_socket=/opt/mysql/mysql.sock','root',...) failed: Access denied for user 'root'@'localhost' (using password: YES) at /usr/bin/innobackupex line 2945
解决方法:
--password='19hb1a23s4dt' 密码要加上单引号
参考文章:
https://www.percona.com/doc/percona-xtrabackup/2.1/howtos/setting_up_replication.html
http://634871.blog.51cto.com/624871/1330643
http://www.cnblogs.com/abobo/p/4242417.html