MySQL主从复制与读写分离
作者:互联网
目录
一、部署原由、
原因:
- 保证主库和从库数据一直,防止单点故障,数据丢失
- 在企业应用中,成熟的业务通常数据量都比较大
- 单台MySQL在安全性、高可用性和高并发方面都无法满足实际的需求
- 配置多台主从数据库服务器以实现读写分离
二、MySQL主从复制原理
2.1 MySQL的复制类型
- 基于语句的复制
- 基于行的复制
- 混合类型的复制
2.2 MySQL主从复制的工作过程
Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
2.3复制的基本过程如下:
-
Master将用户对数据库更新的操作以二进制格式保存到Binary Log日志文件中
-
Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
IO进程:从数据库复制主数据库上二进制日志的进程 -
Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
-
Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
-
Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行.
Sql进程:将二进制日志内容翻译成SQL语句写进从数据库
三、MySQL读写分离原理
-
只在主服务器上写,只在从服务器上读
-
主数据库处理事务性查询,从数据库处理SELECT查询
-
数据库复制用于将事务性查询的变更同步到集群中的从数据库
-
读写分离方案
基于程序代码内部实现 基于中间代理层实现 -1、MySQL-Proxy -2、Amoeba
3.1 MySQL读写分离的工作过程
四、部署详情
4.1 部署原理
主从数据库之间先时间同步,后主从复制,amoeba配置读写分离,授权。最后客户机登录验证
4.2 部署准备
MySQL主数据库 | 20.0.0.11 |
---|---|
MySQL从数据库1 | 20.0.0.12 |
MySQL从数据库2 | 20.0.0.13 |
Amoeba | 20.0.0.14 |
客户端 | 20.0.0.15 |
改名:
[root@server1 ~]# hostnamectl set-hostname master
[root@server2 ~]# hostnamectl set-hostname slave1
[root@server3 ~]# hostnamectl set-hostname slave2
[root@server4 ~]# hostnamectl set-hostname amoeba
[root@server5 ~]# hostnamectl set-hostname client
所有设备关闭防火墙:
[root@master ~]# systemctl stop firewalld
[root@master ~]# setenforce 0
4.3 部署流程
4.31 主从数据库时间同步
主数据库上
1.设置时间同步
[root@master ~]# vi /etc/resolv.conf #编辑配置文件
添加
nameserver 8.8.8.8
[root@master ~]# yum -y install ntpdate ntp #安装ntp软件
[root@master ~]# ntpdate ntp.aliyun.com #时间同步
[root@master ~]# date #查看当前日期
[root@master ~]# vi /etc/ntp.conf #编辑配置文件
添加修改
8: restrict default nomodify #定义默认访问规则,nomodify禁止远程主机修改本地服务器配置
17: restrict 20.0.0.0 mask 255.255.255.0 nomodify notrap
#从20.0.0.1-20.0.0.254的主机都可以使用我们的ntp服务来时间同步
21: fudge 127.127.1.0 stratum 10
#设置本机的时间层级为10级,0级表示时间层级为0级,是向其他服务器提供时间同步源的意思,不要设置为0级
22: server 127.127.1.0 #设置本机为时间同步源
[root@master ~]# systemctl restart ntpd 重启服务
[root@master ~]# netstat -anptu | grep ntpd 查看端口状态
2.部署任务计划
[root@master ~]# crontab -e
*/30 * * * * /usr/sbin/ntpdate ntp.aliyun.com
#每隔30分钟进行一次同步对象为阿里云时钟网站的时间同步
[root@master ~]# date #查看当前日期
从数据库1,2上
[root@slave1 ~]# yum -y install ntpdate #安装ntp
[root@slave1 ~]# ntpdate 20.0.0.11 #设置同步源
[root@slave1 ~]# date #查看当前日期
[root@slave1 ~]# crontab -e #部署任务计划
*/3 * * * * /usr/sbin/ntpdate 20.0.0.11
#每隔3分钟进行一次同步对象为20.0.0.11(主数据库)的时间同步
[root@slave1 ~]# date 查看当前日期
以上主从时间同步设置完成
4.32 配置主从复制
在主数据库上
[root@master ~]# vi /etc/my.cnf #开启二进制日志
添加:
log_bin=master_bin #同步的二进制日志开启前缀
log_slave_updates=true #允许日志同步给从数据库
[root@master ~]# systemctl restart mysqld #重启服务
[root@master ~]# mysql -uroot -p123123 #登录数据库
mysql> grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123123'; #设置授权
--------------------解析---------------------------------
grant replication slave #授权复制权限从数据库
on *.* :#可复制所有库,所有表,
'myslave'@'20.0.0.%' :#授权用户,用户登录范围,网段,
identified by : #识别密码
-----------------------------------------------------------
mysql> flush privileges; #刷新权限
mysql> show master status; #查看主数据库状态信息
数据库1上
[root@slave1 ~]# vi /etc/my.cnf
添加修改:
server-id = 2 #服务id为2
relay_log=relay-log-bin #二进制日志的中继日志前缀
relay_log_index=slave-relay-bin.index #中继日志索引
[root@slave1 ~]# systemctl restart mysqld
[root@slave1 ~]# mysql -uroot -p123123 #登录数据库
mysql> change master to master_host='20.0.0.11',master_user='myslave',master_password='123123',master_log_file='master_bin.000001',master_log_pos=599;
----------------------------解析--------------------------
master_host='20.0.0.11':#主数据库ip地址
master_user='myslave':#主数据库授权用户名
master_password='123123':#授权密码
master_log_file='master_bin.000001':#主从同步日志文件
master_log_pos=599:日志开始路径,主从复制位置
-------------------------------------------------------
mysql> start slave; 开启从状态
mysql> show slave status\G 查看从数据库状态信息
补充:
解析线程错误:
1.I/0线程显示为NO:主库与从库网络不通、主库未授权给从库
若从库查看连接主库I/0线程状态为conneting,-直是这个状态,考虑双方的防火墙是否开启。
2.SQL线程显示为NO:从库日志和位置点与主不同步
数据库2上同理配置
[root@slave2 ~]# vi /etc/my.cnf
添加修改:
server-id = 3 #服务id为3
relay_log=relay-log-bin #二进制日志的中继日志前缀
relay_log_index=slave-relay-bin.index #中继日志索引
[root@slave2 ~]# systemctl restart mysqld
[root@slave2 ~]# mysql -uroot -p123123
mysql> change master to master_host='20.0.0.11',master_user='myslave',master_password='123123',master_log_file='master_bin.000001',master_log_pos=599;
mysql> start slave;
mysql> show slave status\G
4.33 进行主从测试
主数据库上
mysql> show databases; #查看数据库信息
mysql> create database wang; #创建新的数据库wang
mysql> show databases; #查看数据库信息
在从数据库上进行查看是否新生成wang库
mysql> show databases; #查看库信息
因为ameoba用户授权给用户时默认的数据库为test
所以在主数据库时创建数据库test
mysql> create database test;
mysql> show databases;
4.34 设置读写分离
前端数据库ameoba上
时间同步
[root@amoeba ~]# yum -y install ntpdate #安装ntp软件
[root@amoeba ~]# ntpdate 20.0.0.11 #设置同步源
[root@amoeba ~]# crontab -e #设置任务计划
*/30 * * * * /usr/sbin/ntpdate 20.0.0.11
添加jdk安装包
[root@amoeba ~]# ls -lh
[root@amoeba ~]# tar zxvf jdk-8u91-linux-x64.tar.gz #解压缩
root@amoeba ~]# cp -rv jdk1.8.0_91/ /usr/local/java
-rv:#递归,显示过程
[root@amoeba ~]# vi /etc/profile #设置环境变量
结尾添加:
export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export CLASSPATH=./:$JAVA_HOME/lib:$JRE_HOME/lib
[root@amoeba ~]# source /etc/profile #设置生效
[root@amoeba ~]# echo $CLASSPATH #输出类路径信息
[root@amoeba ~]# java -version #查看版本
安装amoeba管理软件
1.添加 amoeba-mysql-3.0.5-RC-distribution.zip
[root@amoeba ~]# ls -lh
[root@amoeba ~]# unzip amoeba-mysql-3.0.5-RC-distribution.zip #解压缩
[root@amoeba ~]# mv amoeba-mysql-3.0.5-RC/ /usr/local/amoeba #剪贴
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/ #授权
[root@amoeba ~]# vi /usr/local/amoeba/jvm.properties #编辑配置文件
在32行下添加,并注释32行数据
JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k" #缓存空间大小设置
2.创建启动脚本
[root@amoeba ~]# vi /etc/init.d/amoeba
#!/bin/bash
#chkconfig: 35 20 90
export JAVA_HOME=/usr/local/java
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
NAME=Amoeba
AMOEBA_BIN=/usr/local/amoeba/bin/launcher
SHUTDOWN_BIN=/usr/local/amoeba/bin/shutdown
PIDFILE=/usr/local/amoeba/Amoeba-MySQL.pid
SCRIPTNAME=/etc/init.d/amoeba
case "$1" in
start)
echo -n "Starting $NAME..."
$AMOEBA_BIN
echo "done"
;;
stop)
echo -n "Stopping $NAME..."
$SHUTDOWN_BIN
echo "done"
;;
restart)
$SHUTDOWN_BIN
sleep 1
$AMOEBA_BIN
;;
*)
echo "Usage:$SCRIPTNAME {start|stop|restart}"
exit 1
;;
esac
[root@amoeba ~]# chmod +x /etc/init.d/amoeba #添加权限
[root@amoeba ~]# chkconfig --add amoeba #加入系统管理
[root@amoeba ~]# service amoeba start #重启服务
[root@amoeba ~]# netstat -anpt | grep 8066 #查看端口状态
tcp6 0 0 :::8066 :::* LISTEN 60877/java
4.341 在主从数据库上进行授权配置
主从数据库都设置
mysql> grant all privileges on *.* to 'test'@'20.0.0.%' identified by '123.com';
mysql> flush privileges;
4.342 在前端上授权客户端登录时用户名和密码
编辑配置文件
[root@amoeba ~]# cd /usr/local/amoeba/
[root@amoeba amoeba]# vi conf/amoeba.xml
设置客户端连接amoeba前端服务器时使用的用户名和密码
<property name="user">amoeba</property> #28行,修改用户名
<property name="password">123123</property #30行,修改密码
4.343 设置读与写数据库的池
<property name="defaultPool">master</property> #83行修改默认池
删除注释
<property name="writePool">master</property> #主数据库负责写
<property name="readPool">slaves</property> #从数据库负责读
编辑配置文件
[root@amoeba amoeba]# vi conf/dbServers.xml
定义amoeba登录上数据库的授权用户名与密码
<!-- mysql user -->
<property name="user">test</property> #修改
<property name="password">123.com</property> #修改
设置主服务,地址
<dbServer name="master" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.11</property>
</factoryConfig>
</dbServer>
设置从服务器1,地址
<dbServer name="slave1" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.12</property>
</factoryConfig>
</dbServer>
复制从服务器1,地址配置数据
设置从服务器2,地址
<dbServer name="slave2" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.13</property>
</factoryConfig>
</dbServer>
设置定义池
<dbServer name="slaves" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
<property name="loadbalance">1</property>
<!-- Separated by commas,such as: server1,server2,server1 -->
<property name="poolNames>slave1,slave2</property>
</poolConfig>
</dbServer>
[root@amoeba amoeba]# cd
[root@amoeba ~]# /usr/local/amoeba/bin/shutdown #关闭服务一定使用自带脚本关闭及启动服务
kill -15 16477
[root@amoeba ~]# /usr/local/amoeba/bin/launcher #启动服务
[root@amoeba ~]# netstat -anpt | grep 8066 查看8066端口状态
tcp6 0 0 :::8066 :::* LISTEN 60877/java
完成以上匹配
4.344 开始设置客户机
[root@client ~]# yum -y install mariadb* #安装软件
[root@client ~]# systemctl start mariadb.service #启动服务
[root@client ~]# mysql #登录数据库
MariaDB [(none)]> exit #退出
[root@client ~]# mysql -uamoeba -p123123 -h 20.0.0.14 -P8066 #登录前端数据库
用户名amoeba,密码123123,ip地址20.0.0.14,端口号8066
4.4 测试部署效果读写分离
4.41 测试读写分离
在master主数据库上创建的数据库或者表,两个从数据库会同步----通过amoeba操作的
在客户端上
[root@client ~]# mysql -uamoeba -p123123 -h 20.0.0.14 -P8066
MySQL [(none)]> use test; #使用数据库
MySQL [test]> create table tree(id int(10),name varchar(128),guanli varchar(128)); #创建表tree
MySQL [test]> insert into tree values(1,'zhangsan','this is master'); #插入数据记录
主数据库上查看
[root@master ~]# mysql -uroot -p123123
mysql> use test; #使用数据库
mysql> select * from tree; #查询所有内容字段
从数据库1,2查看
[root@slave1 ~]# mysql -uroot -p123123 #从1
[root@slave2 ~]# mysql -uroot -p123123 #从2
mysql> select * from test.tree;
4.42 关闭主从同步复制,查看情况
主从复制关闭,再次添加数据,此时因为主数据库负责写操作,从数据库负责读操作,所以此时应只有主数据库上可以查看到新增的数据,从数据库上无变化
客户端添加数据记录
MySQL [test]> insert into tree values(2,'dao','that was master2');
数据库上
mysql> stop slave; #关闭主从同步
客户端再次添加数据记录
MySQL [test]> insert into tree values(3,'small','this is master3');
主数据库上查看 #能查看到最新添加数据
mysql> select * from tree;
从数据库上查看 #关闭主从同步后数据查看不到
mysql> select * from test.tree;
4.43 关闭主从同步复制,查看情况
在从数据库上
写入不同的数据,查看客户端读取时情况
在从数据库1上
mysql> delete from test.tree; #删除test库中的表tree
mysql> select * from test.tree; #查看test库中的表tree中的所有内容
mysql> insert into test.tree values(10,'wang','this is slave1');#插入数据记录
mysql> select * from test.tree; #查看所有内容
在从数据库2上
mysql> delete from test.tree;
mysql> select * from test.tree;
mysql> insert into test.tree values(20,'dao','this is slave2');
mysql> select * from test.tree;
在客户端进行读取查看
MySQL [test]> select * from test.tree; #slave1关闭主从同步创的数据,客户机依然能查看到
说明客户机提供Amoeba写入数据,写在主数据库上,从Amoeba中读取数据库信息,是从从数据库中读取的
此时在主数据库上查看日志状态信息
mysql> show master status; #查看主数据库的状态信息
4.44 恢复从数据库1与主数据库的主从同步
从数据库1上
mysql> change master to master_host='20.0.0.10',master_user='myslave',master_password='abc123',master_log_file='master_bin.000001',master_log_pos=2421;
mysql> start slave; #开启从状态
mysql> show slave status\G #查看从数据库状态信息
标签:主从复制,log,数据库,mysql,amoeba,master,MySQL,root,读写 来源: https://blog.csdn.net/kang_01/article/details/111829924