今天闲来无事,打算搭建一个MySQL的高可用架构,采用的是MySQL的主主结构,再外加Keepalived,对外统一提供虚IP。先来讲说背景吧,如今的项目为了高可用性,都是避免单节点的存在的,好比,咱们的应用程序,都是部署多个节点,经过Nginx作负载均衡,某个节点出现问题,并不会影响总体应用。那么数据库层如何搭建高可用的架构呢?今天咱们就来看看。mysql
总体架构
MySQL采用主主结构,咱们使用两台机器就够了,而后再这两台机器上再安装Keepalived,使用vrrp技术,虚拟出一个IP。两台机器以下:sql
- 192.168.73.141:MySQL(主1)、Keepalived(MASTER)
- 192.168.73.142:MySQL(主2)、Keepalived(BACKUP)
- 192.168.73.150:虚IP
总体架构图以下:shell
MySQL主主搭建
咱们分别在两台机器上安装MySQL,使用yum方式安装,首先从MySQL官网下载rpm包,选择对应的系统,在这里,咱们选择CentOS7的prm包,mysql80-community-release-el7-3.noarch.rpm
。而后将rpm文件分别上传到两台机器上,接下来咱们就是用yum来安装MySQL。数据库
在192.168.73.141(主1)执行以下命令,vim
# 使用yum安装rpm包 yum install mysql80-community-release-el7-3.noarch.rpm # 安装MySQL社区版 时间较长 耐心等待 yum install mysql-community-server #启动MySQL服务 service mysqld start
到这里,MySQL就安装完成,而且正常启动了。而后,咱们用root帐号登陆MySQL,并建立一个可用的帐号。架构
# 从MySQL的日志中 找到root帐号的临时密码 grep 'temporary password' /var/log/mysqld.log # 使用root帐号登陆 输入临时密码 登陆成功 mysql -uroot -p # 修改root帐号的密码 使用MYSQL_NATIVE_PASSWORD的加密方式 这种方式大多数客户端均可以链接 ALTER USER 'root'@'localhost' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'MyNewPass4!'; # 建立MySQL帐号 CREATE USER 'USER'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'USER_PWD'; # 对USER帐号受权 GRANT ALL ON *.* TO 'USER'@'%'; # 刷新权限 FLUSH PRIVILEGES;
好了,到这里,在192.168.73.141上安装MySQL成功,而且建立了USER帐户,咱们可使用NAVICAT等客户端链接。负载均衡
在192.168.73.142(主2)上也执行上面的命令,这样咱们在两台机器上都安装了MySQL。接下来,咱们就要配置MySQL的主主结构了。socket
首先,咱们修改192.168.73.141(主1)上的my.cnf文件。oop
vim /etc/my.cnf datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid # 配置server-id 每一个MySQL实例的server-id都不能相同 server-id=1 # MySQL的日志文件的名字 log-bin=mysql_master # 做为从库时 更新操做是否写入日志 on:写入 其余数据库以此数据库作主库时才能进行同步 log-slave-updates=on # MySQL系统库的数据不须要同步 咱们这里写了3个 更加保险 # 同步数据时忽略一下数据库 可是必须在使用use db的状况下才会忽略;若是没有使用use db 好比create user 数据仍是会同步的 replicate-ignore-db=information_schema replicate-ignore-db=mysql replicate-ignore-db=performance_schema replicate-ignore-db=sys # 使用通配符忽略MySQL系统库的表 这样在create user时也不会进行同步了 replicate_wild_ignore_table=information_schema.% replicate_wild_ignore_table=mysql.% replicate_wild_ignore_table=performance_schema.% replicate_wild_ignore_table=sys.% # MySQL系统库的日志不计入binlog 这样更加保险了 binlog-ignore-db=information_schema binlog-ignore-db=mysql binlog-ignore-db=performance_schema binlog-ignore-db=sys
在192.168.73.142(主2)上也修改my.cnf文件,咱们直接复制过去,只须要修改其中的两个地方,以下:加密
# 配置server-id=2 server-id=2 # MySQL的日志文件的名字 不更名字也能够 这里主要为了区分 log-bin=mysql_slave
配置文件都已经修改好了,咱们分别在192.168.73.141(主1)和192.168.73.142(主2)上重启MySQL服务,
service mysqld restart
下面咱们就要配置主从了,其实主主模式就是配置两个主从,先配置192.168.73.141(主1)->192.168.73.142(主2)的主从,而后再反过来配置192.168.73.142(主2)->192.168.73.141(主1)的主从,这样主主的模式就配置好了。
咱们先来配置192.168.73.141(主1)->192.168.73.142(主2)的主从
先登陆192.168.73.141(主1)的数据库,并执行以下命令:
# 建立备份的帐号 使用MYSQL_NATIVE_PASSWORD的方式加密 mysql> CREATE USER 'repl_master'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'password'; # 对repl_master授予备份的权限 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_master'@'%'; # 刷新权限 mysql> FLUSH PRIVILEGES; # 查看MySQL主节点的状态 mysql> SHOW MASTER STATUS; +-------------------+---------+--------------+---------------------------------------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+---------+--------------+---------------------------------------------+------------------+ | mysql_master.000001 | 516 | | information_schema,mysql,performance_schema,sys | | +-------------------+---------+--------------+---------------------------------------------+------------------+ 1 row in set
咱们要记住binlog文件的名字,也就是mysql_master.000001,和位置,也就是516。
而后,咱们再登陆到192.168.73.142(主2)的数据库,执行以下命令:
mysql> CHANGE MASTER TO # MySQL主的IP -> MASTER_HOST='192.168.73.141', # MySQL主的端口 -> MASTER_PORT=3306 # MySQL主的备份帐号 -> MASTER_USER='repl_master', # MySQL主的备份帐号密码 -> MASTER_PASSWORD='password', # 日志文件 经过show master status获得的 -> MASTER_LOG_FILE='mysql_master.000001', # 日志文件位置 经过show master status获得的 -> MASTER_LOG_POS=516; # 开启从库 mysql> START SLAVE; # 查看从库的状态 mysql> SHOW SLAVE STATUS;
这样,192.168.73.141(主1)->192.168.73.142(主2)的主从就搭建好了。而后,咱们再反过来,搭建192.168.73.142(主2)->192.168.73.141(主1)的主从。
先登陆192.168.73.142(主2)的数据库,执行以下命令:
# 建立备份的帐号 使用MYSQL_NATIVE_PASSWORD的方式加密 mysql> CREATE USER 'repl_slave'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'password'; # 对repl_slave授予备份的权限 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_slave'@'%'; # 刷新权限 mysql> FLUSH PRIVILEGES; # 查看MySQL主节点的状态 mysql> SHOW MASTER STATUS; +-------------------+---------+--------------+---------------------------------------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+---------+--------------+---------------------------------------------+------------------+ | mysql_slave.000001 | 379 | | information_schema,mysql,performance_schema,sys | | +-------------------+---------+--------------+---------------------------------------------+------------------+ 1 row in set
再登陆到192.168.73.141(主1)的数据库,执行以下命令:
mysql> CHANGE MASTER TO # MySQL主的IP -> MASTER_HOST='192.168.73.142', # MySQL主的端口 -> MASTER_PORT=3306 # MySQL主的备份帐号 -> MASTER_USER='repl_slave', # MySQL主的备份帐号密码 -> MASTER_PASSWORD='password', # 日志文件 经过show master status获得的 -> MASTER_LOG_FILE='mysql_slave.000001', # 日志文件位置 经过show master status获得的 -> MASTER_LOG_POS=379; # 开启从库 mysql> START SLAVE; # 查看从库的状态 mysql> SHOW SLAVE STATUS;
这样,192.168.73.142(主2)->192.168.73.141(主1)的主从也搭建好了。咱们可使用navicat分别链接192.168.73.141(主1)和192.168.73.142(主2),并执行建表、插入语句,验证一下主主同步是否成功,这里就不给你们演示了。
Keepalived高可用
MySQL主主结构已经搭建好了,不管从哪一个MySQL插入数据,都会同步到另一个MySQL。虽然有了MySQL主主结构,可是不能保证高可用,好比,咱们的应用程序链接的是192.168.73.141(主1),假若192.168.73.141(主1)的MySQL挂掉了,咱们的应用程序并不能自动的切换到192.168.73.142(主2),咱们的应用程序也是不可用的状态。要作到这一点,就要借助于Keepalived。
Keepalived有两个主要的功能:
- 提供虚IP,实现双机热备
- 经过LVS,实现负载均衡
咱们这里使用Keepalived,只须要使用其中的一个功能,提供虚IP,实现双机热备。咱们须要在192.168.73.141(主1)和192.168.73.142(主2)上都安装Keepalived,执行命令以下:
yum install keepalived
咱们直接使用yum进行安装。安装完以后,编辑keepalived的配置文件,首先编辑192.168.73.141(主1)上的配置文件,以下:
vim /etc/keepalived/keepalived.conf # 全局配置 不用动 只需注释掉vrrp_strict global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr #必须注释掉 不然报错 #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } # 检查mysql服务是否存活的脚本 vrrp_script chk_mysql { script "/usr/bin/killall -0 mysqld" } # vrrp配置虚IP vrrp_instance VI_1 { # 状态:MASTER 另一台机器为BACKUP state MASTER # 绑定的网卡 interface ens33 # 虚拟路由id 两台机器需保持一致 virtual_router_id 51 # 优先级 MASTER的值要大于BACKUP priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 虚拟IP地址 两台keepalived须要一致 virtual_ipaddress { 192.168.73.150 } # 检查脚本 vrrp_script的名字 track_script { chk_mysql } } ###后边的virtual_server所有注释掉 它是和LVS作负载均衡用的 这里用不到 ###
再编辑192.168.73.142(主2)上的配置文件,只须要将state MASTER改成state BACKUP,以下:
state BACKUP
经过keepalived的配置,咱们对外提供192.168.73.150的IP,这个IP实际指向是192.168.73.141(主1),由于它的state是MASTER。当keepalived检测到192.168.73.141(主1)上的MySQL不可用时,会自动切换到192.168.73.142(主2)。对于外部用户是无感知的,由于外部统一使用的是192.168.73.150。
咱们再来看看检测的脚本/usr/bin/killall -0 mysqld
,killall命令不是系统自带的,须要安装,咱们仍是使用yum来安装,以下:
# 先查询一下killall yum search killall #找到了psmisc.x86_64 Loading mirror speeds from cached hostfile ===============Matched: killall ================================ psmisc.x86_64 : Utilities for managing processes on your system # 安装psmisc yum install psmisc
这样咱们就可使用killall命令了。killall -0
并非杀掉进程,而是检查进程是否存在,若是存在则返回0,若是不存在则返回1。当返回1时,keepalived就会切换主备状态。
好了,killall也介绍完了,咱们在两台机器上启动keepalived,以下:
# 启动keepalived service keepalived start
而后,咱们在192.168.73.141(主1)上查看一下IP是否有192.168.73.150,以下:
ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:57:8c:cd brd ff:ff:ff:ff:ff:ff inet 192.168.73.141/24 brd 192.168.73.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.73.150/32 scope global ens33 # 咱们看到了192.168.73.150 valid_lft forever preferred_lft forever inet6 fe80::720b:92b0:7f78:57ed/64 scope link noprefixroute valid_lft forever preferred_lft forever
到这里,keepalived的配置就完成了,咱们经过navicat链接192.168.73.150,能够正常的链接数据库,实际上它链接的是192.168.73.141的数据库,咱们操做数据库也是正常的。
而后,咱们停掉192.168.73.141(主1)上的MySQL服务,
service mysqld stop # 再用 ip addr查看一下 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:57:8c:cd brd ff:ff:ff:ff:ff:ff inet 192.168.73.141/24 brd 192.168.73.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::720b:92b0:7f78:57ed/64 scope link noprefixroute valid_lft forever preferred_lft forever
192.168.73.150的IP找不到了,咱们再去192.168.73.142(主2)上去查看,能够发现192.168.73.150的IP。咱们在navicat上操做数据库,是能够正常使用的。但这时实际链接的是192.168.73.142(主2)的数据库。咱们是没有感知的。若是咱们把192.168.73.141(主1)上的mysql服务再启动起来,192.168.73.150还会切换到192.168.73.141(主1)。
总结
咱们经过MySQL主主结构+keepalived双机热备实现了MySQL的高可用,咱们应用程序能够链接虚IP,具体链接的实际MySQL,不须要咱们关心。若是咱们再作读写分离的话,能够将MySQL(主2)做为主,配置数据库的主从关系。这时,虚IP链接的是MySQL(主1),MySQL(主1)将数据同步到MySQL(主2),而后MySQL(主2)再将数据同步到其余从库。若是MySQL(主1)挂掉,虚IP指向MySQL(主2),MySQL(主2)再将数据同步到其余从库。