1

摘要

本文主要介绍了亚马逊RDS的使用过程中发现的问题以及基于亚马逊EC2实例自己搭建Mysql服务器的一些经验。

mysql遇上AWS

初始

公司项目初始,就使用了亚马逊的各项云服务,亚马逊的各项服务真的非常棒,大大简化了公司产品的扩容和运维工作。

之前公司使用亚马逊的EC2实例,一切都非常好。随着业务的扩展,客户需要mysql关系型数据库,为了使用方便,我们选了亚马逊提供的RDS服务,这玩意儿就是那么简单,选个mysql版本,直接就部署好了,什么my.cnf 文件,那是啥?我不关心啊。

开始运行的挺好,各种方便,还能动态制作一个主机的镜像实例,真是简单又省心。

随着用户量的增加,高可用和负载均衡提上了日程。

高可用?很简单啊,亚马逊的RDS高可用跟用户没关系,他自己内部都冗余好了,亚马逊系统自己准备的slave会顶上去的;负载均衡,嗯,这有点麻烦,我找找资料。

深入

亚马逊提供了一个通用的ELB模块,来动态分配访问落到哪台RDS上,但两台RDS的数据一致性怎么解决呢?

mysql社区版本并不提供集群服务,也就是说实际上在很多mysql系统中,并没有官方的负载均衡的解决方案,这就意味着,如果要从系统层面解决,必须使用第三方工具,或者通过用户的应用代码来完成。现在RDS就是提供一个数据库链接,所有系统工具都不能用。

第三方系统工具用不了,那么让用户改代码?这岂不是和我们的目标冲突了?我们的目标就是让用户能够零修改就能使用我们服务。

于是,我们分析了RDS的状况。

优点:

  1. 简单易用

  2. 自动高可用

  3. 定期有snapshot

缺点:

  1. 缺乏系统级的数据库管理界面

  2. 没有root权限

  3. …(不说了)

缺点的第一和第二两点,足以让我们放弃RDS的应用了。

这难道就是一言不合就开撕?呵呵,并不是,如果亚马逊的RDS能交出root权限,能解决数据同步,读写分离,负载均衡,动态迁移… 。嗯,我们还会是好朋友的 ☺。

弃坑挖新坑

好了言归正传,我们转手搞了3台EC2实例,搭了三个mysql,一主两丛,结构是1常主,一备主,一永从。

这很好理解了,2台做主的,性能比较好,一台永从的,只做数据备份用,按照一定的时间间隔备份数据到S3服务器上。

这里要介绍一个熟悉mysql都会知道的专门搞mysql,扩展mysql的大牛公司:PERCONA。写下这个几个字母的时候,俺的心情是激动的,所以都是大写的。

大家都知道mysql的存储引擎现在主流的有两种MyISAM和INNODB,其中的差别我们不说,只说数据备份,MyISAM的备份很简单,拷贝复制; INNODB的备份就扯了,用mysqldump 命令对数据库进行蹂躏。有时还会偶尔疏忽,漏了个参数,咋办?vi打开sql文件改几十,几百个地方?还是再来重复蹂躏一下,再dump一遍?Oh my god,太痛苦了,想想就是一场噩梦。

一方有难八方支援之一

Percona华丽丽的给出了一份在线热备的工具XtraBackup。这真是mysql admin的居家旅行,XXXX的利器啊,老鸟可以不用在意,小鸟同学们,你们可要好好的掌握这一大杀器啊!

XtraBackup在运行期间,不锁库,不锁库,不锁库。重要的事情说三遍,光这个优势就可以弃用mysqldump了。

还有什么增量备份,差异备份,单库备份恢复等等,犹如瑞士军刀,总有一件适合你。

下面给三条命令:

  1. 备份(备份的时候不需要停服务,如果是主库,用户是无感的)

innobackupex --defaults-file=/etc/my.cnf  --user='root' --password='xxxxx' /opt/data/abcd --no-timestamp

注:/opt/data/abcd 是指定数据库备份输出的目录, --no-timestamp让工具不要主动生成时间戳目录

  1. 恢复

innobackupex --user=root --default-file=/etc/my.cnf --apply-log  /opt/data/abcd
innobackupex --user=root --default-file=/etc/my.cnf --copy-back  /opt/data/abcd

注1:以上是两条命令

注2:恢复之前,需要停mysql服务,删除mysql的data目录下的所有数据,恢复完之后,需要执行命令chown –R 命令把mysql data目录改为mysql:mysql ,之后启动mysql 服务。

Xtrabackup输出的数据目录会有一个文件,里面记录了bin-log文件的序号和position位置,也就是说,我们在执行Xtrabackup命令进行备份的时候,此时输出的数据,是和此文件序号中的position位置的log记录相匹配的。(如果你搭建过主从,就会明白,否则就会认为我在胡言乱语。)

想要深入了解Xtrabackup是怎么干的,可以去看下[Mysql技术内幕-InnoDB存储引擎]。

有了这个工具,搭建主从不要太方便。

先找台做主服务的EC2,搭个mysql。

装下google的半同步插件(写到这里,不禁想到,RDS不知道是用的是啥,难道是异步同步)

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

把REPLICATION SLAVE和REPLICATION CLIENT都搞上,然后就能用Xtrabackup来一式两份了。

GRANT REPLICATION SLAVE ON *.* to 'xxx'@'%' identified by 'xxx';
GRANT REPLICATION CLIENT ON *.* to 'xxx'@'%' identified by 'xxx';

把Xtrabackup输出的目录打个包,scp到两台从机上,恢复并启动mysql服务之后,执行命令:

CHANGE MASTER TO MASTER_HOST='xxx',master_port=3306,master_user='xxx',master_password='xxx',master_log_file='xxx',master_log_pos=xxx;

命令中的xxx各不相同哦,各位谨慎。

master_log_file='xxx',master_log_pos=xxx; 这两个数据可以从xtrabackup_binlog_pos_innodb 文件中获取。

然后在mysql命令行下 show slave statusG; 看下主从复制的情况,就万事OK了!

一方有难八方支援之二

既然搭建了主从,那么MHA也是必须的。

MHA项目地址 https://code.google.com/p/mys...

虽然这个项目许久没有更新,不过历史证明还是蛮可靠的。

我曾经做过一个无负载测试,搞了1600多次,每次都在10-15秒之内顺利切换完成。如果你的服务器能停止mysql服务1600多次,那我还能说什么呢?

MHA一般配合Keepalived 给App提供一个唯一可用的mysql链接ip,一旦MHA脚本检测到mysql 服务中断,可以自己写脚本,中断目标服务器的keepalived服务,这样VIP就漂移到新的服务器上,继续提供服务了。

但是我们架设在亚马逊EC2实例上的mysql服务器为了安全起见都是跨网段的,Keepalived不支持,实现不了啊。还好天无绝人之路,EC2实例提供了辅助私有ip的功能,用AWS命令为主服务器添加一个辅助私有IP,并且把原来的辅助私有IP回收掉,不就可以了吗?

想到就干。

回收:

aws ec2 unassign-private-ip-addresses --network-interface-id xxx --private-ip-addresses $VIP

添加:

aws ec2  assign-private-ip-addresses --network-interface-id xxx --private-ip-addresses $VIP --allow-reassignment

之后我们看下MHA提供的代码:
打开文件master_ip_failover 这是用perl写的(写到这里,又情不自禁的想到了,谁说perl不行了,系统管理处处是perl啊!):

GetOptions(
 'command=s'              => \$command,
 'orig_master_host=s'     => \$orig_master_host,
 'orig_master_ip=s'       => \$orig_master_ip,
 'orig_master_port=i'     => \$orig_master_port,
 'orig_master_user=s'     => \$orig_master_user,
 'orig_master_password=s' => \$orig_master_password,
 'new_master_host=s'      => \$new_master_host,
 'new_master_ip=s'        => \$new_master_ip,
 'new_master_port=i'      => \$new_master_port,
 'new_master_user=s'      => \$new_master_user,
 'new_master_password=s'  => \$new_master_password,
);

这串代码蛮关键,是上游代码调用该脚本时传进来的参数,这些参数也蛮好理解,望文生意的。通过这些拿到的ip,帐号,就能上服务器去折腾一下,重新分配IP到备主上,这样就能很方便的完成常主->备主的切换了。

再看下MHA的配置脚本:

[server default]
user=xxx
password=xxx
repl_user=xxx
ssh_user=xxx
master_binlog_dir=/opt/mysql
remote_workdir=/var/log/masterha
secondary_check_script= masterha_secondary_check -s x.x.x.x -s x.x.x.x -s x.x.x.x
ping_interval=3
master_ip_failover_script=/mha4mysql/script/master_ip_failover_app1
report_script= /mha4mysql/script/send_report

[server1]
candidate_master=1
hostname=x.x.x.x

[server2]
candidate_master=1
hostname=x.x.x.x

[server3]
no_master=1
hostname=x.x.x.x

需要解释下的包括:

secondary_check_script= masterha_secondary_check -s x.x.x.x -s x.x.x.x -s x.x.x.x 

mha检查机制,内置的,咱不用管,只要接着填写-s 后面的ip就好了,有几个就填几个。

ping_interval=3 

俗语说叫采样间隔,放这儿就叫探测间隔吧。

master_ip_failover_script=/mha4mysql/script/master_ip_failover_app1 

failover时执行的脚本,做一些IP回收,分配啥的,主从强制数据同步,以及最新数据源挑选等在主服务器拒绝服务之后,MHA内置脚本帮我们都搞定了,我们也不要care了。(我们这里不用选,就一个 ☺)

report_script= /mha4mysql/script/send_report 

这个也挺关键,failover之后发送邮件通知,要不数据库少了一个服务,你还不知道,那不是扯淡么。

后台Daemon运行:

nohup masterha_manager --conf=/etc/app1.cnf < /dev/null >> /var/log/masterha/app1.log 2>&1 &

好了,一套可靠的mysql服务就搭好了。

那么各位要说了,MHA搞定了,那负载均衡呢?

呃~ 各位等我喝口水,且听下回分解吧,哈哈!


作者信息
原文作者来自 MaxLeap 团队_Service&Infra 成员:Kevin, 喜欢开发一些小脚本来协助流程建设。
力谱宿云 LeapCloud首发:https://blog.maxleap.cn/archi...

相关阅读
快速部署Test-Driven Development/Debug环境

欢迎大家来请关注我们的微信公众号:MaxLeap_yidongyanfa

图片描述


力谱云
2.6k 声望226 粉丝

力谱云 - 让每个企业都拥有自己的移动电商平台