主从复制和读写分离
前言
一、MySQL主从复制的概述
1、MySQL主从复制的概念
2、Mysql主从复制功能和使用场景
2.1、Mysql主从复制功能
2.2、Mysql主从复制使用场景
3、MySQL支持的复制类型
3.1、基于语句的复制
3.2、基于行的复制
3.3、混合复制
4、主从复制的工作过程
5、MySQL三种同步方式
5.1、异步复制(Async Replication)
5.2、同步复制(Sync Replication)
5.3、半同步复制(Semi-Sync Replication)
6、MySQL主从复制延迟
6.1、MySQL主从复制延迟的原因
6.2、解决MySQL主从复制延迟方法
二、部署MySQL主从复制
1、部署Master主服务器
2、搭建Slave1从服务器
3、搭建Slave2从服务器
三、MySQL读写分离
1、MySQL读写分离概述
2、MySQL读写分离的功能和应用场景
2.1、MySQL读写分离的功能
2.2、MySQL读写分离应用场景
3、实现Mysql读写分离的方法
4、读写分离的工作原理
四、搭建MySQL读写分离
1、搭建Amoeba服务器
2、客户端配置
3、测试读写分离(关闭同步)
4、测试读写分离(开启同步)
前言
Mysql 作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过。但在实际的生产环境中,由单台MySQL 作为独立的数据库是完全不能满足实际需求的,无论是在安全性, 高可用性以及高并发等各个方面。
因此,一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分(MySQL-Proxy/Amoeba)来提升数据库的并发负载能力,这样的方案来进行部署与实施的。
一、MySQL主从复制的概述
1、MySQL主从复制的概念
MySQL 主从复制是一种将数据从一个 MySQL 服务器(主服务器)复制到一个或多个 MySQL 服务器(从服务器)的技术。其主要目的是实现数据冗余、负载均衡和备份,提升系统的可用性和性能。
下面是主从复制的核心概念:
主数据库(Master):主数据库是数据变更(包括插入、更新和删除操作)发生的地方。它记录所有的数据变更事件到二进制日志(Binary Log)中。
从数据库(Slave):从数据库从主数据库接收数据变更事件,并将这些变更应用到自己的数据集中,从而保持与主数据库的数据一致性。
二进制日志(Binary Log):这是主数据库上的一个文件,记录了所有对数据库进行更改的事件。这些记录可以被从数据库用来复制数据。
中继日志(Relay Log):从数据库接收到来自主数据库的二进制日志后,会先将其存储在自己的中继日志中,然后再应用这些变更到自己的数据集中。
2、Mysql主从复制功能和使用场景
2.1、Mysql主从复制功能
数据备份:通过将数据从主服务器复制到从服务器,可以在从服务器上进行备份操作,减少主服务器的负担。
读写分离:主服务器处理写操作,而从服务器处理读操作,这样可以分散数据库的访问压力,提高数据库系统的整体性能。
故障恢复:当主服务器出现故障时,可以快速切换到从服务器,保证服务的连续性和数据的完整性。
数据分布:可以将数据复制到地理位置分散的服务器上,提高数据的本地访问速度和可用性。
负载均衡:通过增加从服务器的数量,可以将读请求分散到多个服务器上,实现负载均衡。
2.2、Mysql主从复制使用场景
高可用性部署:在需要确保数据库服务高度可用的场景中,主从复制可以通过自动或手动故障转移来保证服务的持续性。
大规模读操作:对于读操作远远多于写操作的应用,如新闻网站、社交网络等,使用主从复制可以有效地提高查询性能和系统响应速度。
数据分析和报告:可以在从服务器上进行数据分析和生成报告,避免影响主服务器上的业务操作。
跨地域数据同步:对于需要在多个地理位置提供快速数据访问的应用,主从复制可以将数据复制到接近用户的服务器上,减少数据访问延迟。
在线备份:在从服务器上进行备份操作,可以避免对主服务器性能的影响,同时确保数据的安全性。
3、MySQL支持的复制类型
MySQL 主从复制是实现数据库高可用性和负载均衡的关键技术之一。为了适应不同场景的需求,MySQL 提供了三种复制类型:基于语句的复制(Statement-Based Replication, SBR)、基于行的复制(Row-Based Replication, RBR)和混合复制(Mixed Replication)。每种复制类型有其特点和适用场景
3.1、基于语句的复制
基于语句的复制是 MySQL 默认的复制模式,它的工作方式是:当主库执行 SQL 语句时,会将这些语句记录到二进制日志(binlog)中,从库读取主库的二进制日志并在从库上重新执行这些 SQL 语句。
优点:
执行效率高:由于只需要记录 SQL 语句本身,因此二进制日志较小,占用较少的磁盘空间和网络带宽。
适合大部分场景:对于大多数常见的 SQL 操作,基于语句的复制能很好地满足需求。
缺点:
复制精确性问题:在某些特定情况下,基于语句的复制可能会出现不一致的问题。例如,使用包含非确定性函数(如 NOW()、RAND())的语句时,从库可能产生与主库不同的结果。
3.2、基于行的复制
基于行的复制与基于语句的复制不同,它不是将 SQL 语句记录到二进制日志中,而是记录每一行数据的实际变更内容。当主库的某行数据发生改变时,主库会将该行的变化(包括变更前后的数据)写入二进制日志,从库再根据这些变更内容直接更新相应的行。
优点:
更精确的复制:基于行的复制可以避免 SQL 语句执行时可能带来的不一致问题,特别是在使用非确定性函数或复杂事务时。
减少锁争用:因为只复制数据变更的部分,可以减少 SQL 语句执行时的锁争用问题。
缺点:
日志体积较大:基于行的复制需要记录每一行的数据变更,这会导致二进制日志体积显著增大,进而占用更多的磁盘空间和网络带宽。
3.3、混合复制
混合复制模式结合了基于语句的复制和基于行的复制的优点。默认情况下,MySQL 会使用基于语句的复制,但当它检测到某些语句不能保证精确复制时(例如使用了非确定性函数的语句),会自动切换为基于行的复制。这种方式兼顾了性能和数据一致性。
优点:
兼具效率和精度:混合模式在大部分情况下使用基于语句的复制以保证效率,但在需要精确性的场景下会自动切换到基于行的复制,确保数据的一致性。
智能选择复制方式:MySQL 可以根据操作的性质自动选择最合适的复制方式,而无需手动干预。
缺点:
复杂性增加:尽管混合复制能同时提供效率和精确性,但其内部切换机制可能在调试或故障排查时带来一些复杂性。
4、主从复制的工作过程
Master节点将数据的改变记录成二进制日志(bin log),当Master上的数据发生改变时,则将其改变写入二进制日志中。
Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O线程请求 Master的二进制事件。
同时Master节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至Slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成 sql 语句逐一执行,使得其数据和 Master节点的保持一致,最后I/O线程和SQL线程将进入睡眠状态,等待下一次被唤醒。
注:
●中继日志通常会位于 OS 缓存中,所以中继日志的开销很小。
●复制过程有一个很重要的限制,即复制在 Slave上是串行化的,也就是说 Master上的并行更新操作不能在 Slave上并行操作。
5、MySQL三种同步方式
5.1、异步复制(Async Replication)
MySQL 默认采用异步复制机制。在这种模式下,主库(Master)将数据更新写入到 Binlog 日志文件后,不需要等待这些数据是否已经成功复制到从库(Slave),即可继续处理更多的请求。Master 仅将事件写入 Binlog,但并不知道 Slave 是否以及何时接收并处理了这些事件。
在异步复制的情况下,若 Master 宕机,虽然事务在 Master 上已提交,但可能还没有传输到任何从库。如果存在 Master 到 Slave 的故障转移机制,转为主库的 Slave 可能会丢失这些未复制的事务。虽然异步复制提供了最佳的性能,但存在一定的数据丢失风险。
5.2、同步复制(Sync Replication)
主库将更新写入Binlog日志文件后,需要等待数据更新已经复制到从库中,并且已经在从库执行成功, 然后才能返回继续处理其它的请求。
同步复制提供了最佳安全性,保证数据安全,数据不会丢失,但对 性能有一定的影响。
5.3、半同步复制(Semi-Sync Replication)
MySQL 5.5 版本之后引入了半同步复制功能,它在性能和安全性之间取得了一个折中。当主库提交更新并将其写入二进制日志(Binlog)文件后,会等待至少有一个从库将该更新写入自己的中继日志(Relay Log)中,才能继续处理其他请求。这样可以确保主库传递的 Binlog 内容已经被从库接收并写入中继日志,主库上等待的线程才会收到操作完成的通知。
半同步复制需要在主从服务器上安装半同步复制插件才能启用该功能。如果主库在等待从库响应时超过了 rpl_semi_sync_master_timeout 参数设定的时间(默认10秒),则会关闭半同步复制并自动切换为异步复制模式。当主库 dump 线程发送完一个事务的所有事件并在超时前收到从库的 ACK(确认字符)响应后,主从可以恢复为增强的半同步复制模式。
6、MySQL主从复制延迟
6.1、MySQL主从复制延迟的原因
MySQL数据库中的主从复制延迟主要是由于从服务器在复制和应用主服务器上的更改时出现了延迟。这种延迟可能由多种因素引起,包括但不限于:
网络延迟:主服务器和从服务器之间的网络延迟可能导致复制数据的速度变慢。如果服务器之间的网络连接不稳定或带宽有限,复制延迟就会增加。
硬件性能差异:如果从服务器的硬件(如 CPU 速度、磁盘 I/O 性能、内存大小等)不如主服务器,那么它在处理复制数据时可能会更慢,导致延迟。
高负载:如果主服务器或从服务器承受着高负载,例如处理大量的写操作或复杂查询,可能会导致复制过程变慢,增加延迟。
大事务:主服务器上的大事务需要在从服务器上完整复制和重放。如果事务非常大,复制和应用这些事务可能需要更长的时间,从而导致延迟。
复制配置:复制配置不当也可能导致延迟。例如,如果启用了基于行的复制(row-based replication)而数据变更很频繁,可能会产生大量的复制数据,从而增加延迟。
并发写入:在某些情况下,从服务器上的并发写入操作可能会与复制过程争夺资源,导致复制应用速度减慢。
SQL线程单一:在 MySQL 复制架构中,从服务器上的 SQL 线程是单线程的,这意味着在任何给定时间点,只有一个复制事件被应用。这可能成为复制延迟的瓶颈,尤其是在高更新频率的场景中。
6.2、解决MySQL主从复制延迟方法
优化网络连接:确保主从服务器之间的网络连接稳定和高速。使用高性能的网络设备和优化网络配置可以减少数据传输延迟。
优化主从服务器配置:确保主从服务器的硬件配置足够强大,包括 CPU、内存和磁盘性能。这可以提高数据处理和传输的效率,减少延迟。
调整主从同步参数:通过调整 MySQL 的主从同步参数来优化同步效率。例如,调整 binlog 相关参数、增加 binlog 大小、调整同步线程数等。
避免长事务:长事务可能会导致主从复制延迟,因为在事务未提交之前,主库的 binlog 日志不会被发送到从库。尽量避免长事务的执行。
监控和优化数据库性能:定期监控数据库性能,包括主从服务器的负载、I/O 等情况,及时发现并解决潜在问题。
使用并行复制:MySQL 5.6 及以上版本支持并行复制,可以提高数据同步的效率,减少延迟。
定期清理 binlog 日志:定期清理不再需要的 binlog 日志,避免日志文件过大影响同步效率。
考虑使用第三方工具:使用如 pt-heartbeat、pt-table-checksum 等第三方工具来帮助优化主从复制。
二、部署MySQL主从复制
搭建环境:
设备 操作系统 IP 地址 所需工具/软件/安装包
Master 主服务器 CentOS 7 172.16.88.44 ntp 、 mysql-boost-5.7.20.tar.gz
Slave1 从服务器 CentOS 7 172.16.88.55 ntpdate 、 mysql-boost-5.7.20.tar.gz
Slave2 从服务器 CentOS 7 172.16.88.66 ntpdate 、 mysql-boost-5.7.20.tar.gz
1、部署Master主服务器
安装MySQL软件
#修改主机名,方便区分对应的服务器
[root@localhost ~]#hostnamectl set-hostname master
[root@localhost ~]#bash
#master主服务器需编译安装的mysql软件
可参考《Mysql数据库——概念与安装》:https://blog.csdn.net/A6985HG/article/details/141601495?spm=1001.2014.3001.5501
部署主从服务器同步
#部署主与从服务器的时间同步
[root@master ~]#yum install -y ntp
[root@master ~]#vim /etc/ntp.conf
server 127.127.12.0
#设置本地是时钟源,注意修改网段
fudge 127.127.12.0 stratum 8
#设置时间层级为8(限制在15内)
[root@master ~]#systemctl start ntpd
修改MySQL的配置文件
[root@master ~]#vim /etc/my.cnf
server-id = 1
log-bin=master-bin
#添加,主服务器开启二进制日志
binlog_format = MIXED
log-slave-updates=true
#添加,允许slave从master复制数据时可以写入到自己的二进制日志
[root@master ~]#systemctl restart mysqld
在Master上为Slave授权
[root@master ~]#mysql -uroot -p123456
grant replication slave on *.* to 'myslave'@'172.16.88.%' identified by '123456';
#为172.16.88.网段的从服务器授权
flush privileges;
[root@master ~]#show master status; #查看主服务器当前状态
#File 列显示日志名,Fosition 列显示偏移量
2、搭建Slave1从服务器
安装mysql软件
#修改主机名,方便区分对应的服务器
[root@localhost ~]#hostnamectl set-hostname slave1
[root@localhost ~]#bash
#master主服务器需编译安装的mysql软件
可参考《Mysql数据库——概念与安装》:https://blog.csdn.net/A6985HG/article/details/141601495?spm=1001.2014.3001.5501
部署主从服务器同步
[root@slave1 ~]#yum -y install ntpdate
[root@slave1 ~]#service ntpd start
/usr/sbin/ntpdate 172.16.88.55
#进行时间同步,指向Master服务器IP
[root@slave1 ~]#date
[root@slave1 ~]#crontab -e
*/20 * * * * /usr/sbin/ntpdate 172.16.88.55
修改mysql配置文件
[root@slave1 ~]#vim /etc/my.cnf
server-id = 2
#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin
#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#添加,定义中继日志文件的位置和名称
relay_log_recovery = 1
#选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启
[root@slave1 ~]#systemctl restart mysqld
配置主从同步
[root@slave1 ~]#mysql -u root -p
change master to master_host='172.16.88.44' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=602;
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致,每个人的都不一样
#master_host='172.16.88.44':设置主服务器的IP地址为192.168.88.44。
#master_user='myslave':设置用于复制的用户为'myslave',这个用户在主服务器上必须拥有replication slave权限
#master_password='123456':设置复制用户的密码为'123456'。在实际生产环境中,务必使用强密码
#master_log_file='master-bin.000001':指定从哪个二进制日志文件开始复制,这里是从'master-bin.000001'文件开始
#master_log_pos=602:指定在上述二进制日志文件中的起始位置为1743
#执行这个命令之后,从服务器将开始尝试连接主服务器,并从指定的日志文件和位置开始接收并执行主服务器上的数据变更事件,以实现主从复制的功能。在执行此命令前,请确保主服务器的二进制日志配置正确,且从服务器有权访问主服务器。此外,执行完该命令后通常还需要执行START SLAVE命令来启动复制进程
启动同步,并查看slave1状态
start slave; #启动同步,如有报错执行 reset slave;
show slave status\G #查看 Slave 状态
#确保 IO 和 SQL 线程都是 Yes,代表同步正常
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
注:
一般 Slave_IO_Running: No 的可能性(一步步排查):
网络不通
my.cnf配置有问题
设置主从同步时:密码、file文件名、pos偏移量不对
防火墙、核心防护没有关闭
3、搭建Slave2从服务器
安装MySQL软件
#修改主机名,方便区分对应的服务器
[root@localhost ~]#hostnamectl set-hostname slave2
[root@localhost ~]#bash
#master主服务器需编译安装的mysql软件
可参考《Mysql数据库——概念与安装》:https://blog.csdn.net/A6985HG/article/details/141601495?spm=1001.2014.3001.5501
部署主从服务器同步
[root@slave2 ~]#yum -y install ntpdate
[root@slave2 ~]#service ntpd start
/usr/sbin/ntpdate 172.16.88.44
#进行时间同步,指向Master服务器IP
[root@slave2 ~]#date
[root@slave2 ~]#crontab -e
*/20 * * * * /usr/sbin/ntpdate 172.16.88.44
修改mysql配置文件
[root@slave2 ~]#vim /etc/my.cnf
server-id = 3
#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin
#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#添加,定义中继日志文件的位置和名称
relay_log_recovery = 1
#选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启
[root@slave2 ~]#systemctl restart mysqld
配置主从同步
[root@slave2 ~]#mysql -u root -p
change master to master_host='172.16.88.44' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=602;
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致,每个人的都不一样
#master_host='172.16.88.44':设置主服务器的IP地址为192.168.88.44。
#master_user='myslave':设置用于复制的用户为'myslave',这个用户在主服务器上必须拥有replication slave权限
#master_password='123456':设置复制用户的密码为'123456'。在实际生产环境中,务必使用强密码
#master_log_file='master-bin.000001':指定从哪个二进制日志文件开始复制,这里是从'master-bin.000001'文件开始
#master_log_pos=602:指定在上述二进制日志文件中的起始位置为1743
#执行这个命令之后,从服务器将开始尝试连接主服务器,并从指定的日志文件和位置开始接收并执行主服务器上的数据变更事件,以实现主从复制的功能。在执行此命令前,请确保主服务器的二进制日志配置正确,且从服务器有权访问主服务器。此外,执行完该命令后通常还需要执行START SLAVE命令来启动复制进程
启动同步,并查看slave2状态
start slave; #启动同步,如有报错执行 reset slave;
show slave status\G #查看 Slave 状态
#确保 IO 和 SQL 线程都是 Yes,代表同步正常
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
注:
一般 Slave_IO_Running: No 的可能性(一步步排查):
网络不通
my.cnf配置有问题
设置主从同步时:密码、file文件名、pos偏移量不对
防火墙、核心防护没有关闭
三、MySQL读写分离
示意图
1、MySQL读写分离概述
MySQL 读写分离是一种常见的数据库架构优化方案,旨在提高数据库的整体性能和处理能力。在 MySQL 主从复制环境中,主服务器(Master)主要负责处理写操作(如插入、更新、删除),而从服务器(Slave)负责处理读操作(如查询)。通过这种方式,读写操作被分配到不同的服务器上运行,从而减少主服务器的负载,并提高系统的并发处理能力。
读写分离能够有效地解决数据库在高并发读写场景下的性能瓶颈,特别适用于读操作远多于写操作的应用场景,如电商网站、社交平台等。同时,它还能够增强系统的容错性和可扩展性,增加从服务器的数量以分散读请求,既提升了系统的响应速度,又减轻了单一数据库的压力。然而,读写分离在实现时需要保证数据的实时性与一致性,尤其是处理写操作后从服务器的同步延迟问题,这需要通过合适的调度策略来解决。
2、MySQL读写分离的功能和应用场景
2.1、MySQL读写分离的功能
提高性能:通过将读操作和写操作分离,读写分离可以有效减轻主数据库的负担,提高系统的整体性能。
负载均衡:通过在多个从数据库上分发读请求,可以实现负载均衡,避免单点故障,提高系统的并发处理能力。
提高可用性:读写分离架构可以提高系统的可用性。如果主数据库发生故障,可以快速切换到从数据库,确保系统的正常运行。
扩展性:读写分离可以方便地扩展数据库系统。通过添加更多的从数据库,可以横向扩展系统的读取能力,应对不断增长的读取需求。
故障恢复:当主数据库发生故障时,从数据库可以顶替主数据库的角色,保证系统的持续运行,降低系统宕机的风险。
2.2、MySQL读写分离应用场景
高并发读取:适用于读操作频繁、写操作相对较少的场景,如新闻网站、电子商务平台等,能够显著提升系统的读取性能。
数据报表查询:对于需要大量数据分析和报表生成的应用,读写分离可以加快数据查询速度,提高报表生成的效率。
全文搜索:对于需要进行全文搜索的应用,读写分离可以将搜索操作分担到从数据库上,减轻主数据库的压力。
分布式部署:在分布式系统中,通过读写分离可以简化数据访问模式,提高系统的整体性能和稳定性。
大型社交平台:适用于大型社交平台等需要处理大量用户读取请求的场景,通过读写分离可以更好地应对高并发读取的挑战。
3、实现Mysql读写分离的方法
目前较为常见的 MySQL 读写分离分为以下两种:
①、基于程序代码内部实现
在代码中根据 select 和 insert 进行路由分类,这种方法是生产环境中应用最广泛的。
优点:性能较好,因为直接在程序代码中实现,不需要额外的硬件设备,减少开支。
缺点:需要开发人员实现,运维人员难以参与。如果是大型复杂的 Java 应用,在代码中实现读写分离可能会导致较大的代码改动。
②、基于中间代理层实现
代理位于客户端和服务器之间,接收客户端请求后,通过判断将请求转发到后端数据库。常见的代理程序有以下几种:
MySQL-Proxy:MySQL 的开源项目,通过 Lua 脚本进行 SQL 判断和路由。需要编写大量 Lua 脚本,较为复杂。
Atlas:由奇虎 360 开发,基于 MySQL-Proxy 进行优化,增加了更多功能特性,支持事务和存储过程。在 360 内部,每天承载的读写请求数达数十亿。
Amoeba:由陈思儒开发,基于 Java 语言,阿里巴巴曾在生产环境中使用。优点是易用、移植性强,但不支持事务和存储过程。
由于 MySQL Proxy 需要大量编写 Lua 脚本,对于不熟悉 MySQL Proxy 内置变量和 MySQL Protocol 的人来说较为困难。而 Amoeba 因其易用性和高移植性,广泛应用于生产环境的数据库代理层。
4、读写分离的工作原理
客户端所有的写操作(插入、更新、删除)可以通过Amoeba服务器将请求调度到主服务器上进行
客户端所有的读操作(查询)可以通过Amoeba服务器将请求分发到多个从数据库上进行,以实现负载均衡
主服务器和从服务器的数据通过主从复制机制保持数据的一致性
这种架构模式可以提高系统的性能、可用性和扩展性,是许多高负载应用和网站常用的数据库架构设计模式
四、搭建MySQL读写分离
基于上面的Mysql主从复制的搭建,然后再进行读写分离的搭建!
设备 操作系统 IP 地址 所需工具/软件/安装包
Master 主服务器 CentOS 7 172.16.88.22 ntp 、 mysql-boost-5.7.20.tar.gz
Slave1 从服务器 CentOS 7 172.16.88.33 ntpdate 、 mysql-boost-5.7.20.tar.gz
Slave2 从服务器 CentOS 7 172.16.88.44 ntpdate 、 mysql-boost-5.7.20.tar.gz
Amoeba CentOS 7 172.16.88.55 jdk-6u14-linux-x64.bin 、 amoeba-mysql-binary-2.2.0.tar.gz
客户端 CentOS 7 172.16.88.66 mariadb
1、搭建Amoeba服务器
下载地址:http://sourceforge.net/projects/amoeba/files/,下载amoeba-mysql-binary-2.2.0.tar.gz
解压后直接放入/usr/local/amoeba(该路径随意)
#修改主机名,方便区分对应的服务器
[root@localhost ~]#hostnamectl set-hostname Amoeba
[root@localhost ~]#bash
安装Amoeba软件
因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。
将jdk-6u14-linux-x64.bin 和 amoeba-mysql-binary-2.2.0.tar.gz.0 上传到/opt目录下
#先安装 java 环境
下载jdk安装包
下载地址:https://www.oracle.com/java/technologies/java-archive-javase5-downloads.html
安装包:jdk-1_5_0_22-linux-amd64-rpm.bin
给安装添加可执行权限
chmod +x jdk-1_5_0_22-linux-amd64-rpm.bin
./ jdk-1_5_0_22-linux-amd64-rpm.bin
#按空格到最后一行
#按yes,再按enter
结束后生成一个rpm包jdk-1_5_0_22-linux-amd64.rpm
安装
rpm -ivh jdk-1_5_0_22-linux-amd64.rpm
会自动安装在/usr/local下
/usr/java/jdk1.5.0_22/bin/java -version
在/etc/profile中添加环境变量即可。
安装Amoeba软件
##安装 Amoeba软件##
[root@amoeba local]#mkdir /usr/local/amoeba
[root@amoeba local]#tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba local]#chmod -R 755 /usr/local/amoeba/
[root@amoeba local]#/usr/local/amoeba/bin/amoeba
#如显示amoeba start|stop 说明安装成功
配置Amoeba读写分离及两个从服务器读负载均衡
先必须在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问!
grant all on *.* to test@'172.16.88.%' identified by '123456';
Amoeba服务器配置Amoeba服务
[root@amoeba local]#cd /usr/local/amoeba/conf/
修改dbServer.xml配置文件 【修改之前先备份一下,防止修改出错无法还原】
这里贴一份已经测试通过的配置
[root@mn-test-amoeba-18-84 conf]# cat dbServers.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">
<dbServer name="abstractServer" abstractive="true">
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="manager">${defaultManager}</property>
<property name="sendBufferSize">64</property>
<property name="receiveBufferSize">128</property>
<!-- mysql port -->
<property name="port">3306</property>
<!-- mysql schema -->
<property name="schema">test</property>
<!-- mysql user -->
<property name="user">root</property> # 这里的用户是amoeba服务连接mysql的用户,最好所有mysql都保持一致
<!-- mysql password -->
<property name="password">0cLG%mJW1ynE</property> # 这里的密码是amoeba连接mysql的密码,最好所有mysql都保持一致
</factoryConfig>
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
<property name="maxActive">500</property>
<property name="maxIdle">500</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testOnReturn">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>
<!--写库的配置,即主库-->
<dbServer name="master" parent="abstractServer">
<factoryConfig>
<property name="ipAddress">192.168.18.81</property>
</factoryConfig>
</dbServer>
<!--读库的配置,即从库-->
<dbServer name="readslave01" parent="abstractServer">
<factoryConfig>
<property name="ipAddress">192.168.18.82</property>
</factoryConfig>
</dbServer>
<!--读库的配置,即从库-->
<dbServer name="readslave02" parent="abstractServer">
<factoryConfig>
<property name="ipAddress">192.168.18.83</property>
</factoryConfig>
</dbServer>
<!--从库作为一个虚拟组-->
<dbServer name="slavepool" virtual="true"> # 这个名字在amoeba.xml中会用到
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<property name="loadbalance">1</property>
<property name="poolNames">readslave01,readslave02</property> # 这里的名字是上面定义的slave的名字
</poolConfig>
</dbServer>
</amoeba:dbServers>
然后修改amoeba.xml配置文件,同样修改之前备份一次。
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">
<proxy>
<service name="Amoeba for Mysql" class="com.meidusa.amoeba.net.ServerableConnectionManager">
<!-- 配置amoeba -->
<!-- amoeba端口 -->
<property name="port">8066</property> # 访问amoeba服务的端口
<!-- amoeba地址 -->
<property name="ipAddress">0.0.0.0</property> # 绑定的地址
<property name="manager">${clientConnectioneManager}</property>
<property name="connectionFactory">
<bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">
<property name="sendBufferSize">128</property>
<property name="receiveBufferSize">64</property>
</bean>
</property>
<property name="authenticator">
<bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
<!--访问amoeba的用户名和密码-->
<property name="user">webimajdzkd02_rw</property>
<property name="password">dong@159751</property>
<property name="filter">
<bean class="com.meidusa.amoeba.server.IPAccessController">
<property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
</bean>
</property>
</bean>
</property>
</service>
<!-- server class must implements com.meidusa.amoeba.service.Service -->
<service name="Amoeba Monitor Server" class="com.meidusa.amoeba.monitor.MonitorServer">
<!-- port -->
<!-- default value: random number
<property name="port">9066</property>
-->
<!-- bind ipAddress -->
<property name="ipAddress">127.0.0.1</property>
<property name="daemon">true</property>
<property name="manager">${clientConnectioneManager}</property>
<property name="connectionFactory">
<bean class="com.meidusa.amoeba.monitor.net.MonitorClientConnectionFactory"></bean>
</property>
</service>
<runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">
<!-- proxy server net IO Read thread size -->
<property name="readThreadPoolSize">200</property>
<!-- proxy server client process thread size -->
<property name="clientSideThreadPoolSize">300</property>
<!-- mysql server data packet process thread size -->
<property name="serverSideThreadPoolSize">300</property>
<!-- per connection cache prepared statement size -->
<property name="statementCacheSize">500</property>
<!-- query timeout( default: 60 second , TimeUnit:second) -->
<property name="queryTimeout">60</property>
</runtime>
</proxy>
<connectionManagerList>
<connectionManager name="clientConnectioneManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
<property name="subManagerClassName">com.meidusa.amoeba.net.ConnectionManager</property>
<!--
default value is avaliable Processors
<property name="processors">5</property>
-->
</connectionManager>
<connectionManager name="defaultManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
<property name="subManagerClassName">com.meidusa.amoeba.net.AuthingableConnectionManager</property>
</connectionManager>
</connectionManagerList>
<dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">
<property name="configFile">${amoeba.home}/conf/dbServers.xml</property>
</dbServerLoader>
<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
<property name="ruleLoader">
<bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
<property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
<property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
</bean>
</property>
<property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
<property name="LRUMapSize">1500</property>
<property name="defaultPool">master</property>
<property name="writePool">master</property> # dbServer.xml中定义的名字
<property name="readPool">slavepool</property> # dbServer.xml中定义的名字
<property name="needParse">true</property>
</queryRouter>
</amoeba:configuration>
然后就可以启动服务了。
[root@amoeba conf]#/usr/local/amoeba/bin/amoeba start&
[root@amoeba conf]#netstat -anpt | grep java
#查看8066端口是否开启,默认端口为TCP 8066
2、客户端访问
[root@pc ~]#mysql -u amoeba -p123456 -h 192.168.18.84 -P8066
#远程访问amoeba服务器
3、测试读写分离(关闭同步)
这里说一下测试读写分离的思路:
1. 关闭从库中的slave服务
2. 在主库和从库中创建相同的数据库和表,假设数据库是amoeba,表是test
3. 然后登录从库在多个从库中的amoeba库的 test表写入不同的数据 【为了测试轮询的效果】
客户端连接amoeba服务后,先进入amoeba库,多次执行查test表的操作。看是否在从库之间轮询。
原文链接:https://blog.csdn.net/A6985HG/article/details/141929304