• MySQL 主从复制、读写分离


    目录

    一、MySQL 主从复制

    1.1.主从复制架构

    1.2.主从复制原理

    1.3.主从复制主要内容

    1.4.主从复制延迟原因

    二、读写分离

    2.1.读写分离基本原理

    2.2.MySQL 读写分离原理 

    2.3.为什么要读写分离

    2.4. 什么时候要读写分离

    2.5.主从复制与读写分离

    三、主从复制和读写分离实验

    3.1.环境配置

    3.2.搭建mysql主从复制

    3.2.1.搭建时间同步(主服务器:192.168.10.4)

    3.2.2.搭建时间同步(从服务器:192.168.10.5、192.168.10.6)

    3.2.3.配置主服务器(192.168.10.4)

    3.2.4.配置从服务器(192.168.10.5、192.168.10.6)

    3.2.5.验证主从同步

    3.3.搭建Amoeba 实现读写分离(192.168.10.7)

    3.3.1.安装Java环境

    3.3.2.配置amoeba

    3.4.在客户端测试(192.168.10.8)

    四、总结 


    一、MySQL 主从复制

    1.1.主从复制架构

     

     

     1.2.主从复制原理

    主从复制工作过程:

    1. 1、首先client端将数据写入到master节点的数据库中,master节点会通知存储引擎提交事务,
    2. 同时会将数据以(基于行、基于sQL、基于混合)的方式保存在"二进制日志"中。
    3. 2、SLAVE节点会开启I/O线程,用于监听master的二进制日志的更新,一旦发生更新内容,则向master的dunp线程发出同步请求。
    4. 3、master的dump线程在接收到SLAVE的I/O请求后,会读取二进制日志文件中更新的数据,并发送给slave的I/O线程。
    5. 4、SLAVE的I/o线程接收到数据后,会保存在slave节点的中继日志中。
    6. 5、同时slave节点中的sQL线程,会读取中继日志中的数据,更新在本地的mysql数据库中。
    7. 6、最终完成的slave复制master数据,达到主从同步的效果。

     1.3.主从复制主要内容

    主从复制核心部分就是两个日志 三个线程(高版本的mysql以及异步复制、半同步复制、全同步复制三种模式)

    • 二个日志:二进制日志和中继日志。
    • 三个线程:master的dump 和slave的I/O、SQL。
    • 主要原理:master将数据保存在二进制日志中,I/O向dump发出同步请求,dump把数据发送给I/O线程,I/O写入本地的中继日志SQL线程读取本地中继日志数据,同步到自己数据库中,完成同步。

    1.4.主从复制延迟原因

    1. 主服务器的负载过大、被多个睡眠或者僵尸线程占用,导致系统负载过大。
    2. 从库硬件比主库硬件差,导致复制延迟。
    3. 主从复制单线程,如果主库写并发太大,来不及传送到从库,就会导致延迟。
    4. 慢SQL语句过多。
    5. 网络延迟。

    二、读写分离

    2.1.读写分离基本原理

    基本的原理是:

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

    2.2.MySQL 读写分离原理 

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

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

    (1)基于程序代码内部实现

    在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。 优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。 但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。

    (2)基于中间代理层实现

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

    (1)MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。 (2)Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。 (3)Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

    • 由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的。
    • Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。

    2.3.为什么要读写分离

    • 因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
    • 但是数据库的“读”(读10000条数据可能只要5秒钟)。
    • 所以读写分离,解决的是,数据库的写入,影响了查询的效率。

    2.4. 什么时候要读写分离

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

    2.5.主从复制与读写分离

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

    三、主从复制和读写分离实验

    3.1.环境配置

    1. master服务器: 192.168.10.4 mysql
    2. slave1服务器: 192.168.10.5 mysql
    3. slave2服务器: 192.168.10.6 mysql
    4. Amoeba服务器: 192.168.10.7 jdk、Amoeba
    5. 客户端服务器: 192.168.10.8 mysql

    3.2.搭建mysql主从复制

    3.2.1.搭建时间同步(主服务器:192.168.10.4)

    1. 1.#安装时间同步服务器
    2. yum install ntp -y
    3. 2.#修改配置文件
    4. vim /etc/ntp.conf
    5. 插入:
    6. server 127.127.10.0 #设置本地时钟源 (10.0代表的是本机的网段)
    7. fudge 127.127.10.0 stratum 8 #设置时间层级为8 限制在15以内
    8. 3.#开启服务
    9. service ntpd start

    3.2.2.搭建时间同步(从服务器:192.168.10.5、192.168.10.6)

    1. ###########slave2:192.168.10.5################
    2. 1.#安装时间同步服务器、同步服务
    3. yum install ntp -y
    4. yum install ntpdate -y
    5. 2. #开启服务
    6. service ntpd start
    7. 3. #执行同步
    8. /usr/sbin/ntpdate 192.168.10.4
    9. 4.#计划定时任务
    10. crontab -e
    11. */30 * * * * /usr/sbin/ntpdate 192.168.10.4
    12. ###########slave2:192.168.10.6与以上操作相同##############

    3.2.3.配置主服务器(192.168.10.4)

    1. 1. #开启二进制日志
    2. vim /etc/my.cnf
    3. log-bin=master-bin #开启二进制日志
    4. binlog_format=MIXED #二进制日志格式
    5. log-slave-updates=true #开启从服务器同步
    6. 2. #重启服务
    7. systemctl restart mysqld.service
    8. 3. #登入mysql,给从服务器在网段授权
    9. mysql -uroot -p123456
    10. grant replication slave on *.* to 'myslave'@'192.168.10.%' identified by '123456';
    11. #刷新数据库
    12. flush privileges;
    13. #查看主服务器二进制文件
    14. show master status;
    15. 开启二进制日志

    3.2.4.配置从服务器(192.168.10.5、192.168.10.6)

    在服务器mysql中查看:

    1. #########slave2:192.168.10.5##############
    2. 1.#开启二进制日志
    3. vim /etc/my.cnf
    4. server-id = 11 #slave1和slave2的id不能相同,我slave2设置的22
    5. relay-log=relay-log-bin
    6. relay-log-index=slave-relay-bin.index
    7. 2.#重启服务
    8. systemctl restart mysqld.service
    9. 3. #登入mysql,配置同步注意master_log_file和master_log_pos的值要和master查询的一致
    10. mysql -uroot -p123456
    11. change master to master_host='192.168.10.4',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
    12. 4.#启动同步,如果报错,执行restart slave试试
    13. start slave;
    14. show slave status\G;
    15. ##以下两个必须要是YES
    16. #Slave_IO_Running: Yes
    17. #Slave_SQL_Running: Yes
    18. #########slave2:192.168.10.6与以上操作相同######

     3.2.5.验证主从同步

    1. #在主服务器上创建一个库,和一个表
    2. create database shiyan;
    3. use shiyan;
    4. create table info(id int(4) not null,name char(10) not null,age int(4),primary key(id));
    5. insert into info values(1,'yy',22),(2,'zzh',21),(3,'xg',23),(4,'szj',21);
    6. #在从服务器上查看
    7. select * from shiyan.info;

    3.3.搭建Amoeba 实现读写分离(192.168.10.7)

    3.3.1.安装Java环境

    1. ################安装 Java 环境###############
    2. 1.#下载安装包:jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz
    3. cd /opt
    4. 2.#把jdk复制到/usr/local下
    5. cp jdk-6u14-linux-x64.bin /usr/local/
    6. 3.#赋予jdk权限并执行
    7. chmod +x /usr/local/jdk-6u14-linux-x64.bin
    8. cd /usr/local/
    9. ./jdk-6u14-linux-x64.bin #一路回车到底,最后输入yes 自动安装
    10. 4.#jdk改个名字
    11. mv jdk1.6.0_14/ jdk1.6
    12. 5.#配置环境并刷新
    13. vim /etc/profile
    14. 插入:
    15. export JAVA_HOME=/usr/local/jdk1.6
    16. export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
    17. export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
    18. export AMOEBA_HOME=/usr/local/amoeba
    19. export PATH=$PATH:$AMOEBA_HOME/bin
    20. source /etc/profile #刷新配置文件
    21. java -version #查看java版本

    3.3.2.配置amoeba

    1. ############## 安装amoeba ###########
    2. 1.#在/usr/local目录下创建amoeba目录
    3. mkdir /usr/local/amoeba
    4. 2.#切换至opt解压amoeba
    5. cd /opt/
    6. tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
    7. cd /usr/local/ 切换至目录查看
    8. 3.#给目录/usr/local/amoeba赋予执行权限
    9. chmod -R 755 /usr/local/amoeba/
    10. 4.#运行amoeba
    11. /usr/local/amoeba/bin/amoeba
    12. ###########配置 Amoeba读写分离 ###############
    13. 5.#先在Master、Slave1、slave2的mysql上开放权限给 Amoeba 访问
    14. grant all on *.* to root@'192.168.10.%' identified by '123456';
    15. flush privileges;
    16. 6.#备份amoeba配置
    17. cd /usr/local/amoeba/conf/
    18. cp amoeba.xml amoeba.xml.bak
    19. cp dbServers.xml dbServers.xml.bak
    20. 7.#修改amoeba配置
    21. vim amoeba.xml
    22. 30 <property name="user">amoeba</property>
    23. #设置登录用户名
    24. 32<property name="password">123456</property>
    25. #设置密码
    26. 115<property name="defaultPool">master</property>
    27. #设置默认池为master
    28. 118<property name="writePool">master</property>
    29. #设置写池
    30. 119<property name="readPool">slaves</property>
    31. #设置读池
    32. vim dbServers.xml
    33. 23 <!-- <property name="schema">test</property> -->
    34. #23行注释
    35. 26<property name="user">test</property>
    36. #设置登录用户
    37. 28 <!-- mysql password -->
    38. #删除
    39. 29<property name="password">123456</property>
    40. #解决28注释,添加密码
    41. 45<dbServer name="master" parent="abstractServer">
    42. #服务池名
    43. 48<property name="ipAddress">192.168.10.4</property>
    44. #添加地址
    45. 52<dbServer name="slave1" parent="abstractServer">
    46. 55<property name="ipAddress">192.168.10.5</property>
    47. 复制6行 添加另一从节点
    48. 59<dbServer name="slave2" parent="abstractServer">
    49. 62<property name="ipAddress">192.168.10.6</property>
    50. 66<dbServer name="slaves" virtual="true">
    51. #定义池名
    52. 72<property name="poolNames">slave1,slave2</property>
    53. #写上从节点名
    54. 8.#启动amoeba,并测试
    55. amoeba start
    56. netstat -ntap |grep java

    3.4.在客户端测试(192.168.10.8)

    1. 1.#安装mariadb
    2. yum install mariadb mariadb-server.x86_64 -y
    3. 2.#登入并查看数据库
    4. mysql -uamoeba -p123456 -h 192.168.10.7 -P8066
    5. 3.#测试读写分离
    6. #停止slave1和slave2的slave同步功能
    7. stop slave;
    8. #在master、slave1和slave2上插入数据

    ①在客户端插入数据,数据只在master数据库上显示,说明写的操作只在master服务器上执行。

     ​​​

     

     ② 在slave1和slave2插入不同的数据,然后在客户端进行访问数据库,因为是轮询的方式,所以会分别访问slave1和slave2的数据,而不会读到master上的数据,说明读的操作只在从服务器上进行。

    (1)查看master和slave1,slave2的数据。

     (2)在客户端访问数据库

    四、总结 

    1、主从同步复制原理。

    • ①首先client端将数据写入到master节点的数据库中,master节点会通知存储引擎提交事务,
    • 同时会将数据以(基于行、基于sQL、基于混合)的方式保存在"二进制日志"中。
    • ②SLAVE节点会开启I/O线程,用于监听master的二进制日志的更新,一旦发生更新内容,则向master的dunp线程发出同步请求。
    • ③master的dump线程在接收到SLAVE的I/O请求后,会读取二进制日志文件中更新的数据,并发送给slave的I/O线程。
    • ④SLAVE的I/o线程接收到数据后,会保存在slave节点的中继日志中。
    • ⑤同时slave节点中的sQL线程,会读取中继日志中的数据,更新在本地的mysql数据库中。
    • ⑥最终完成的slave复制master数据,达到主从同步的效果。

    2、读写分离你们使用什么方式?

    • ① amoeba中间代理
    • ② mycat 中间代理
    • ③ 公司自研

    3、如何查看主从同步状态是否成功?

    • mysql> show slave status\G  #查看是否都为yes都为yes就说明同步成功
    • Slave_IO_Running=YES
    • Slave_SQL_Running=YES

    4、如果I/0不是yes呢,你如何排查?

    • ①首先排除网络问题,使用ping命令查看从服务是否能与主服务器通信
    • ②再者查看防火墙和核心防护是否关闭
    • ③接着查看从服务器内的slave是否开启
    • ④两个从服务器的 server-id 是否相同导致只能连上一台
    • ⑤master_log_file 和 master_log_pos 的值要是否与Master查询的一致

    5、show slave status能看到哪些信息(比较重要)?

    • ①IO线程的状态信息
    • ②master服务器的IP地址、端口、事务开始位置
    • ③最近一次的报错信息和报错位置等

    6、主从复制慢(延迟)会有哪些可能?怎么解决?

    • ①主服务器的负载过大,被多个睡眠或者僵尸线程占用,导致系统负载过大
    • ②从库硬件比主库差,导致复制延迟
    • ③主从复制单线程,如果主库写并发太大,来不及传送到从库,就会导致延迟。
    • ④慢SQL语句过多
    • ⑤网络延迟

  • 相关阅读:
    【设计模式】 - 结构型模式 - 外观模式
    猿创征文|见过的最傲娇的开源管理者,真的气人,SRS视频流方案
    且看五年开发码农,如何备战仨月硬刚字节面试官,轻松拿offer
    C#创建并调用dll
    流式数据湖Hudi核心概念四:文件布局
    [MySQL]实训七
    一文浅谈Mockito使用
    R语言详解二
    js高级(代理,浅拷贝深拷贝,节流和防抖,闭包.hasOwnProperty)
    基于Java毕业设计智能化管理的仓库管理源码+系统+mysql+lw文档+部署软件
  • 原文地址:https://blog.csdn.net/weixin_64015933/article/details/125482787