MySQL数据库 主从复制与读写分离

读写分离是什么

读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

为什么要进行读写分离

因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。

但是数据库的“读”(读10000条数据可能只要5秒钟)。

所以读写分离,解决的是,数据库的写入,影响了查询的效率。

何时要进行读写分离

数据库不一定要读写分离,但如果程序使用数据库较多,而更新少,查询多的情况下会考虑使用。利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。

主从复制与读写分离

在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。

MySQL支持的复制类型

STATEMENT:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。

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

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

主从复制的过程

主(Master):dump线程,二进制日志

从(Slave):I/O线程,SQL线程,中继日志

1、主中数据进行更新,并写入二进制日志。

2、从开启IO线程,并勘测主的二进制日志是否有更新,请求读取二进制日志。

3、主为从的IO线程开启dump线程,向从发送二进制日志

4、从保存二进制日志到中继日志中

5、从开启SQL线程读取中继日志,解析成sql语句,实现主从同步
 

数据库主从数据不一致解决方案

一:忽略错误后,继续同步 该方法适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况

二:重新做主从,完全同步 该方法适用于主从库数据相差较大,或者要求数据完全统一的情况

MYSQL读写分离原理

读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性操作,而从数据库处理select查询。数据库复制被用来把主数据库上事务性操作导致的变更同步到集群中的从数据库。

目前较为常见的MysQL读写分离分为以下两种:

基于程序代码内部实现

在代码中根据select、insert进行路由分类,这类方法也是目前生产环境应用最广泛的。

优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。

但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。

基于中间代理层实现

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

        MySQL-Proxy

MySQL-Proxy为MysQL开源项目,通过其自带的1ua脚本进行sQL判断。

        Atlas

是由奇虎360的Web平台部基础架构团队开发维护的一个基于MysQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用atlas运行的mysql业务,每天承载的读写请求数达几干保条。支持事物以及存储过程。

        Amoeba

由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。

        Mycat

是一款流行的基于Java语言编写的数据库中间件,是一个实现了MySq1协议的服务器,其核心功能是分库分表。配合数据库的主从模式还可以实现读写分离 由于使用MysQLProxy需要写大量的ua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MysQLProxy 内置变量和MySQL Protocol的人来说是非常困难的。

MySQL主从复制延迟的原因

1、master服务器高并发,形成大量事务

2、网络延迟

3、主从硬件设备导致:cpu主频、内存io、硬盘io

4、本来就不是同步复制、而是异步复制

从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作。

从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o方面性。

从库使用SSD磁盘

网络优化,避免跨机房实现同步

主从复制配置

#准备Master 服务器:20.0.0.30		mysql5.7         
Slave1 服务器:20.0.0.40		mysql5.7         
Slave2 服务器:20.0.0.120		mysql5.7#关闭防火墙及安全机制systemctl stop firewalld
systemctl disable firewalld
setenforce 0

Mysql主从服务器时间同步

#主服务器设置(20.0.0.30)
#安装ntp
yum install ntp -yvim /etc/ntp.conf
--末尾添加--
server 127.0.0.0							#设置本地是时钟源,注意修改网段  127.0.0.0
fudge 127.0.0.0 stratum 8				#设置时间层级为8(限制在15内)service ntpd start
或
systemctl start ntpd#从服务器设置(20.0.0.40 、20.0.0.120)yum install ntp ntpdate -yservice ntpd start
或
systemctl start ntpd/usr/sbin/ntpdate 20.0.0.30				#进行时间同步   20.0.0.30#可添加定时任务,实现自动同步
crontab -e
*/30 * * * * /usr/sbin/ntpdate 20.0.0.30

主服务器的mysql配置

vim /etc/my.cnf                          #MySQL的配置文件
server-id = 1
log-bin=master-bin					     #添加,主服务器开启二进制日志
binlog_format = MIXED                    #设置日式格式为混合模式
log-slave-updates=true					 #添加,允许slave从master复制数据时可以写入到自己的二进制日志#重启MySQL服务
systemctl restart mysqldmysql -u root -p123456
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'20.0.0.%' IDENTIFIED BY '123456';			#给从服务器的网段授权#刷新
FLUSH PRIVILEGES;show master status;
//如显示以下
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |    447   |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)#File 列显示日志名,Position 列显示偏移量

从服务器的mysql配置

vim /etc/my.cnf
server-id = 2    [server-id = 3]			#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin						#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index		#添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录
relay_log_recovery = 1                      
#relay_log_recovery = 1 选配项:当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。systemctl restart mysqldmysql -u root -123456
CHANGE master to master_host='20.0.0.30',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=447;					
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致start slave;						#启动同步,如有报错执行 reset slave;
show slave status\G					#查看 Slave 状态
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes				#负责与主机的io通信
Slave_SQL_Running: Yes				#负责自己的slave mysql进程

查看从配置不正常的情况

#一般 Slave_IO_Running: No 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭

验证主从复制效果

#当主数据库进行增添或修改时,从数据库会同步记录主的数据#在主数据库增添数据(20.0.0.30)mysql> create database xxxx;
Query OK, 1 row affected (0.00 sec)#此时查看配置的两台从服务器数据库#20.0.0.40
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| bbs                |
| mysql              |
| performance_schema |
| sys                |
| test               |
| test1              |
| wordpress          |
| xxxx               |
+--------------------+#20.0.0.120
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test1              |
| test2              |
| xxxx               |
+--------------------+

读写分离配置

基于上面的主从复制

#准备Master 服务器:20.0.0.30		mysql5.7         
Slave1 服务器:20.0.0.40		mysql5.7         
Slave2 服务器:20.0.0.120		mysql5.7Amoeba 服务器:20.0.0.41		jdk1.6、Amoeba   
客户端 服务器:20.0.0.41		mysql#关闭防火墙及安全机制systemctl stop firewalld
systemctl disable firewalld
setenforce 0

做读写分离实验之前必须有一 主 两从 环境

#Amoeba服务器配置##安装 Java 环境##因为 Amoeba 是基于 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。cd /opt/
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64
./jdk-6u14-linux-x64.bin//按yes,按enter#重命名目录
mv jdk1.6.0_14/ /usr/local/jdk1.6#修改系统配置文件
vim /etc/profileexport JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$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
#执行
source /etc/profile
#查看当前java环境
java -version#安装 Amoeba软件mkdir /usr/local/amoebatar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/chmod -R 755 /usr/local/amoeba//usr/local/amoeba/bin/amoeba#如显示amoeba start|stop说明安装成功#配置 Amoeba读写分离,两个 Slave 读负载均衡###先在Master(20.0.0.30)、Slave1(20.0.0.40)、Slave2(20.0.0.120) 的mysql上开放权限给 Amoeba 访问grant all on *.* to test@'20.0.0.%' identified by '123456';#再回到amoeba服务器配置amoeba服务:cd /usr/local/amoeba/conf/#备份
cp amoeba.xml amoeba.xml.bakvim amoeba.xml									#修改amoeba配置文件
--30行--
<property name="user">amoeba</property>--32行-- 
<property name="password">123456</property>--115行--
<property name="defaultPool">master</property>--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>#备份
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml								#修改数据库配置文件--23行--注释掉  作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->--26--修改
<property name="user">test</property>--28-30--去掉注释
<property name="password">123456</property>--45--修改,设置主服务器的名Master
<dbServer name="master"  parent="abstractServer">--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.10.15</property>--52--修改,设置从服务器的名slave1
<dbServer name="slave1"  parent="abstractServer">--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.10.14</property>--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.10.16</property>--65行--修改
<dbServer name="slaves" virtual="true">--71行--修改
<property name="poolNames">slave1,slave2</property>/usr/local/amoeba/bin/amoeba start&					#启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java							#查看8066端口是否开启,默认端口为TCP 8066

测试读写分离

yum install -y mariadb-server mariadb
systemctl start mariadb.service
———————————————————— 可选,也可以用MySQL在客户端服务器上测试(20.0.0.41):mysql -u amoeba -p123456 -h 20.0.0.41 -P8066#通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器#在客户端(20.0.0.41)更新mysql> create database amoeba;
Query OK, 1 row affected (0.04 sec)#查看主(20.0.0.30)、从1(20.0.0.40)、从2(20.0.0.120)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| amoeba             |
| bbs                |
| mysql              |
| performance_schema |
| sys                |
| test               |
| test1              |
| wordpress          |
+--------------------+
9 rows in set (0.01 sec)#当关闭两台从服务器(20.0.0.40、20.0.0.120)stop slave;		#关闭同步use amoeba;
create table test(id int,name varchar(20),text varchar(30));//在slave1上:insert into test values('1','zhangsan','this_is_slave1');//在slave2上:
insert into test values('2','lisi','this_is_slave2');//在主服务器上:
insert into test values('3','wangwu','this_is_master');//在客户端服务器上:
use amoeba;
select * from test;		//客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
mysql> select * from test;
+------+----------+----------------+
| id   | name     | text           |
+------+----------+----------------+
|    1 | zhangsan | this_is_slave1 |
+------+----------+----------------+再次执行select * from test;	mysql> select * from test;
+------+------+----------------+
| id   | name | text           |
+------+------+----------------+
|    2 | lisi | this_is_slave2 |
+------+------+----------------+#在客户端(20.0.0.41) 插入新条目
insert into test values('4','qianqi','this_is_client');		#只有主服务器(20.0.0.30)上有此数据
mysql> select * from test;
+------+--------+----------------+
| id   | name   | text           |
+------+--------+----------------+
|    3 | wangwu | this_is_master |
|    4 | qianqi | this_is_client |
+------+--------+----------------+//在两个从服务器(20.0.0.40、20.0.0.120)上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;
#(20.0.0.40)
mysql> select * from test;
+------+----------+----------------+
| id   | name     | text           |
+------+----------+----------------+
|    1 | zhangsan | this_is_slave1 |
|    3 | wangwu   | this_is_master |
|    4 | qianqi   | this_is_client |
+------+----------+----------------+#(20.0.0.120)
mysql> select * from test;
+------+----------+----------------+
| id   | name     | text           |
+------+----------+----------------+
|    2 | lisi     | this_is_slave2 |
|    3 | wangwu   | this_is_master |
|    4 | qianqi   | this_is_client |
+------+----------+----------------+

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Matlab实现多个图像融合案例(附上源码+数据集)

图像融合是将多幅图像合成为一幅图像的过程&#xff0c;旨在融合不同图像的信息以获得更多的细节和更丰富的视觉效果。在本文中&#xff0c;我们将介绍如何使用Matlab实现图像融合。 文章目录 简单案例源码数据集下载 简单案例 首先&#xff0c;我们需要了解图像融合的两种主…

【STM32】IIC的初步使用

IIC简介 物理层 连接多个devices 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中&#xff0c;可连接多个 I2C 通讯设备&#xff0c;支持多个通讯主机及多个通讯从机。 两根线 一个 I2C 总线只使用两条总线线路&#xff0c;一条双向串行数…

掌握 Android 自动化测试框架 UiAutomator UiAutomator2

掌握 Android 自动化测试框架 UiAutomator & UiAutomator2 一、UiAutomator 简介二、UiAutomator2 的诞生三、UiAutomator2 的应用实践总结你是否曾经在进行 Android 应用开发时,对于如何进行全面、有效的自动化测试感到困惑?你是否想要更高效地进行 UI 测试,而不是一遍…

Android Studio 汉化

一、汉化&#xff1a; 查看版本号&#xff0c;查看Android Studio版本&#xff0c;根据版本下载对应的汉化包。例如我的是223。 下载汉化包&#xff1a; 中文语言包下载地址 找到对应的版本 回到Android Studio 1、进入设置 2、从磁盘安装插件 3、选择下载好的包点击OK 4、…

介绍OpenCV

OpenCV是一个开源计算机视觉库&#xff0c;可用于各种任务&#xff0c;如物体识别、人脸识别、运动跟踪、图像处理和视频处理等。它最初由英特尔公司开发&#xff0c;目前由跨学科开发人员社区维护和支持。OpenCV可以在多个平台上运行&#xff0c;包括Windows、Linux、Android和…

AJAX学习笔记6 JQuery对AJAX进行封装

AJAX学习笔记5同步与异步理解_biubiubiu0706的博客-CSDN博客 AJAX请求相关的代码都是类似的&#xff0c;有很多重复的代码&#xff0c;这些重复的代码能不能不写&#xff0c;能不能封装一个工具类。要发送ajax请求的话&#xff0c;就直接调用这个工具类中的相关函数即可。 用J…

深圳-海岸城购物中心数据分析

做数据分析的时候&#xff0c;如果要对商场进行分析&#xff0c;可以从这些数据纬度进行分析&#xff0c;如下图所示&#xff1a; 截图来源于数位观察&#xff1a;https://www.swguancha.com/

如何炒伦敦金

由于疫情的影响&#xff0c;目前世界上多个国家降低存款利率&#xff0c;以推动经济发展&#xff0c;由此也引发了比较严重的通胀问题&#xff0c;尤其是在俄乌冲突之后&#xff0c;国际油价不断上涨&#xff0c;加大了这种通货膨胀的影响。进行伦敦金投资是一种规避通胀的好方…

Python爬虫-某网酒店数据

前言 本文是该专栏的第5篇,后面会持续分享python爬虫案例干货,记得关注。 本文以某网的酒店数据为例,实现根据目标城市获取酒店数据。具体思路和方法跟着笔者直接往下看正文详细内容。(附带完整代码) 正文 地址:aHR0cHM6Ly93d3cuYnRoaG90ZWxzLmNvbS9saXN0L3NoYW5naGFp …

Python 中下划线详解(_、_xx、xx_、__xx、__xx__)

文章目录 1 概述2 演示2.1 _&#xff1a;不重要的变量2.2 _xx&#xff1a;声明私有&#xff0c;仅内部调用2.3 xx_&#xff1a;区分关键字2.4 __xx&#xff1a;声明私有&#xff0c;仅当前类中可用2.5 __xx__&#xff1a;内置函数 1 概述 2 演示 2.1 _&#xff1a;不重要的变…

jmeter setUp Thread Group

SetUp Thread Group 是一种特殊类型的线程组&#xff0c;它用于在主测试计划执行之前执行一些初始化任务。 SetUp Thread Group 通常用于以下几种情况&#xff1a; 用户登录&#xff1a;在模拟用户执行实际测试之前&#xff0c;模拟用户登录到系统以获取访问权限。 创建会话&a…

Spring 自带工具——URI 工具UriComponentsBuilder

UriComponentsBuilder 是 Spring Framework 提供的一个实用工具类&#xff0c;用于构建 URI&#xff08;Uniform Resource Identifier&#xff09;。URI 是用于标识和定位资源的字符串&#xff0c;例如 URL&#xff08;Uniform Resource Locator&#xff09;就是一种特殊的 URI…

OpenWrt编译自己的应用程序

编译OpenWrt的应用程序可以参考OpenWrt内部其他应用程序的例程&#xff0c;来编写成自己的应用程序 一、OpenWrt源代码获取与编译 1.1、搭建环境 下载OpenWrt的官方源码&#xff1a; git clone https://github.com/openwrt/openwrt.git1.2、安装编译依赖项 sudo apt update…

Linux下的系统编程——进程(八)

前言&#xff1a; 程序是指储存在外部存储(如硬盘)的一个可执行文件, 而进程是指处于执行期间的程序, 进程包括 代码段(text section) 和 数据段(data section), 除了代码段和数据段外, 进程一般还包含打开的文件, 要处理的信号和CPU上下文等等.下面让我们开始对Linux进程的学…

使用【宝塔+docker】在云服务器上部署基于SpringBoot 和 Dubbo RPC 的项目:踩坑记录

待部署的项目包括&#xff1a;前端front&#xff0c;服务提供者backend&#xff0c;服务消费者gateway&#xff0c;注册中心nacos 服务器信息&#xff1a;腾讯云入门级服务器2核2G&#xff08;后续有对服务器进行升级&#xff09; 部署工具&#xff1a;前端使用宝塔部署&#x…

IDEA中debug调试模拟时显示不全(不显示null)的解决

IDEA中debug调试模拟时显示不全&#xff08;不显示null&#xff09;的解决 1、在IDEA中找到File&#xff08;文件&#xff09;->Settings&#xff08;设置&#xff09; 2、依次找到以下内容进行设置&#xff08;原版、汉化版&#xff09;&#xff1a; 打开Build, Executio…

服务器基本故障排查方法

1、加电类故障 定义 从上电(或复位)到自检完成这一段过程中电脑所发生的故障。可能的故障现象 1、 主机不能加电(如&#xff1a;电源风扇不转或转一下即停等)、有时不能加电、开机掉闸、机箱金属部分带电等; 2、 开机无显&#xff0c;开机报警; 3、 自检报错或死机、自检过程中…

【笔记】Spring Boot 历史官方文档学习(持续更新)

文章目录 前言1 Spring Boot 1.01.1 Spring Boot 1.0 特性 —— 专属的Spring事件1.1.1 背景1.1.2 原文解读 1.2 Spring Boot 1.0 特性 —— 外部化配置1.2.1 背景1.2.2 原文解读 1.3 前言 Spring Boot 2014正式发布1.0版本&#xff0c;距今已经快10年了。看历史官方文档了解重…

2.2 Vector<T> 动态数组(模板语法)

C数据结构与算法 目录 本文前驱课程 1 C自学精简教程 目录(必读) 2 动态数组 Vector&#xff08;难度1&#xff09; 其中&#xff0c;2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。 本文目标 1 学会写基本的C类模板语法&#xff1b; 2 为以后熟练使用 S…

【STL】模拟实现map和set {map和set的封装;核心结构;插入和查找;红黑树的迭代器;STL中的红黑树结构}

模拟实现map和set map和set是红黑树的两种不同封装形式&#xff0c;底层使用同一颗泛型结构的红黑树&#xff0c;只是存储类型不同。set是红黑树的K模型&#xff0c;存储key&#xff1b;map是红黑树的KV模型&#xff0c;存储pair<key,value>。 下面的代码和讲解着重体现…