1:在企业应用中,成熟的业务通常数据量都比较大
2:单台MySQL在安全性、高可用性和高并发方面都无法满足实际的需求
3:配置多台主从数据库服务器以实现读写分离
1:MySQL的复制类型
1.Master将用户对数据库更新的操作以二进制格式保存到 Binary Log日志文件中
2.Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容
3.Master接收到来自Slave的IO进程的请求后,通过负责复制的TO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave的I0进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置
4.Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
5.Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行
1:只在主服务器上写,只在从服务器上读
2:主数据库处理事务性查询,从数据库处理SELECT查询
3:数据库复制用于将事务性查询的变更同步到集群中的从数据库
4:读写分离方案
1:建立时间同步环境,在主节点上搭建时间同步服务器
[root@master ~]# yum -y install ntp ntpdate
[root@slave1 ~]# yum -y install ntpdate
[root@slave2 ~]# yum -y install ntpdate
[root@master ~]# ntpdate ntp.aliyun.com
[root@master ~]# vi /etc/ntp.conf
restrict default nomodify # 8
restrict 20.0.0.0 mask 255.255.255.0 nomodify notrap # 17 同步网段
21-24 行删除,添加两句
fudge 127.127.1.0 stratum 8
server 127.127.1.0
[root@master ~]# systemctl restart ntpd
[root@master ~]# netstat -anptu | grep ntpd
udp 0 0 20.0.0.13:123 0.0.0.0:* 77692/ntpd
udp 0 0 0.0.0.0:123 0.0.0.0:* 77692/ntpd
2:从节点同步时间
[root@slave1 ~]# ntpdate 20.0.0.13
[root@slave2 ~]# ntpdate 20.0.0.13
3:主、从节点创建计划任务
[root@master ~]# crontab -e
*/30 * * * * /usr/sbin/ntpdate ntp.aliyun.com # 每半个小时执行一次时间同步
[root@slave1 ~]# crontab -e
*/3 * * * * /usr/sbin/ntpdate 20.0.0.13
[root@slave2 ~]# crontab -e
*/3 * * * * /usr/sbin/ntpdate 20.0.0.13
三台都需安装
1:配置 MySQL master 主服务器
server-id = 1
log_bin=master_bin
log_slave_updates=true
[root@master ~]# systemctl restart mysqld
其中 File 列显示日志名,Position 列显示偏移量,这两个值在后面配置从服务器的时候会用到
slave 应从该点在 master 上进行新的跟新
[root@master ~]# mysql -uroot -p123123
mysql> grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges; # 刷新权限
Query OK, 0 rows affected (0.00 sec)
mysql> show master status; # 查看主服务器信息
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master_bin.000001 | 599 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2:配置 MySQL slave 从1 服务器
[root@slave1 ~]# vi /etc/my.cnf
server-id = 2 # 注意:server-id 不能与主服务器相同
relay_log=relay-log-bin
relay_log_index=slave-relay-bin.index
[root@slave1 ~]# systemctl restart mysqld
接主服务器结果更改下面命令中 master_log_file 和 master_log_pos 的参数
[root@slave1 ~]# mysql -uroot -p123123
mysql> change master to master_host='20.0.0.13',master_user='myslave',master_password='123123',
master_log_file='master_bin.000001',master_log_pos=599;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 20.0.0.13
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master_bin.000001
Read_Master_Log_Pos: 599
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master_bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
3:配置 MySQL slave 从2 服务器
[root@slave2 ~]# vi /etc/my.cnf
server-id = 3 # 注意:server-id 不能与主服务器相同
relay_log=relay-log-bin
relay_log_index=slave-relay-bin.index
[root@slave2 ~]# systemctl restart mysqld
接主服务器结果更改下面命令中 master_log_file 和 master_log_pos 的参数
[root@slave2 ~]# mysql -uroot -p123123
mysql> change master to master_host='20.0.0.13',master_user='myslave',master_password='123123',
master_log_file='master_bin.000001',master_log_pos=599;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 20.0.0.13
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master_bin.000001
Read_Master_Log_Pos: 599
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master_bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
4:验证主从复制效果
三台数据库执行结果应该相同
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database txt;
Query OK, 1 row affected (0.15 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| txt |
+--------------------+
5 rows in set (0.01 sec)
5:新建数据表 test ,客户机登录 Amoeba 时用
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
1:时间同步
[root@amoeba ~]# ntpdate 20.0.0.13
[root@amoeba ~]# crontab -e
*/3 * * * * /usr/sbin/ntpdate 20.0.0.13
2:在主机 amoeba 上安装 JDK
[root@amoeba ~]# tar zxvf jdk-8u91-linux-x64.tar.gz
[root@amoeba ~]# cp -rv jdk1.8.0_91/ /usr/local/java
[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 $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/java/bin:/usr/local/java/jre/bin
[root@amoeba ~]# echo $CLASSPATH
./:/usr/local/java/lib:/usr/local/java/jre/lib
[root@amoeba ~]# java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
3:安装并配置 Amoeba 软件
[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
#JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPermSize=96m"#32行,注释
JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k" # 接 32 行下面添加
#!/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
rm -rf $PIDFILE
echo "done"
;;
restart)
$SHUTDOWN BIN
sleep 1
$AMOEBA_BIN
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}"
exit 1
esac
[root@amoeba ~]# chmod 755 /etc/init.d/amoeba
[root@amoeba ~]# chkconfig --add amoeba
4:进入三台 MySQL 数据库开放权限给 Amoeba 访问
mysql> grant all privileges on *.* to 'test'@'20.0.0.%' identified by '123.com';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
5:编辑 amoeba 配置文件
[root@amoeba ~]# vi /usr/local/amoeba/conf/amoeba.xml
<property name="user">amoeba</property> # 28
<property name="password">123456</property> # 30
<property name="defaultPool">master</property> # 83
85 和 88 去掉
<property name="writePool">master</property> # 86
<property name="readPool">slaves</property> # 87
6:编辑 dbServers.xml 配置文件
[root@amoeba ~]# vi /usr/local/amoeba/conf/dbServers.xml
<property name="user">test</property> # 26
<property name="password">123.com</property> # 28
<dbServer name="master" parent="abstractServer"> # 43
<property name="ipAddress">20.0.0.13</property> # 46
<dbServer name="slave1" parent="abstractServer"> # 50
<property name="ipAddress">20.0.0.14</property> # 53
接 53 行后面复制添加一组 slave2
<dbServer name="slave2" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.15</property>
</factoryConfig>
</dbServer>
<dbServer name="slaves" virtual="true"> # 64
<property name="poolNames">slave1,slave2</property> # 70
7:启动 amoeba 服务
[root@amoeba ~]# cd /usr/local/amoeba/bin/
[root@amoeba bin]# ./launcher
8:查看 8066 号端口是否监听
[root@amoeba bin]# netstat -anpt | grep java
tcp6 0 0 :::8066 :::* LISTEN 52878/java
tcp6 0 0 20.0.0.12:57802 20.0.0.15:3306 ESTABLISHED 52878/java
tcp6 0 0 20.0.0.12:52758 20.0.0.13:3306 ESTABLISHED 52878/java
tcp6 0 0 20.0.0.12:33636 20.0.0.14:3306 ESTABLISHED 52878/java
9:客户机登录测试
需安装软件
[root@client ~]# yum -y install mariadb*
开启服务
[root@client ~]# systemctl start mariadb
登录
[root@client ~]# mysql -uamoeba -p123456 -h 20.0.0.12 -P8066
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
| txt |
+--------------------+
6 rows in set (0.01 sec)
MySQL [(none)]> create table a1(id int(10),name varchar(64),address varchar(20));
Query OK, 0 rows affected (0.01 sec)
MySQL [(none)]> insert into a1 values(1,'lisi','this is master');
Query OK, 1 row affected (0.01 sec)
三台服务器查询结果一样
mysql> select * from test.a1;
+------+------+----------------+
| id | name | address |
+------+------+----------------+
| 1 | lisi | this is master |
+------+------+----------------+
1 row in set (0.00 sec)
断开
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
客户机写入数据
MySQL [(none)]> insert into a1 values(2,'wangwu','this is master2');
Query OK, 1 row affected (0.00 sec)
主服务器查询测试
mysql> select * from test.a1;
+------+--------+-----------------+
| id | name | address |
+------+--------+-----------------+
| 1 | lisi | this is master |
| 2 | wangwu | this is master2 |
+------+--------+-----------------+
2 rows in set (0.00 sec)
从服务器查询,没有写入的数据
mysql> select * from test.a1;
+------+------+----------------+
| id | name | address |
+------+------+----------------+
| 1 | lisi | this is master |
+------+------+----------------+
1 row in set (0.00 sec)
删除从1、从2 服务器表里的数据
mysql> delete from test.a1;
Query OK, 1 row affected (0.01 sec)
从1、从2 单独写入数据
mysql> insert into test.a1 values(100,'zhangsan','slave1');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test.a1 values(200,'zhaoliu','slave2');
Query OK, 1 row affected (0.00 sec)
客户机多次查询
多次查询后依旧是这两个数据,
MySQL [(none)]> select * from test.a1;
+------+---------+---------+
| id | name | address |
+------+---------+---------+
| 200 | zhaoliu | slave2 |
+------+---------+---------+
1 row in set (0.00 sec)
MySQL [(none)]> select * from test.a1;
+------+----------+---------+
| id | name | address |
+------+----------+---------+
| 100 | zhangsan | slave1 |
+------+----------+---------+
1 row in set (0.01 sec)
结论:主从同步关闭时,客户机通过 amoeba 写入数据是写在主服务器里的,客户机通过 amoeba 读出数据第一次是从从1 里读的,第二次是从从2 里度的,默认轮询
10:重新主从同步
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master_bin.000001 | 2843 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> change master to master_host='20.0.0.13',master_user='myslave',master_password='123123',
master_log_file='master_bin.000001',master_log_pos=2843;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 20.0.0.13
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master_bin.000001
Read_Master_Log_Pos: 2843
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master_bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: