在生产环境中,保证业务稳定永远是第一位,而数据库又是业务的核心,所以数据库的部署方案就尤为重要。从技术的角度讲,像mysql自动failover,双主复制,这种有切换的高可用功能很容易实现。但是保证不丢数据,保证服务的正常运行,远比这种有代价的切换重要。这里说的代价指的是业务中断和维护成本。就双机高可用来讲,个人认为双主复制是不可靠的做法。首先如果两边都有写操作,无论是否发生故障都可能造成数据不一致,网上管这个叫的脑裂。如果把写操作固定到一台,又不如单向的主从同步省事。至于自动failover,MHA的主从切换已经很成熟,但是会造成业务短暂的中断,同时会增加复杂性,越复杂的架构,故障点就越多,排除故障时间和难度也大,增加了维护成本。我相信多台数据库会有更多更好的选择,但是双机高可用方案我使用的方案是:

  1. 最简单的主从复制,去掉自动failover
  2. 使用atlas中间件保证主库宕机时继续提供服务,同时读写分离增强吞吐量

此方案的优点:

  1. 双机高可用
  2. 读写分离,提供更强的性能
  3. 足够简单和可靠,易于排除故障

缺点是主库宕机会写入失败,但不会造成数据丢失,而且因为架构简单,排除故障很容易。

一、准备工作

系统选择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复制和传统主从复制的区别:

  1. 不再需要指定传统复制中的 master_log_files和master_log_pos,使主从复制更简单可靠
  2. 可以实现基于库的多线程复制
  3. 减小主从复制的延迟

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