这里写目录标题
- 一、主从复制与读写分离的意义
- 二、主从数据库实现同步(主从复制)
- 三、主从读写分离
- 四、案例实操
一、主从复制与读写分离的意义
企业中的业务通常数据量都比较大,而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求,所以需要配置多台主从数据服务器,以实现主从复制,增加数据可靠性,读写分离,也减少数据库压力和存储引擎带来的表锁定和行锁定问题。
二、主从数据库实现同步(主从复制)
什么是主从复制?简单来说就是在主服务器上执行的语句,从服务器执行同样的语句,在主服务器上的操作在从服务器产生了同样的结果。
主从复制的基本过程如下:
- Master(主数据库)将用户对数据库更新的操作以二进制格式保存到BinaryLog日志文件中。
- Slave(从数据库)上面的I0进程连接上Master, 并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容。
- Master接收到来自Slave的I0进程的请求后,通过负责复制的I0进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的I0进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置。
- Slave的I0进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master “我需要从某个bin- log的哪个位置开始往后的日志内容,请发给我”。
- Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay- log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
三、主从读写分离
只在主服务器上写,在从服务器上读;
主数据库处理事务性查询,从数据库处理SELECT查询;
进行读操作时,是在两个从服务器上轮流读取,利用虚拟模块MySQL-Proxy做读取从服务器时的轮询。
四、案例实操
环境准备:需要准备五台主机,一台作主数据库服务器,两台做从服务器,还需要一台Amoeba的服务器作为中间代理,用于客户机登录数据库进行读写操作,而不用直接登录主从服务器。
三台主机上都编译安装好mysql5.7,安装过程见另一篇文章,Mysql安装链接
1、为了保证数据同步必须先保证时间同步,在三台服务器均做时间同步
[root@master ~]# ntpdate ntp.aliyun.com
21 Oct 18:29:46 ntpdate[44242]: step time server 120.25.115.20 offset 1.449094 sec
2、主服务器上配置(IP:192.168.247.130)
修改配置文件:
vim /etc/my.cnf
#在[Mysqld]模块修改
server-id = 11 //三台主从数据库的id必须不同
log-bin = master-bin //主服务器日志文件
log-slave-updates=true //允许从服务器更新
[root@master ~]# systemctl restart mysqld.service //配置文件修改后必须重启
登录主数据库给从数据库授权:
[root@master ~]# mysql -uroot -p
Enter password:
mysql> grant replication slave on *.* to 'myslave'@'192.168.247.%' identified by 'abc123'';
Query OK, 0 rows affected, 1 warning (0.01 sec)
//给从服务器授权,允许192.168.247.网段的服务器使用myslave访问所有库的所有表
mysql> flush privileges; //策略刷新
Query OK, 0 rows affected (0.00 sec)
mysql> show master status; //查看主服务器状态,日志用于从服务器同步,position是当前定位
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 154 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (
3、从服务器上配置(IP:192.168.247.140 和 192.168.247.150)
修改配置文件:
vim /etc/my.cnf
server-id = 22 //另一个从服务器为33
relay-log = relay-log-bin //从主服务器上同步日志文件记录到本地
relay-log-index = slave-relay-bin.index //建立索引文件,定义relay-log的位置和名称
[root@slave1 ~]# systemctl restart mysqld
登录数据库配置:
mysql> change master to master_host='192.168.247.130',master_user='myslave',master_password='abc123',master_log_file='master-bin.000001',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
##指明从哪里找什么文件的什么位置进行复制
mysql> start slave; //开启从复制
Query OK, 0 rows affected (0.00 sec)
master_log_file:需要同步的二进制日志文件名,即主服务器上查询到的状态中file
master_log_pos:断点位置,即主服务器上查询到的状态position
查看从服务器状态:
mysql> show slave status \G
I/O线程与SQL线程都为Yes,主从复制完成
4、验证主从复制效果
在主服务器上创建aaa数据库:
mysql> create database aaa;
Query OK, 1 row affected (0.01 sec)
在两个从服务器上查看:有aaa数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| aaa |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
同步到了主服务器的数据,主从复制实现。
另起一台主机,安装Amoeba:(IP:192.168.247.170)
1、首先安装jdk依赖包
[root@server2 ~]# tar xf jdk-8u91-linux-x64.tar.gz
[root@server2 ~]# cp -rf jdk1.8.0_91/ /usr/local/java
##配置环境变量
[root@server2 ~]# vim /etc/profile
在末尾加入
export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$JAVA_HOME/bin:$AMOEBA_HOME/bin
export CLASSPATH=./:/local/java/lib:/usr/local/java/jre/lib
[root@server2 ~]# source /etc/profile //生效
2、安装Amoeba,并启动
[root@server2 ~]# unzip amoeba-mysql-3.0.5-RC-distribution.zip //解压安装包
[root@server2 ~]# mv amoeba-mysql-3.0.5-RC /usr/local/amoeba //创建并移动至工作目录
[root@server2 ~]# chmod -R 755 /usr/local/amoeba //给执行权限
[root@server2 ~]# vi /usr/local/amoeba/jvm.properties
#将32行注释掉并添加下面一行
#JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPerSize=96m"
JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k"
[root@server2 ~]# cd /usr/local/amoeba/bin/
[root@server2 bin]# launcher
[root@server2 bin]# netstat -anpt | grep 8066
tcp6 0 0 :::8066 :::* LISTEN 1829/java
##Amoeba开启,主机会强制关机,需要自行开机
3、修改Amoeba配置文件
## 进入配置文件目录
[root@server2 bin]# cd /usr/local/amoeba/conf
需要修改下面两个配置文件
第一个配置文件修改:
vi amoeba.xml
#28行修改,允许客户机登录amoeba的账户名,密码
#84行下取消注释,并设置读写池
第二个配置文件修改:
vi dbServers.xml
#修改如下配置
(不修改为mysql的话,也可以新建test数据库。)
配置文件修改完成后,重新启动Amoeba,并查看状态
cd /usr/local/amoeba/bin/
launcher
[root@server2 bin]# netstat -anpt | grep 8066
tcp6 0 0 :::8066 :::* LISTEN 1829/java
在三台MySQL数据库中为amoeba授权:
mysql> grant all on *.* to test@'192.168.247.%' identified by '123.com';
#允许test账户以123.com为密码访问数据库的所有库的所有表
mysql> flush privileges;
#刷新权限
客户机上的测试(IP:192.168.247.160)
安装轻量级数据库,登录amoeba服务器可进入主从数据库
[root@server2 ~]# yum -y install mariadb*
[root@server2 ~]# systemctl start mariadb
[root@server2 ~]# mysql -uamoeba -p123456 -h 192.168.247.170 -P8066
#通过amoeba登录数据库 -u用户名 -p密码 -h 访问地址为amoeba服务器 -P amoeba端口号
主从同步验证
在主服务器上新建test数据库和表tt
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> use test
Database changed
mysql> create table tt(name char(10), id int(3) primary key auto_increment);
Query OK, 0 rows affected (0.02 sec)
mysql> desc tt;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| name | char(10) | YES | | NULL | |
| id | int(3) | NO | PRI | NULL | auto_increment |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
在从服务器上都可查看到test和表tt(主从复制的效果)
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| tt |
+----------------+
1 row in set (0.00 sec)
关闭从服务器的从状态:
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
在客户端进行写入操作:
客户端:也无法查看,只能写入主服务器
MySQL [(none)]> insert into test.tt values('a',1);
Query OK, 1 row affected (0.02 sec)
MySQL [(none)]> select * from test.tt;
ERROR 1146 (42S02): Table 'test.tt' doesn't exist
只能在主服务器查看,从服务器无法查看
主服务器:
mysql> select * from tt;
+------+----+
| name | id |
+------+----+
| a | 1 |
+------+----+
1 row in set (0.00 sec)
从服务器:
mysql> select * from test.tt;
ERROR 1146 (42S02): Table 'test.tt' doesn't exist
在从服务器上写入数据
slave1:
mysql> insert into tt values('bb',2);
Query OK, 1 row affected (0.01 sec)
#从服务器上可以查看
mysql> select * from tt;
+------+----+
| name | id |
+------+----+
| bb | 2 |
+------+----+
slave2:
mysql> select * from test.tt;
+------+----+
| name | id |
+------+----+
| aa | 1 |
| cc | 3 |
+------+----+
客户端可以轮流读取到从服务器的数据
而主服务器上不会存储从服务器的数据,依旧是从客户端写入的数据。
mysql> select * from tt;
+------+----+
| name | id |
+------+----+
| a | 1 |
+------+----+
实现了读写分离。
开启主从同步之后,主服务器上写入的数据同步到从服务器,客户端也能读取主服务器数据了,但从服务器上的数据不会到主服务器上。
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from test.tt;
+------+----+
| name | id |
+------+----+
| a | 1 |
+------+----+
1 row in set (0.01 sec)