超详细!MySQL如何实现主从复制和读写分离(原理详解和实操)

   日期:2020-10-30     浏览:86    评论:0    
核心提示:目录一、主从复制与读写分离的意义二、主从数据库实现同步(主从复制)三、主从读写分离四、案例实操一、主从复制与读写分离的意义  企业中的业务通常数据量都比较大,而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求,所以需要配置多台主从数据服务器,以实现主从复制,增加数据可靠性,读写分离,也减少数据库压力和存储引擎带来的表锁定和行锁定问题。二、主从数据库实现同步(主从复制)什么是主从复制?简单来说就是在主服务器上执行的语句,从服务器执行同样的语句,在主服务器上的操作在从服务器产生了同样的结果。

这里写目录标题

  • 一、主从复制与读写分离的意义
  • 二、主从数据库实现同步(主从复制)
  • 三、主从读写分离
  • 四、案例实操

一、主从复制与读写分离的意义

  企业中的业务通常数据量都比较大,而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求,所以需要配置多台主从数据服务器,以实现主从复制,增加数据可靠性,读写分离,也减少数据库压力和存储引擎带来的表锁定和行锁定问题。

二、主从数据库实现同步(主从复制)

什么是主从复制?简单来说就是在主服务器上执行的语句,从服务器执行同样的语句,在主服务器上的操作在从服务器产生了同样的结果。

主从复制的基本过程如下:

  • 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)
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服