MySQL主从复制与读写分离(详细部署案例)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: MySQL主从复制与读写分离(详细部署案例)

一,主从复制了解:


1、为什么需要主从复制?

       在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。


       做数据的热备


       架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。


二,为什么使用主从复制、读写分离

       主从复制、读写分离一般是一起使用的。目的很简单,就是为了提高数据库的并发性能。你想,假设是单机,读写都在一台MySQL上面完成,性能肯定不高。如果有三台MySQL,一台mater只负责写操作,两台salve只负责读操作,性能不就能大大提高了吗?


三,mysql主从复制原理

       mysql的主从复制和MySQL的读写分离两者有着紧密联系,首选要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。


1.mysql支持的复制类型


       基于语句的复制。在主服务器上执行的SQL语句,在从服务器上执行同样的语句。mysql默认采用基于语句的复制,效率比较高。


       基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。


       混合类型复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。


2.复制的工作过程

     

3.mysql读写分离原理

常见的mysql读写分离分为两种:

一.基于程序代码内部实现:

        在代码中根据select,insert进行路由分类,这类方法也是目前生产环境应用最广泛的。优点是性能较好,因为在程序代码中实现,不需要增加额外的设备作为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。

二.基于中间代理层实现

       代理一般位于客户端和服务器之间,代理服务器接到客户端的请求后通过判断后转发到后端数据库,有两个代表性程序。

       1.mysql-proxy。mysql-proxy为MySQL开源项目,通过其自带的lua脚本进行SQL判断,虽然是MySQL官方产品,但是mysql官方不建议将mysql-proxy用到生产环境中。

       2.amoeba(变形虫)。由陈思儒开发,其曾就职于阿里巴巴。该程序用于Java语言进行开发,阿里巴巴将其用于生产环境中。它不支持事务和存储过程。

二,搭建MySQL主从复制

注:在部署环境前请先部署好三台数据库,如有初学者可以查看前面的LAMP部署的mysql部署安装部分。

1.建立时间同步,在主部署NTP,在从服务器上进行时间同步。

[root@localhost ~]# yum -y install ntp
[root@localhost ~]# vim /etc/ntp.conf 
server 127.127.1.0
fudge 127.127.1.0 startum 8
[root@localhost ~]# systemctl restart ntpd
[root@localhost ~]# systemctl enable ntpd
Created symlink from /etc/systemd/system/multi-user.target.wants/ntpd.service to /usr/lib/systemd/system/ntpd.service.

  在每一台服务器上关闭firewalld或者指定端口,服务进行开放

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.

   在节点上进行时间同步

[root@localhost ~]# yum -y install ntpdate
[root@localhost ~]# ntpdate 192.168.2.1
 4 Sep 15:23:06 ntpdate[81050]: adjust time server 192.168.2.1 offset -0.000618 sec

2.配置MySQL master主服务器

       在/etc/my.cnf中修改或者增加下面内容,重启服务。

[root@localhost ~]# vim /etc/my.cnf
server_id = 11        #指定id每一台MySQL服务器禁止相同
log_bin = master-bin        #开启master二进制文件
log-slave-updates = true    #开启slave从服务更新二进制文件
[root@localhost ~]# systemctl restart mysqld

 在登录MySQL程序,给从服务器以授权。

mysql> grant replication slave on *.* to 'myslave'@'192.168.2.%' identified by '123456';
Query OK, 0 rows affected (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 |      410 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3.配置从服务器,两台节点配置相同,注意server_id不要相同。

        在/etc/my.cnf中修改或者增加下面内容,重启MySQL服务器

[root@localhost ~]# vim /etc/my.cnf
server_id = 22
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
[root@localhost ~]# systemctl restart mysqld

    登录MySQL,配置同步,查看  Slave_IO_Running: Yes, Slave_SQL_Running: Yes两项是否为Yes。

[root@localhost ~]# mysql -u root -p
Enter password: 
mysql> change master to master_host='192.168.2.1',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=410;
Query OK, 0 rows affected, 2 warnings (0.06 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: 192.168.2.1
                  Master_User: myslave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 410
               Relay_Log_File: relay-log-bin.000002
                Relay_Log_Pos: 284
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 

4.验证主从复制效果。

        在主,从服务器上登录MySQL, 在主服务器上新建数据库db_test

1. mysql> create database db_test;
2. Query OK, 1 row affected (0.00 sec)

  在主,从服务器上分别查看数据库,显示数据库相同,则主从复制成功。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db_test            |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.01 sec)

三,搭建MySQL读写分离

1.在主服务器上部署amoeba上安装Java环境

注:因为amoeba是基于jbk开发的,所以官方团建使用jdk1.5或1.6版本,高版本不建议使用。

[root@localhost ~]# chmod +x jdk-6u14-linux-x64.bin
[root@localhost ~]# ./jdk-6u14-linux-x64.bin
[root@localhost ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6
[root@localhost ~]# vim /etc/profile
export  JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba/
export PATH=$PATH:$AMOEBA_HOME/bin
[root@localhost ~]# source /etc/profile
[root@localhost ~]# java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)

    java环境已配置成功

       安装并配置Amoeba软件。

[root@localhost ~]# mkdir /usr/local/amoeba
[root@localhost ~]# tar zxf /mnt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@localhost ~]# chmod -R 755 /usr/local/amoeba/
[root@localhost ~]# /usr/local/amoeba/bin/amoeba
amoeba start|stop

配置Amoeba读写分离,两个slave读负载均衡。


  在master,slave1,slave2中开放权限给Amoeba访问

mysql> grant all on *.* to test@'192.168.2.%' identified by '123.com';
Query OK, 0 rows affected (0.00 sec)

  编辑amoeba.xml配置文件,设置客户端登录用户名和密码。

[root@localhost ~]# cd /usr/local/amoeba/
[root@localhost amoeba]# vim conf/amoeba.xml 
                        <property name="authenticator">
                                <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
                                        <property name="user">amoeba</property>
                                        <property name="password">123456</property>
                                        <property name="filter">
                                                <bean class="com.meidusa.amoeba.server.IPAccessController">
                                                        <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
                                                </bean>
                                        </property>
                                </bean>
                        </property>

  指定写入数据库master,指定读取使用slaves组。

 <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
                <property name="ruleLoader">
                        <bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
                                <property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
                                <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
                        </bean>
                </property>
                <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
                <property name="LRUMapSize">1500</property>
                <property name="defaultPool">master</property>
                <property name="writePool">master</property>
                <property name="readPool">slaves</property>
                <property name="needParse">true</property>
        </queryRouter>

   编辑dbServer.xml配置文件,指定刚刚授权的用户和密码,来获取信息。

[root@localhost amoeba]# vim conf/dbServers.xml 
<!-- mysql user -->
                        <property name="user">test</property>
                        <property name="password">123.com</property>

   指定mysql数据库的地址,和slave组的服务器地址。

     <dbServer name="master"  parent="abstractServer">
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.2.1</property>
                </factoryConfig>
        </dbServer>
        <dbServer name="slave1"  parent="abstractServer">
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.2.2</property>
                </factoryConfig>
        </dbServer>
        <dbServer name="slave2"  parent="abstractServer">
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.2.3</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>

配置无误后,可以启动amoeba软件,其默认端口为tcp 8066测试。

[root@localhost amoeba]# bin/amoeba start&
[1] 33254
[root@localhost amoeba]# netstat -napt | grep java
tcp6       0      0 127.0.0.1:37645         :::*                    LISTEN      33254/java          
tcp6       0      0 :::8066                 :::*                    LISTEN      33254/java          
tcp6       0      0 192.168.2.1:52608       192.168.2.3:3306        ESTABLISHED 33254/java          
tcp6       0      0 192.168.2.1:56320       192.168.2.1:3306        ESTABLISHED 33254/java          
tcp6       0      0 192.168.2.1:45090       192.168.2.2:3306        ESTABLISHED 33254/java     

  测试。

       在client主机上安装mariadb数据库

yum -y install mariadb
[root@localhost ~]# mysql -u amoeba -p123456 -h 192.168.2.1 -P8066
mysql> use db_test;
Database changed
mysql> create table name_table (id int(10),name varchar(10),address varchar(20));
Query OK, 0 rows affected (0.09 sec)

 分别在两台从服务器上,关闭slave复制

1. mysql> stop slave;
2. Query OK, 0 rows affected (0.02 sec)

从服务器上同步了表,手动插入其他内容。

salve1:
mysql> use db_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> insert into name_table values ('2','li','244');
Query OK, 1 row affected (0.01 sec)
salve2:
mysql> use db_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql> insert into name_table values ('1','zhang','233');
Query OK, 1 row affected (0.02 sec)

在client主机上第一次和第二次查看结果:

mysql> select * from name_table;
+------+------+---------+
| id   | name | address |
+------+------+---------+
|    2 | li   | 244     |
+------+------+---------+
1 row in set (0.01 sec)
mysql> select * from name_table;
+------+-------+---------+
| id   | name  | address |
+------+-------+---------+
|    1 | zhang | 233     |
+------+-------+---------+
1 row in set (0.00 sec)

 测试写入操作,在client主机上插入一条语句:

1. mysql> insert into name_table values('3','wang','255');
2. Query OK, 1 row affected (0.05 sec)

但是在cilent上查询不到,只有master上才能查看到这条语句内容,说明写操作在master服务器上。

mysql> select * from name_table;
+------+------+---------+
| id   | name | address |
+------+------+---------+
|    3 | wang | 255     |
+------+------+---------+
1 row in set (0.00 sec)

由此验证,以及实现了MySQL读写分离,目前所有的写操作都全部在master(主服务器上),用来避免数据的不同步;所有读数据都分摊给了slave(从服务器) ,用来分担数据库压力。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
4月前
|
存储 关系型数据库 MySQL
MySQL Docker 容器化部署全指南
MySQL是一款开源关系型数据库,广泛用于Web及企业应用。Docker容器化部署可解决环境不一致、依赖冲突问题,实现高效、隔离、轻量的MySQL服务运行,支持数据持久化与快速迁移,适用于开发、测试及生产环境。
750 4
|
5月前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
|
6月前
|
关系型数据库 MySQL 数据库
为什么 MySQL 不推荐用 Docker 部署?
本文探讨了MySQL是否适合容器化的问题,分析了Docker容器在数据安全、性能瓶颈、状态管理及资源隔离等方面的挑战,并指出目前主流分布式数据库如TDSQL和OceanBase仍倾向于部署在物理机或KVM上。
330 0
|
9月前
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
472 41
|
9月前
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
598 17
|
9月前
|
Java 关系型数据库 MySQL
在Linux操作系统上设置JDK、Tomcat、MySQL以及J2EE后端接口的部署步骤
让我们总结一下,给你的Linux操作系统装备上最强的军队,需要先后装备好JDK的弓箭,布置好Tomcat的阵地,再把MySQL的物资原料准备好,最后部署好J2EE攻城车,那就准备好进军吧,你的Linux军团,无人可挡!
213 18
|
9月前
|
开发框架 关系型数据库 Java
Linux操作系统中JDK、Tomcat、MySQL的完整安装流程以及J2EE后端接口的部署
然后Tomcat会自动将其解压成一个名为ROOT的文件夹。重启Tomcat,让新“植物”适应新环境。访问http://localhost:8080/yourproject看到你的项目页面,说明“植物”种植成功。
280 10
|
10月前
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
12月前
|
关系型数据库 MySQL 数据库
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
727 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
|
12月前
|
SQL 关系型数据库 MySQL
数据库数据恢复——MySQL简介和数据恢复案例
MySQL数据库数据恢复环境&故障: 本地服务器,安装的windows server操作系统。 操作系统上部署MySQL单实例,引擎类型为innodb,表空间类型为独立表空间。该MySQL数据库没有备份,未开启binlog。 人为误操作,在用Delete命令删除数据时未添加where子句进行筛选导致全表数据被删除,删除后未对该表进行任何操作。

推荐镜像

更多