**6. Mysql主从同步+读写分离+**读负载均衡
目标:
- 搭建mysql一主两从同步
- 搭建从mysql读负载均衡
- 结合web工程实现mysql读写分离
整体示意图:
如图所示:
192.168.238.129:负载均衡服务器
192.168.238.128: mysql-slave1服务器 mysql-master服务器
192.168.238.131: mysql-slave2服务器
VIP: 192.168.238.130 提供对外的统一读IP
Tomcat通过AOP根据方法名来区分读写操作,分别访问不同的数据库连接,从而实现mysql读写分离。
当执行写操作时,直接从192.168.238.128:3003写;当执行读操作时,访问VIP192.168.238.130, 由LVS负载均衡分配给192.168.238.128:3306或者192.168.238.131:3306从而实现读负载均衡。
Tomcat主从同步利用自身的二进制日志方式来实现同步。
简要步骤:
- 搭建keepalived+lvs实现读mysql负载均衡。
- 搭建mysql主从同步。
- 搭建tomcat web工程来实现读写分离。
具体操作如下:
- 搭建keepalived+lvs实现读mysql负载均衡。
Docker search mysql
Docker pull mysql
192.168.238.131 mysql_slave1
192.168.238.128 mysql_slave2
192.168.238.129 keepalived+lvs负载均衡
192.169.238.130 对外统一VIP
1.1在192.168.238.131 启动从mysql1
Docker run –name mysql_slave1
–p 3306:3306
-e MYSQL_ROOT_PASSWORD=123456 –d mysql
Mysql –h 192.168.238.131 –P 3306 –u root –p
连接数据库,新建数据库slave1_131;
- 同理在192.168.238.128启动mysql_slave2
Docker run –name mysql_slave2
–p 3306:3306
-e MYSQL_ROOT_PASSWORD=123456 –d mysql
连接,新建数据库slave2_128;
- 在128和131上,分别新建realserver脚本如下:
chmod 755 realserver;
启动脚本,查看ip add
bash realserver start;
131显示如下:
128显示如下:
说明:
- SNS_VIP 直接路由模式的VIP必须和服务器对外提供的ip地址在同一个网段;
- VIP被绑定在环回接口lo0:0上,广播地址是其本身,子网掩码255.255.255.255;
- 抑制ARP广播。
- 负载均衡机192.168.238.129设置如下:
安装ipvsadm服务:
Apt-get install ipvsadm
Lsmod | grep ip_vs
Ipvsadm
安装keepalived
Apt-get install keepalived
Cd /etc/keepalived
编辑配置文件:keepalived.conf
配置文件说明:
- 搭建lvs,只需使用virtual_server虚拟块配置即可。
- 虚拟机端口和真实机端口应该保持一致,否则访问不到真实机相应端口。
- Virtual_server 虚拟机IP和端口号
- Delay_loop 运行情况检查时间,单位秒
- Lb_algo 负载调试算法
- Lb_kind DR/NAT/TUN
- Persistence_timeout 会话保持时间
- Protocol TCP 转发协议类型 TCP/UDP
- Real_server 真实服务器的IP和端口号
- Weight 该真实机的权重
- Connect_timeout 10 10秒无响应超时
- Nb_get_retry 重试次数
- Delay_before_retry 重试间隔
- Connect_port 3306 使用3306端口进行保活
Service keepalived start;
Service keepalived status;
Ipvsadm
在负载均衡机129上连接VIP,来访问数据库;
Mysql –h 192.168.238.130 –P 3306 –u root -P
可知成功连接131真实服务器数据库,因为上面配置131weight=3,所以权重较大。
再一次访问
可知此时连接128真实服务器数据库
- 搭建mysql主从同步。
2.1准备主从mysql配置文件
查看一下mysql容器的mysqld.conf配置文件位置
/etc/mysql/mysql.conf.d/mysqld.cnf
Mysql-master mysqld.cnf文件配置
Log-bin必须设置
Server-id必须设置,并且唯一
Mysql-slave1 mysqld.cnf 文件:
Mysql-slave2 mysqld.cnf 文件:
- 重新启动容器,把配置文件挂载到相应目录
在192.168.238.131启动mysql_slave1容器:
Docker run –name mysql_slave1 –p 3306:3306
–v /data/mysql-backup1/mysqld.cnf :/etc/mysql/mysqld.conf.d/mysqld.cnf
-e MYSQL_ROOT_PASSWORD=123456 -d mysql
在192.168.238.129启动mysql_master容器:
Docker run –name mysql_master –p 3306:3306
–v /data/mysql-master/mysqld.cnf :/etc/mysql/mysqld.conf.d/mysqld.cnf
-e MYSQL_ROOT_PASSWORD=123456 –d mysql
在192.168.238.128启动mysql_slave2容器:
Docker run –name mysql_slave2 –p 3306:3306
–v /data/mysql-backup2/mysqld.cnf :/etc/mysql/mysqld.conf.d/mysqld.cnf
-e MYSQL_ROOT_PASSWORD=123456 -d mysql
- 配置主从复制
登录mysql_master
Mysql –h 192.168.238.129 –P 3306 –u root –p
123456
分配复制权限:
Grant replication slave on *.* to ‘root’@’%’ identified by ‘123456’
replication slave 分配复制权限
*.*数据库所有表都可以
‘%’IP限制,在此设置所有主机
Root用户名
登录mysql-slave1
配置从服务器1复制功能:
change master to master_host =’192.168.238.129’,
master_port=3306,
master_user=’root’ ,
master_password=’123456’,
master_log_file=’mysql-bin.000003’,
master_log_pos=429;
启动复制功能
start slave;
show slave status;
其中:
Slave_IO_State = Waiting for master to send event
Slave_IO和Slave_SQL 都是 YES
则表示主从复制配置成功。
登录mysql-master新建数据库test_slave1;
此时slave1的状态:
可知,mysql_master和mysql_slave2已经同步。
同理配置mysql_slave2;
change master to master_host =’192.168.238.129’,
master_port=3306,
master_user=’root’ ,
master_password=’123456’,
master_log_file=’mysql-bin.000003’,
master_log_pos=429;
start slave;
show slave status;
show databases;
可知mysql_slave2和mysql_master已经同步。
此时,
写mysql:
192.168.238.129 3306
读mysql
192.168.238.130 3306(VIP)
在192.168.238.131和192.168.238.128启动realserver脚本
bash realserver start
在192.168.238.129上启动keepalived
Ipvsadm:
连接129:3306和130:3306,测试如下:
可知读写ip和端口号已经成功。
- 搭建tomcat web工程来测试读写分离。
/usr/local/tomcat/webapps/ssh_runner.war
登录129负载均衡服务器:
登录slave1和slave2,关闭slave功能;
Stop slave;
此时,slave1和slave2表index_msg的状态
Slave1的状态:
Slave2的状态;
利用index_msg表的记录数量来区分slave1的负载均衡。
将mysql-master迁移到128 3003端口,其余保持不变。
现在准备web测试工程ssh-runner.war
启动:
http://localhost:8080/ssh-runner/back/getMethodTest
可知数据库切换到slave,轮询读取从库的数据(此时主从复制已关闭),从而实现了读从mysql负载均衡。
http://localhost:8080/ssh-runner/back/saveMethodTest
数据库切换到master,从而实现了读写分离。
工程详细配置如下:
配置文件如下:
- dataSource.xml 配置主从数据源
在dataSource.xml中添加如下bean:
parentDataSource, masterDataSource, slaveDataSource, dataSource
- spring-hibernate.xml 配置事务和AOP
需要根据工程来修改相应配置:
AOP的适用范围,加在service层还是dao层
方法名命名规则需要统一
- pom.xml配置主从数据库的连接,用户名和密码
代码修改:
com.huanke.sshshell.aop
DataSourceAdvice
DataSourceSwitcher
DynamicDataSource
未解决的问题:
- VIP的访问,工程部署在本地可以运行,部署在linux虚拟机,VIP访问不到。网络配置等问题;
- 代码层的方案还没有解决,方法名的规范以及AOP切面的位置(因为现在工程业务逻辑乱,service和controller层均有业务代码)
实现读写分离可以尝试使用数据库中间件Atlas以及一些持久层框架Rose,使用注解等便捷,易于开发。