• 【MySql】mysql之主从复制和读写分离搭建


    MySql】mysql之主从复制和读写分离搭建

    1主从复制

    1.1MySql支持从复制类型

    基于语句的复制(statement)

    • 在煮服务器上执行的sql语句,在从服务器执行同样的语句。
    • mysql默认采用的方式。效率高。

    基于行的复制

    • 把改变的内容复制过去。

    基于混合类型复制

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

    1.2主从复制的原理

    两日志

    二进制文件: 记录数据库变动的信息(语句、变动记录)
    中继日志文件: 用于临时存放二进制文件内容。
    三线程

    dump线程: ①监听I/O线程请求。②将二进制日志文件更新的数据发送给slave的I/O线程。
    I/O线程: ①监听master主机的二进制文件。②向master的dump线程发出同步请求
    SQL线程: 读取中继日志中的文件,更新到本机的数据库。

    1、首先client端(tomcat)将数据写入到master节点的数据库中,master节点会通知存储引擎提交事务,同时会将数据以(基于行、基于SQL、基于混合)的方式保存在二进制文件中。
    
    2、slave节点会开启 I/O 线程,用于监听master的二进制日志的更新,一旦发生更新内容,则向master的dump线程发出同步请求。
    
    3、master的dump线程在接收到salve的I/O请求后,会读取二进制日志文件中更新的数据,并发送给slave的I/O线程。
    
    4、slave的I/O线程接收到数据后,会保存在slave节点的中继日志中。
    
    5、同时,slave节点中的SQL线程,会读取中继日志中的数据,更新在本地的mysql数据库中
    
    6、最终,完成slave---> 复制master数据,达到主从同步的效果。
    
    中继日志通常会位于OS缓存中,所以中继日志的开销很小。
    复制过程有一个很重要的限制,即复制在slave上时串行化的,也就是说,master上的并行更新操作不能再slave上并行操作。
    

    1.3主从复制的工作过程

    (1)在每个事务更新数据完成之前,Master在二进制日志(Binary log)记录这些改变。写入二进制日志完成后,Master通知存储引擎提交事务。

    (2)Slave将Master的复制到其中继日志(Relay log)。首先slave开始一个工作线程(I/O),I/O线程在Master上打开一个普通的连接,然开始Binlog dump process。Binlog dump process从Master的二进制日志中读取事件,如果以及跟上Master,它会睡眠并等待Master产生新的事件,I/O线程将这些事件写入中继日志。

    (3)SQL slave thread(SQL从线程)处理该线程的最后一步,SQL线程从中继日志中读取事件,并重放其中的事件而更新slave数据,使其与master的数据保持一致,只要该线程与I/O线程保持一致,中继日志通常会位于OS缓存中,所以中继日志的开销小。
    复制过程有一个和重要的限制,即复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

    img

    img

    从库生成两个线程,一个I/O线程,一个SQL线程;

    i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;

    主库会唤醒 log dump 线程,用来给从库 i/o线程传binlog;

    SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一 致;

    注:

    ●中继日志通常会位于 OS 缓存中,所以中继日志的开销很小。

    ●复制过程有一个很重要的限制,即复制在 Slave上是串行化的,也就是说 Master上的并行更新操作不能在 Slave上并行操作

    1.3.1 主从复制相关线程

    主节点:

    dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events

    从节点:

    I/O Thread:向Master请求二进制日志事件,并保存于中继日志中

    SQL Thread:从中继日志中读取日志事件,在本地完成重放

    1.3.2 跟复制功能相关的文件

    master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等

    relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系

    mariadb-relay-bin.00000#: 中继日志,保存从主节点复制过来的二进制日志,本质就是二进制日志

    1.3.3 MySQL 主从复制延迟

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

    网络延迟

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

    本来就不是同步复制、而是异步复制 从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作。 从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o面性。 从库使用SSD磁盘 网络优化,避免跨机房实现同步

    1.4mysql主从复制方式

    异步复制(Async Replication)
    主库将更新写入Binlog日志文件后,不需要等待数据更新是否已经复制到从库中,就可以继续处理更多的请求。Master将事件写入binlog,但并不知道Slave是否或何时已经接收且已处理。在异步复制的机制的情况下,如果Master宕机,事务在Master上已提交,但很可能这些事务没有传到任何的Slave上。假设有Master->Salve故障转移的机制,此时Slave也可能会丢失事务。MySQL复制默认是异步复制,异步复制提供了最佳性能。

    同步复制(Sync Replication)
    主库将更新写入Binlog日志文件后,需要等待数据更新已经复制到从库中,并且已经在从库执行成功,然后才能返回继续处理其它的请求。同步复制提供了最佳安全性,保证数据安全,数据不会丢失,但对性能有一定的影响。

    半同步复制(Semi-Sync Replication)
    写入一条数据请求到master,从服务器只要有一台接收到写入自己的中继日志,会给客户端返回一条接收成功的信息。
    主库提交更新写入二进制日志文件后,等待数据更新写入了从服务器中继日志中,然后才能再继续处理其它请求。该功能确保至少有1个从库接收完主库传递过来的binlog内容已经写入到自己的relay log里面了,才会通知主库上面的等待线程,该操作完毕。**
    半同步复制,是最佳安全性与最佳性能之间的一个折中。
    MySQL 5.5版本之后引入了半同步复制功能,主从服务器必须安装半同步复制插件,才能开启该复制功能。如果等待超时,超过rpl_semi_sync_master_timeout参数设置时间(默认值为10000,表示10秒),则关闭半同步复制,并自动转换为异步复制模式。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为增强半同步复制。
    ACK (Acknowledge character)即是确认字符。

    增强半同步复制(lossless Semi-Sync Replication、无损复制)
    增强半同步是在MySQL 5.7引入,其实半同步可以看成是一个过渡功能,因为默认的配置就是增强半同步,所以,大家一般说的半同步复制其实就是增强的半同步复制,也就是无损复制。
    增强半同步和半同步不同的是,等待ACK时间不同
    rpl_semi_sync_master_wait_point = AFTER_SYNC(默认)
    半同步的问题是因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户看到的是老数据。
    增强半同步将等待ACK的点放在提交Commit之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。

    2 MySQL 读写分离

    2.1mysql读写分离原理

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

    img

    2.2常见的 MySQL 读写分离分为两种

    (1)基于程序代码内部实现
    在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
    优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
    但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。
    (2)基于中间代理层实现
    代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序:

    MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
    Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
    Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
    由于使用MySQL Proxy需要写大量的Lua脚本,这些Lua脚本不是现成的,而需要自己编写,这对于并不熟悉MySQL Proxy内置变量和MySQL Protocol的人来说是非常困难的。
    Amoeba是一个非常容易使用,可移植性非常强的软件,因此它在生产环境中被广泛用于数据库的代理层。

    3主从复制实验

    3.1Mysql主从服务器时间同步

    环境配置

    systemctl stop firewalld
    systemctl disable firewalld
    setenforce 0

    3.1.1主服务时间同步

    yum -y install ntp 下载更新时间同步工具

    ntpdate ntp1.aliyun.com 同步阿里云时间

    systemctl start ntpd; 开启同步服务

    或者设置本地时间源

    vim /etc/ntp.conf 在末尾添加

    server 127.127.0.0 #设置本地时钟源(网段与本机相同)
    fudge 127.127.0.0 stratum 8 #设置时间层级为8(限制在15以为) 层级环

    设置本机的时间层级为8级,0级表示层级为0级,是向其他服务器时间同步源的意思,不要设置为0级

    systemctl start ntpd; 开启同步服务

    img

    img

    img

    3.1.2 从服务器时间同步

    yum -y install ntp 下载更新时间同步工具

    ntpdate ntp1.aliyun.com 同步阿里云时间

    systemctl start ntpd; 开启同步服务

    或者同步指定的服务器

    ntpdate 192.168.100.20 #指定同步NTP服务器

    systemctl start ntpd; 开启同步服务

    设置周期性计划同步主服务日志

    3.2主服务器的mysql配置

    vim /etc/my.cnf
    
    [mysqld] 在这里插入
    
    server-id = 1
    log-bin=master-bin                            #添加,主服务器开启二进制日志
    log-slave-updates=true                        #添加,允许从服务器更新二进制日志
    
    systemctl restart mysqld  重启
    
    mysql -uroot -p #登录数据库
    
    授权,允许192.18.100.0网段主机使用myslave账号及密码登录并使用数据库
    
    grant replication slave on *.* to 'myslave'@'192.168.100.%' identified by '123456';
    
    flush privileges; #将用户和权限配置保存在内存中
    
    show master status;  #查看master服务器当前正在执行的二进制日志位置,和列偏移
    
    

    img

    img

    3.3 slave从服务器的配置

    vim /etc/my.cnf
    server-id=2   #修改,id不能与master相同,两个slave也不能相同
    relay-log=relay-log-bin   #添加,开启中继日志,从服务器上同步master服务器日志文件到本地
    relay-log-index=slave-relay-bin.index  #添加,定义中继日志文件的位置和名称
    relay_log_recovery=1  
    #当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启
    
    systemctl restart mysqld  #启动mysqld服务器
    mysql -uroot -p123456 #登录数据库
    
    change master to master_host='192.168.100.20',
    
    master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
     #配置同步,注意 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进程
    
    

    img

    img

    3.4测试主从复制

    1.在主服务器上创建一个库
    create database test_1;
    
    2.在从服务器上查看
    show databases;
    

    img

    4读写分离实验

    做读写分离必须要做好主从复制的的环境,因为读写分离是基于主从复制的基础上去执行的架构。

    4.1前期环境及数据流向图

    主机ip
    主服务器192.168.100.20
    从服务器1192.168.100.30
    从服务器2192.168.100.40
    Amoeba192.168.100.50
    客户端192.168.100.10

    4.2Amoeba服务搭建

    systemctl stop firewalld
    systemctl disable firewalld
    setenforce 0

    4.3JDK环境安装

    ################安装 Java 环境###############
    1.#下载安装包:jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz 
    cd /opt
    
    2.#把jdk复制到/usr/local下
    cp jdk-6u14-linux-x64.bin /usr/local/
    
    3.#赋予jdk权限并执行
    chmod +x /usr/local/jdk-6u14-linux-x64.bin
    cd /usr/local/
    ./jdk-6u14-linux-x64.bin  #一路回车到底,最后输入yes 自动安装
    
    4.#jdk改个名字
    mv jdk1.6.0_14/ jdk1.6
    
    5.#配置环境并刷新
    vim /etc/profile
    export 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 -version
    #查看版本
    

    img

    img

    img

    4.4配置amoeba

    一、安装amoeba 
    
    1.#在/usr/local目录下创建amoeba目录
    mkdir /usr/local/amoeba
    
    2.#切换至opt解压amoeba
    cd /opt/
    tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
    
    cd /usr/local/ 切换至目录查看
    
    
    3.#给目录/usr/local/amoeba赋予执行权限
    chmod -R 755 /usr/local/amoeba/
    
    4.#运行amoeba
    /usr/local/amoeba/bin/amoeba
    
    
     二、Amoeba读写分离 
    5.#先在Master、Slave1mysql上开放权限给 Amoeba 访问
    grant all on *.* to amoeba@'20.0.0.%' identified by '123456';
    flush privileges;
    
    
    6.#备份amoeba配置
    cd /usr/local/amoeba/conf/
    cp amoeba.xml amoeba.xml.bak
    cp dbServers.xml dbServers.xml.bak
    
    7.#修改amoeba配置
    vim amoeba.xml
    30 amoeba
    #设置登录用户名
    32123456
    #设置密码
    
    115master
    #设置默认池为master
    118master
    #设置写池
    119slaves
    #设置读池
    
    8.vim dbServers.xml 
    23 
    #23行注释
    26amoeba
    #设置登录用户
    28 
    #删除
    29123456
    #解决28注释,添加密码
    
    45
    #服务池名
    4820.0.0.30
    #添加地址
    
    52
    5520.0.0.31
    复制6行 添加另一从节点
    59
    6220.0.0.32
    
    66
    #定义池名
    72slave1,slave2
    #写上从节点名
    
    8.#启动amoeba,并测试
    amoeba start &
    netstat -ntap |grep java
    

    img

    img

    img

    image-20220816154256279

    4.5测试读写分离

    在客户端服务器上进行测试:
    使用yum快速安装MySQL虚拟客户端

    yum install -y mariadb mariadb-server
    systemctl start mariadb
    mysql -u amoeba -p123456 -h 20.0.0.18 -P8
    

    img

    image-20220816191318126

    在主服务器上

    use test_1;

    create table test (id int(10),name varchar(10),age int);

    img

    两台从服务器上

    stop slave; #关闭同步use test_1;

    在slave1上

    insert into test values(‘1’,‘aaa’,‘20’);
    在slave2上

    insert into test values(‘2’,‘bbb’,‘30’);
    img

    在主服务器上

    insert into test values('3','ccc','25');
    

    img

    在客户端服务器上

    use test_1;
    select * from test;   
    客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据 
    insert into test values('4','ddd','40');   
    只有主服务器上有此数据
    

    img

    img

    MySQL读写分离是基于MySQL主从复制的,其要求为至少一主两从,主服务器用于写数据,从服务器用于读。
    MySQL读写分离可以大大减少数据库的压力,提高数据库抗压能力

    5遇到问题

    安装MariaDB后无法启动怎么解决

    1、清除预装的mariadb或mysql

    rpm -aq|grep -E “mariadb|mysql”|xargs yum remove -y;
    2、卸载完成后再次查询已安装的mariadb和mysql

    rpm -aq|grep -E “mariadb|mysql”;
    3、查找数据库残留文件

    find / -name mysql;
    find / -name my.cnf;
    find / -name mariadb;
    如果能找到下面两个数据存储目录和配置文件,则需要删除

    /var/lib/mysql

    /etc/my.cnf

    4、安装mariadb客户端

    yum install -y mariadb;
    5、安装mariadb服务器

    yum install -y mariadb-server;
    6、启动mariadb服务

    #启动mariadb服务
    systemctl start mariadb;

    #补充
    #查看mariadb服务状态
    systemctl status mariadb;

    #关闭mariadb服务
    systemctl stop mariadb;

    #重启mariadb服务
    systemctl restart mariadb;
    7、给root用户设置密码

    mysqladmin -u root -p password ‘123456’;
    8、进入mariadb

    mysql -u root -p
    9、给root账号授权

    grant all privileges on . to root@‘%’ identified by ‘123456’; #授予root用户的密码为Aa123456.,允许其可以通过所有客户机访问本数据库下的所有的库及其下面所有的表,权限为所有权限。
    flush privileges; #刷新权限
    10、退出mariadb,开放防火墙3306端口号

    开端口命令:firewall-cmd --zone=public --add-port=3306/tcp --permanent

    重启防火墙:systemctl restart firewalld.service

    systemctl restart mariadb;

    6总结

    6.1主从复制
    主从复制,简单理解就是2个日志文件,三个线程。

    两日志

    二进制文件: 记录数据库变动的信息(语句、变动记录)
    中继日志文件: 用于临时存放二进制文件内容。
    三线程

    dump线程: ①监听I/O线程请求。②将二进制日志文件更新的数据发送给slave的I/O线程。
    I/O线程: ①监听master主机的二进制文件。②向master的dump线程发出同步请求
    SQL线程: 读取中继日志中的文件,更新到本机的数据库。

    6.2读写分离
    读写分离,简单来说,就是基于主从复制来进行读和写的操作,但是读和写是分开来的,读是在slave服务器上,写是在master服务器上,这样做的 目的可以很好的缓解master的压力,而且在生产环境中,读的频率要搞,所以salva服务器可以设置多套服务器,使用轮询,权重、哈希的分流策略进行分摊压力。

    10、退出mariadb,开放防火墙3306端口号

    开端口命令:firewall-cmd --zone=public --add-port=3306/tcp --permanent

    重启防火墙:systemctl restart firewalld.service

    systemctl restart mariadb;

    6总结

    6.1主从复制
    主从复制,简单理解就是2个日志文件,三个线程。

    两日志

    二进制文件: 记录数据库变动的信息(语句、变动记录)
    中继日志文件: 用于临时存放二进制文件内容。
    三线程

    dump线程: ①监听I/O线程请求。②将二进制日志文件更新的数据发送给slave的I/O线程。
    I/O线程: ①监听master主机的二进制文件。②向master的dump线程发出同步请求
    SQL线程: 读取中继日志中的文件,更新到本机的数据库。

    6.2读写分离
    读写分离,简单来说,就是基于主从复制来进行读和写的操作,但是读和写是分开来的,读是在slave服务器上,写是在master服务器上,这样做的 目的可以很好的缓解master的压力,而且在生产环境中,读的频率要搞,所以salva服务器可以设置多套服务器,使用轮询,权重、哈希的分流策略进行分摊压力。

  • 相关阅读:
    利用python爬取上证指数股吧评论并保存到mongodb数据库
    form表单的自定义校验规则
    让你的相册变成私有云!Synology Photos 的公网访问功能指南
    C 标准库 - <math.h>和<setjmp.h>详解
    微服务网关Gateway实践总结
    GitHub每日最火火火项目(9.16)
    使用ElementUI结合Vue完善主页的导航菜单和书籍管理的后台数据分页查询
    我看世界杯
    左程云 递归+动态规划
    【Java从入门到大牛】多线程
  • 原文地址:https://blog.csdn.net/linhaoyanglinhao/article/details/127095289