• MySQL主从复制和基于Amoeba的读写分离部署


    MySQL主从复制和基于Amoeba读写分离

    什么是主从复制?

    ​ MySQL主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQl默认采用异步复制方式(还有多线程复制、半同步复制),这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库或者特定的表。

    简单理解就是:通过复制(异步、同步等方式)建立一个和主数据库完全一样的从数据库,从数据库会实时同步(复制)主数据库的记录。

    为什么要有MySQL主从复制?

    ​ 一是确保数据安全;做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据的丢失。

    ​ 二是读写分离,使数据库能支持更大的并发;在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。

    ​ 三是提升I/O性能;随着日常生产中业务量越来越大,I/O访问频率越来越高,单机无法满足,此时做多库的存储,实现多个库提供读,有效降低磁盘I/O访问的频率,提高了单个设备的I/O性能。

    ​ 主从复制从基础来讲,就是实现数据库主节点和从节点的数据同步,实现数据的备份,在主从的基础上可以通过读写分离,主设备写,从设备提供读,实现数据的负载分担(因为数据库写的时候会🔒表,无法读,但从节点是空闲的,所以从节点可以提供读)。这样降低了主节点的I/O访问频率,从而降低了主节点磁盘的I/O的压力。

    什么是读写分离?

    ​ 读写分离是指将数据库的读和写操作分不到不同的数据库节点上。主服务器负责处理写操作和实时性要求较高的读操作,从服务器负责处理读操作。

    一、MySQL主从复制原理

    ​ MySQL的主从复制就是,主数据库开启二进制日志,从数据库把主数据库的二进制日志复制到本地的一个中继日志中,再通过执行日志中的SQL语句,实现主从的数据同步。其实和二进制日志备份类似,通过二进制日志记录数据库的修改SQL语句,实现对数据库数据的修改,主和从执行相同SQL语句不就是数据同步了。

    二、主从复制的工作过程

    image-20220815173914937

    1、主数据库开启二进制日志,记录修改SQL语句。

    2、从数据库手动执行更改主数据库(change master to)语句连接主数据库。

    3、从数据库的IO线程和主数据库的dump线程建立连接。

    4、从数据库的IO线程向主数据库发出binglog请求,主数据库的dump线程响应请求,将本地的binlog以events事件的方式发送给从数据库的IO线程。

    5、从数据库IO线程接收后binlog数据后,存放到Relay log中。

    6、从数据库的SQL线程读取Relay log,并且把应用过的记录到relay-log.info中,在默认的情况下,应用过的relay log中的数据会被清理掉,所以relay log因为其消耗小,所以存放在缓存中(binglog存放在磁盘中)。

    两个日志:

    1. Binglog:用来记录mysql内部增删改查等对mysql数据库有更新的内容的记录。

    2. Relay-log:用于存放从主数据库发送过来的Binlog日志的数据,其中存放的是已经解析成各类events的记录。

    三个线程:

    1. dump线程:当binlog有变动时,log dump线程读取其内容发送个从节点的IO线程。

    2. IO线程:负责与主数据库建立连接,并发出请求,以及接收dump发送的binlog并存放到relay log中。

    3. SQL线程:会读取relay log中数据,运行其中的SQL语句,实现数据存放到从数据库中。

    三、主从复制方式

    1、异步复制方式

    ​ MySQL异步复制是主从复制过程中默认的复制模式。主从复制涉及三个线程,master I/O线程、slave I/O线程、slave sql线程。因为是异步复制,所以master事务的提交,不需要经过slave的确认,即master I/O线程提交事务后,不需要等待slave I/O线程的回复确认,master并不保证binlog一定写入到了relay log中;而slave I/O把binlog写入relay log后,由slave sql线程异步执行应用到slave mysql中,slave I/O也不需要slave sql的回复确认,并不保证relay log日志完整写入到了mysql中。

    2、半同步复制/增强半同步复制

    ​ 基于传统异步存在的缺陷,mysql在5.5版本推出半同步复制,是对传统异步复制的改进。在master事务commit前,必须确保binlog日志已经写入slave 的relay log日志中,收到slave给master的响应后,才能进行事务的commit。但是后半部分的relay log到sql线程仍然属于异步执行。

    ​ 增强半同步是在MySQL 5.7引入,其实半同步可以看成是一个过渡功能,因为默认的配置就是增强半同步,所以,大家一般说的半同步复制其实就是增强的半同步复制,也就是无损复制。
    增强半同步和半同步不同的是,等待ACK时间不同

    rpl_semi_sync_master_wait_point = AFTER_SYNC(默认)

    ​ 半同步的问题是因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户看到的是老数据。
    ​ 增强半同步将等待ACK的点放在提交Commit之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。

    3、全同步复制

    ​ 指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

    4、多线程复制

    ​ 在MySQL5.7中,带来了全新的多线程复制技术,解决了当master同一个schema下的数据发生了变更,从库不能并发应用的问题,同时也真正将binlog组提交的优势充分发挥出来,保障了从库并发应用Relay Log的能力。

    ​ 在MySQL8.0中,多线程复制又进行了技术更新,引入了writeset的概念,而在之前的版本中,如果主库的同一个会话顺序执行多个不同相关对象的事务,例如,先执行了Update A表的数据,又执行了Update B表的数据,那么BINLOG在复制到从库后,这两个事务是不能并行执行的,writeset的到来,突破了这个限制。

    四、MySQL读写分离原理

    1、读写分离存在意义

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

    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主从复制部署

    IP地址划分

    主机名IP地址角色说明
    server-test1192.168.10.11Master
    server-test2192.168.10.12slave1

    1、关闭防火墙和SELinux增强模块

    systemctl stop firewalld
    systemctl disable firewalld
    setenforce 0
    
    • 1
    • 2
    • 3

    image-20220815190841707

    2、设置MySQL主从服务器时钟同步(NTP)

    2.1、搭建NTP服务器

    将NTP服务器搭建在MySQL主服务器上(192.168.10.11)。

    yum -y install ntp
    
    • 1

    image-20220815191203107

    NTP服务配置文件

    各项参数详解
    ————————————————————————————————————————
    vi /etc/ntp.conf
    
    #系统时间与BIOS事件的偏差记录
    driftfile /var/lib/ntp/drift
    
    restrict default kod nomodify notrap nopeer noquery    # 拒绝所有IPv4的client连接此NTP服务器
    restrict -6 default kod nomodify notrap nopeer noquery    # 拒绝所有IPv6的client连接此NTP服务器
    
    
    restrict 127.0.0.1    # 放行本机localhost对NTP服务的访问
    restrict  ::1
    
    
    # Hosts on local network are less restricted.
    #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap    # 放行192.168.1.0网段主机与NTP服务器进行时间同步
    
    # Use public servers from the pool.ntp.org project.
    # Please consider joining the pool (http://www.pool.ntp.org/join.html).
    
    server 0.centos.pool.ntp.org iburst    # 代表的同步时间服务器
    server 1.centos.pool.ntp.org iburst
    server 2.centos.pool.ntp.org iburst
    server 3.centos.pool.ntp.org iburst
    
    #broadcast 192.168.1.255 autokey        # broadcast server
    #broadcastclient                        # broadcast client
    #broadcast 224.0.1.1 autokey            # multicast server
    #multicastclient 224.0.1.1              # multicast client
    #manycastserver 239.255.254.254         # manycast server
    #manycastclient 239.255.254.254 autokey # manycast client
    
    # Enable public key cryptography.
    #crypto
    
    includefile /etc/ntp/crypto/pw
    
    # Key file containing the keys and key identifiers used when operating
    # with symmetric key cryptography. 
    keys /etc/ntp/keys
    ----
    各项参数详解
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    配置NTP配置文件

    vim /etc/ntp.conf
    在restrict default nomodify notrap nopeer noquery 下添加放行网段。
    restrict 192.168.10.0 mask 255.255.255.0 nomodify notrap 
        # nomodify notrap 表示不允许客户端配置为时间服务器
        
    在末尾添加
    server 127.127.1.0							#设置本地是时钟源,注意修改网段
    fudge 127.127.1.0 stratum 8					#设置时间层级为8(限制在15内)
    
    systemctl start ntpd
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20220816001646856

    image-20220816001738514

    2.2、搭建NTP客户端
    yum -y install ntp ntpdate
    
        ntpdate 192.168.10.11  #指定同步NTP服务器
    crontab -e
        * 1 * * * /usr/sbin/ntpdate 192.168.10.11
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20220816005345374

    image-20220816005236232

    3、主服务器的mysql配置

    vim /etc/my.cnf
    server-id = 1
    log-bin=mysql-bin							#添加,主服务器开启二进制日志
    log-slave-updates=true						#添加,允许从服务器更新二进制日志
    
    systemctl restart mysqld
    
    mysql -u root -p
    GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.10.%' IDENTIFIED BY '123456';			#给从服务器授权
    FLUSH PRIVILEGES;
    
    show master status;
    
    #File 列显示日志名,Fosition 列显示偏移量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    image-20220816010506255

    image-20220816010812304

    image-20220816010941216

    image-20220816011044849

    4、从服务器的mysql配置

    vim /etc/my.conf
        server-id=2
        relay-log=relay-log-bin 
        //开启中继日志
        relay-log-index=slave-relay-bin.index
        //将中继日志存放至磁盘(中继日志默认存缓存)
        relay_log_recovery=1
    systemctl restart mysqld
    
    mysql -uroot -p
    change master to master_host='192.168.10.11' , master_user='myslave',master_password='123456',master_log_file='mysql-bin.000011',master_log_pos=595;
    //在从服务器上指定主服务器 ,偏移量表示主服务器的二进制文件位置变量初始的位置。
    start slave; //开启主从复制
    show slave status\G //查看主从复制
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    image-20220816011319737

    image-20220816011356452

    image-20220816011817513

    5、验证

    在主服务器上创建一个测试的数据库
        create database master_test;
    再在从服务器上查看
        show databases;
    
    • 1
    • 2
    • 3
    • 4

    image-20220816012023585

    image-20220816012121573

    6、在原有主从的基础上再追加部署一台从服务器slave2

    设置NTP
    yum -y install ntp ntpdate
        ntpdate 192.168.10.11  #指定同步NTP服务器
    crontab -e
        * 1 * * * /usr/sbin/ntpdate 192.168.10.11
    
    • 1
    • 2
    • 3
    • 4

    image-20220816155211972

    image-20220816155159054

    配置mysql配置文件
    vim /etc/my.conf
        server-id=3
        relay-log=relay-log-bin
        relay-log-index=slave-relay-bin.index
        relay_log_recovery=1
    //relay_log_recovery,当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1时,可在slave从库上开启该功能,建议开启;
    systemctl restart mysqld
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    image-20220816155340381

    将主服务器数据导入到从服务器中
    flush tables with read lock; //锁表防止后续数据写入,导致主从数据不一致
    mysqldump -uroot -p -A --master-data=1 > /opt/mysql_all.sql //完全备份
    scp -p /opt/mysql_all.sql root@192.168.10.13:/opt  //将备份文件发送到slave2
    mysql -uroot -p < /opt/mysql_all.sql   //slave2同步master数据
    
    • 1
    • 2
    • 3
    • 4

    image-20220816162024974

    image-20220816161810882

    image-20220816162606908

    image-20220816162946355

    配置slave2主从复制配置
    查看当前master二级制文件名和偏移量
        show master status;
    mysql -uroot -p
    change master to master_host='192.168.10.11' , master_user='myslave',master_password='123456',master_log_file='mysql-bin.000011',master_log_pos=775;
    //在从服务器上指定主服务器 ,偏移量表示主服务器的二进制文件位置变量初始的位置。
    start slave; //开启主从复制
    show slave status\G //查看主从复制
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    image-20220816163142954

    image-20220816163303307

    解锁主服务器
    UNLOCK TABLES ;
    
    • 1

    image-20220816163617301

    六、MySQL主从渎职和读写分离部署

    服务部署表

    应用名server-test1server-test2server-test3server-test4
    MySQL
    NTP
    Amoeba

    IP地址规划表

    主机名IP地址说明
    server-test1192.168.10.11MySQL master
    server-test2192.168.10.12MySQL slave1
    server-test3192.168.10.13MySQL slave2
    server-test4192.168.10.14Amoeba

    部署说明

    在之前的主从复制的实验中再添加一台MySQL从服务器和Amoeba服务器。

    1、关闭防火墙和SELinux增强模块

    systemctl stop firewalld
    systemctl disable firewalld
    setenforce 0
    
    • 1
    • 2
    • 3

    image-20220816153434542

    2、安装java环境

    //因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。
    //将jdk-6u14-linux-x64.bin 和 amoeba-mysql-binary-2.2.0.tar.gz.0 上传到/opt目录下。
    
    cd /opt/
    cp jdk-6u14-linux-x64.bin /usr/local/
    
    cd /usr/local/
    chmod +x jdk-6u14-linux-x64.bin 
    ./jdk-6u14-linux-x64.bin
    按空格到最后一行
    按yes,按enter
    
    mv jdk1.6.0_14/ /usr/local/jdk1.6
    
    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
    
    ##安装 Amoeba软件##
    mkdir /usr/local/amoeba
    tar zxvf /opt/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 说明安装成功
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    image-20220816170659788

    image-20220816171029982

    image-20220816171501469

    image-20220816172301972

    image-20220816171244656

    image-20220816172334558

    image-20220816172450852

    image-20220816172612786

    3、配置Amoeba读写分离

    grant all on *.* to test@'192.168.10.%' identified by '123123';
    
    • 1

    image-20220816174632868

    image-20220816174642299

    image-20220816174651505

    4、配置amoeba配置文件

    cd /usr/local/amoeba/conf/
    
    cp amoeba.xml amoeba.xml.bak
    vim amoeba.xml									#修改amoeba配置文件
    30修改
    amoeba
    32修改
    123123
    115修改
    master
    117去掉注释–
    master
    slaves
    cp dbServers.xml dbServers.xml.bak
    
    vim dbServers.xml								#修改数据库配置文件
    23注释掉
    作用:默认进入test库 以防mysql中没有test库时,会报错
    
    26修改
    
    test
    28-30去掉注释
    123.com
    45修改,设置主服务器的名Master
    
    48修改,设置主服务器的地址
    192.168.184.10
    52修改,设置从服务器的名slave1
    
    55修改,设置从服务器1的地址
    192.168.184.30
    58复制上面6行粘贴,设置从服务器2的名slave2和地址
    
    192.168.184.40
    65修改
    
    71修改
    slave1,slave2
    /usr/local/amoeba/bin/amoeba start&					#启动Amoeba软件,按ctrl+c 返回
    netstat -anpt | grep java							#查看8066端口是否开启,默认端口为TCP 8066
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    image-20220816175308446

    image-20220816175502015

    image-20220816175733532

    image-20220816180053012

    image-20220816180244559

    5、测试读写分离

    节省时间,在Amoeba服务器上安装mysql测试

    yum install -y mariadb-server.x86_64 mariadb
        //MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB来代替MySQL的InnoDB。
    
    • 1
    • 2

    image-20220816182501366

    mysql -u amoeba -p123123 -h 192.168.10.14 -P8066
    
    • 1

    image-20220816182536418

    在主服务器上
    create database test;
    use test;
     create table test (test varchar(48) not null primary key );
    两台从服务器上
    
    stop slave;						#关闭同步
    use test;
    在slave1上
    
    insert into test values('this is slave1');
    在slave2上
    stop slave;
    insert into test values('this is slave2');
    在主服务器上
    
    insert into test values('this is master');
    在客户端服务器上
    
    use test;
    select * from test;		//客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    image-20220816185028313

    image-20220816185458359

    image-20220816185505585

    image-20220816185515697

    image-20220816185603743

    进行读写测试

    //在客户端上
    insert into test values('this is write_test');	//只有主服务器上有此数据
    
    再在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
    start slave;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    再次查看各服务器test表的内容

    image-20220816185910968

    image-20220816185917117

    image-20220816190023943

  • 相关阅读:
    Prism 实现依赖注入
    【Linux】权限管理 _目录权限 _umask _粘滞位[学习总结 _复习专用]
    linux操作Rpm
    服了,一个ThreadLocal被问出了花
    【Day3】最长上升子序列|Python
    电力通信网与运营商5G网络融合方案
    GRPC 和 http
    Linux中Tomcat发布war包后无法正常访问非静态资源
    git 将本地分支与远程master主分支合并
    Eureka Series : Thinking in Dissertations
  • 原文地址:https://blog.csdn.net/weixin_46514551/article/details/126404510