Mysql + keepalived 实现双主热备读写分离

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: <p style="line-height:22.6667px; color:rgb(85,85,85); font-family:Verdana,'BitStream vera Sans',Tahoma,Helvetica,sans-serif; font-size:13.3333px; margin-top:0px; margin-bottom:10px; padding-top:0p


Mysql + keepalived 实现双主热备读写分离


架构图

系统:CentOS6.4_X86_64
软件版本:Mysql-5.6.12,Keepalived-1.2.7
环境简介:
1.Master-A 192.168.1.168 (Mysql+Keepalived)
2.Master-B 192.168.1.169 (Mysql+Keepalived)
3.写入VIP 192.168.100 (168主,169从)
4.读取VIP 192.168.200 (169主,168从)
此处略过Mysql和Keepalived的安装过程,请读者自行查找相关的安装指导资料.

工作流程图

复制实现原理(适用于Mysql 5.5及之前的版本):

MySQL支持单向,异步复制,复制过程中一个服务器充当主服务器,而另外一个或多个其它服务器充当从服务器。

MySQL复制基于主服务器在二进制日志中跟踪所有对数据库的更改(插入、更新、删除等等),必须在主服务器上启用二进制日志。

MySQL使用3个线程来执行复制同步功能,其中两个线程(Sql线程和IO线程)在从服务器,另外一个线程(IO线程)在主服务器。

当从服务器发出start slave服务时,从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。

主服务器创建Binlog Dump线程将二进制日志中的内容发送到从服务器。

从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中(中继日志),接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”。SQL线程读取中继日志并执行日志中包含的更新。在从服务器上,读取和执行更新语句被分成两个独立的任务。

当从服务器启动时,其I/O线程可以很快地从主服务器索取所有二进制日志内容,然后执行sql线程。

Mysql 5.6 特性

由于Mysql 5.6 引入了 GTID(Global Transaction ID),保证 Slave 在复制的时候不会重复执行相同的事务操作;其次,是用全局事务 IDs 代替由文件名和物理偏移量组成的复制位点,定位 Slave 需要复制的 binlog 内容,在旧的 binlog 事件基础上新增两类事件

1.Previous_gtids_log_event 该事件之前的全局事务 ID 集合
2.Gtid_log_event 标记之后的事务对应的全局事务 ID

MySQL 5.6 的 binlog 文件中,每个事务的开始不是 “BEGIN” ,而是 Gtid_log_event 事件。

详解可以参考 http://gitsea.com/wp-content/uploads/2013/06/MySQL_Innovation_Day_Replication_HA.pdf

优点:
1.使用 GTIDs 作为主备复制的位点,在写 binlog 时用 Gtid_log_event 标记事务

2.主从复制不再基于master的binary logfile和logfile postition,从服务器连接到主服务器之后,把自己曾经获取到的GTID(Retrieved_Gtid_Set)发给主服务器,主服务器把从服务器缺少的GTID及对应的transactions发过去即可.

3.采用多个sql线程,每个sql线程处理不同的database,提高了并发性能,即使某database的某条语句暂时卡住,也不会影响到后续对其它的database进行操作.

配置Master-Master

一.创建同步用户

分别在两台mysql上执行

1
2
mysql> grant replication slave on *.* to 'replicate' @ '%' identified by '123456' ;
mysql> flush privileges ;

二.修改my.cnf

修改 /etc/my.cnf 前最好做个备份

Master-A 的my.cnf配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
binlog- format =ROW //二进制日志的格式,有row、statement和mixed几种类型,
log-slave-updates=true
gtid-mode=on //启用GTID
enforce-gtid-consistency=true //启用GTID
master-info-repository=TABLE//默认是file,选择table方式保存
relay-log-info-repository=TABLE//默认是file,选择table方式保存
sync-master-info= 1 //实时同步
slave-parallel-workers= 2 //设定从服务器的SQL线程数; 0 表示关闭多线程复制功能
binlog-checksum=CRC 32 //日志校验
master-verify-checksum= 1 //启用校验
slave-sql-verify-checksum= 1 //启用校验
binlog-rows-query-log-events= 1 //只对row-based binlog有效
server-id= 1
report-port= 3307
port= 3306
log-bin=master-a-bin.log
report-host= 192.168 . 1.168
innodb_flush_log_at_trx_commit= 1 //)每N次事务提交或事务外的指令都需要把日志写入(flush)硬盘
sync_binlog= 1 //This makes MySQL synchronize the binary log’s contents to disk each time it commits a transaction 
auto_increment_offset = 1 // 设置AUTO_INCREMENT起点
auto_increment_increment = 2 //设置AUTO_INCREMENT增量
replicate-do-db = test//需要同步的数据库
replicate-ignore-db = mysql,information_schema,performance_schema//不需要同步的数据库

Master-B 的my.cnf配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
binlog- format =ROW
log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info= 1
slave-parallel-workers= 2
binlog-checksum=CRC 32
master-verify-checksum= 1
slave-sql-verify-checksum= 1
binlog-rows-query-log-events= 1
server-id= 2
report-port= 3307
port= 3306
log-bin=master-a-bin.log
report-host= 192.168 . 1.169
innodb_flush_log_at_trx_commit= 1
sync_binlog= 1
auto_increment_offset = 1
auto_increment_increment = 2
replicate-do-db = test
replicate-ignore-db = mysql,information_schema,performance_schema

三.重启Mysql,启动Slave服务

首先重启两台mysql服务,

在Master-A 执行如下操作

1
2
change master to master_host= '192.168.1.169' , master_user= 'replicate' ,master_password= '123456' ,master_auto_position=1;
start slave;

在Master-B 执行如下操作

1
2
change master to master_host= '192.168.1.168' , master_user= 'replicate' ,master_password= '123456' ,master_auto_position=1;
start slave;

接下来就可以测试了,两边的test数据库增加不同的数据,都会同步到另外一台服务器上
同时还可以通过 show slave status G;查看相关服务状态

配置Keepalived

修改keepalived.cnf 文件,默认放置/etc/keepalived/
Master-A 的keepalived.conf配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
! Configuration File for keepalived
 
bal_defs {
    notification_email {
      ****@163.com
    }
    notification_email_from ***8@qq.com
    smtp_server smtp.qq.com
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
 
vrrp_instance VI_1 {
     state MASTER
     interface eth0 // 网卡
     virtual_router_id 51 // 同一实例下virtual_router_id必须相同 
     priority 100 // 定义优先级,数字越大,优先级越高 BACKUP 优先级要低于MASTER
     advert_int 1 //MASTER 与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒 
     authentication { // 验证类型和密码
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress { //VIP
         192.168.1.100
     }
}
vrrp_instance VI_2 {
     state BACKUP
     interface eth0
     virtual_router_id 52
     priority 50
     advert_int 1
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
         192.168.1.200
     }
}

Master-B keepalived.conf 配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
! Configuration File for keepalived
 
bal_defs {
    notification_email {
      ***@ 163 .com
    }
    notification_email_from ***@qq.com
    smtp_server smtp.qq.com
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
 
vrrp_instance VI_1 {
     state BACKUP
     interface eth0
     virtual_router_id 51
     priority 50
     advert_int 1
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
         192.168 . 1.100
     }
}
vrrp_instance VI_2 {
     state MASTER
     interface eth0
     virtual_router_id 52
     priority 100
     advert_int 1
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
         192.168 . 1.200
     }
}

在开启keepalived服务之前先关闭防火墙,keepalived服务会占用112和255端口
然后通过sudo service keepalived start 开启服务,读者可以随意开启和停止keepalived测试看看IP有没有自动切换。
在遇到问题的时候可以通过ip add show eth0 和tail -f /var/log/messages进行问题定位。

锦上添花
添加mysql监控功能,当一台服务器的mysql进程挂掉之后,自动重启mysql服务,如果重启失效,则停止运行keepalived,进行容灾切换
首先安装nmap,运行yum -y install nmap
分别在两台服务器上的/opt目录下新增chk_mysql.sh脚本,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# check mysql server status
PORT=3306
 
nmap localhost -p $PORT | grep "$PORT/tcp open"
#echo $?
if [ $? - ne 0 ]; then
     service mysql stop
     service mysql start
     sleep 5
     nmap localhost -p $PORT | grep "$PORT/tcp open"
     [ $? - ne 0 ] && service keepalived stop
fi

增加可执行权限 chmod +x /opt/chk_mysql.sh

把Master-A的keepalived.conf 修改成如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
! Configuration File for keepalived
 
bal_defs {
    notification_email {
      ****@163.com
    }
    notification_email_from ***8@qq.com
    smtp_server smtp.qq.com
    smtp_connect_timeout 30
    router_id LVS_DEVEL
}
vrrp_script chk_mysql_port {
     script "/opt/chk_mysql.sh"
     interval 2
     weight 2
}
vrrp_instance VI_1 {
     state BACKUP
     interface eth0 // 网卡
     virtual_router_id 51 // 同一实例下virtual_router_id必须相同 
     priority 50 // 定义优先级,数字越大,优先级越高 BACKUP 优先级要低于MASTER
     advert_int 1 //MASTER 与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒 
     authentication { // 验证类型和密码
         auth_type PASS
         auth_pass 1111
     }
     track_script {
         chk_mysql_port
     }
     virtual_ipaddress { //VIP
         192.168.1.100
     }
}
vrrp_instance VI_2 {
     state MASTER
     interface eth0
     virtual_router_id 52
     priority 100
     advert_int 1
     authentication {
         auth_type PASS
         auth_pass 1111
     }
     track_script {
         chk_mysql_port
     }
     virtual_ipaddress {
         192.168.1.200
     }
}

同理,相应的修改Master-B的配置文件。
重启服务生效之后,你会发现,手动关闭mysql服务之后,会被keepalived自动开启服务。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
关系型数据库 MySQL Java
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
155 0
|
7月前
|
SQL 关系型数据库 MySQL
Mycat【Mycat部署安装(核心配置及目录结构、安装以及管理命令详解)Mycat高级特性(读写分离概述、搭建读写分离、MySQL双主双从原理)】(三)-全面详解(学习总结---从入门到深化)
Mycat【Mycat部署安装(核心配置及目录结构、安装以及管理命令详解)Mycat高级特性(读写分离概述、搭建读写分离、MySQL双主双从原理)】(三)-全面详解(学习总结---从入门到深化)
682 0
|
2月前
|
负载均衡 监控 关系型数据库
MySQL 官宣:支持读写分离了!!
【10月更文挑战第8天】MySQL的读写分离功能显著提升了数据库性能、可用性和可靠性。通过将读写操作分配至不同服务器,有效减轻单个服务器负载,提高响应速度与吞吐量,并增强系统稳定性。此外,它还支持便捷的扩展方式,可通过增加只读服务器提升读操作性能。实现读写分离的方法包括软件层面(如使用数据库中间件)和硬件层面(使用独立服务器)。使用时需注意数据一致性、负载均衡及监控管理等问题。
178 0
|
7月前
|
SQL 关系型数据库 MySQL
mysql 主从复制与读写分离
mysql 主从复制与读写分离
|
3月前
|
关系型数据库 MySQL Java
MySQL主从复制实现读写分离
MySQL主从复制(二进制日志)、 Sharding-JDBC实现读写分离
MySQL主从复制实现读写分离
|
4月前
|
SQL 关系型数据库 MySQL
(二十五)MySQL主从实践篇:超详细版读写分离、双主热备架构搭建教学
在上篇《主从原理篇》中,基本上把主从复制原理、主从架构模式、数据同步方式、复制技术优化.....等各类细枝末节讲清楚了,本章则准备真正对聊到的几种主从模式落地实践,但实践的内容通常比较枯燥乏味,因为就是调整各种配置、设置各种参数等步骤。
657 3
|
4月前
|
关系型数据库 MySQL PHP
开发者必看:MySQL主从复制与Laravel读写分离的完美搭配
开发者必看:MySQL主从复制与Laravel读写分离的完美搭配
93 2
|
4月前
|
SQL 关系型数据库 MySQL
mysql读写分离,主从同步
本文介绍了如何在Laravel项目中配置数据库读写分离,并实现MySQL主从同步。主要步骤包括:在`config/database.php`中设置读写分离配置;为主机授予从机访问权限;配置各MySQL服务器的`/etc/my.cnf`文件以确保唯一的`server-id`;以及通过SQL命令设置主从关系并启动从服务。文章还针对一些常见错误提供了排查方法。最后通过验证确认主从同步是否成功。[原文链接](https://juejin.cn/post/6901581801458958344)。版权所有者为作者佤邦帮主,转载请遵循相关规定。
|
4月前
|
cobar 关系型数据库 MySQL
使用MyCat实现MySQL主从读写分离(一)概述
【8月更文挑战第11天】MySQL读写分离通过主从复制分散负载,主库负责写操作,从库承担读查询,以复制技术确保数据一致性。此策略有效缓解锁竞争,提升查询效能并增强系统可用性。实现方式包括应用层处理,简便快捷但灵活性受限;或采用中间件如MyCAT、Vitess等,支持复杂场景但需专业团队维护。
148 0
|
4月前
|
SQL 关系型数据库 MySQL
基于proxysql实现MySQL读写分离
基于proxysql实现MySQL读写分离