hello大家好,我是魔笑,希望这篇文章对你有帮助

下面的文章会对如下几点进行讲解

1,搭建主从复制架构

目的:实现数据库的高可用,实现数据的读写分离

2,升级为半同步复制

 目的:解决数据丢失的问题并行复制

3,升级为并行复制

目的:解决从库复制延迟的问题

4,实现读写分离

5,升级为双主模式,介绍实现故障自动切换的MMM架构,MHA架构

目的:实现高可用,

一,搭建主从复制建构

原理:

1,首先Master会有一个线程BinlogDump Thread,将数据写入Binlog日志当中.

2,Slave的I/O Thread将读取到的Binlog信息写入到本地Relay Log中,

3,Slave的SQL Thread检测到Relay Log的变更请求,解析relay log中内容在从库上执行。

1,下载数据库

下载地址:

https://downloads.mysql.com/archives/community/

下载mysql5.7.28

8基于GID的主从复制 mysql mysql主从复制搭建_数据

2,为了搭建主从架构,我们得有两个服务器,有钱的可以买两台云服务器,如果没钱,那就下载虚拟机vmare,再用xshell连接,方便操作,可以看我这篇文章

(47条消息) VmWare的下载和虚拟机安装_魔笑的博客

3,将两台服务器都进行如下安装,将下载的mysql包导入服务器,并且解压,随后我们按一定的顺序去进行安装,因为包与包之间有依赖

[root@localhost mysql]# tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar
 //解压文件
mysql-community-embedded-5.7.28-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.28-1.el7.x86_64.rpm
mysql-community-devel-5.7.28-1.el7.x86_64.rpm
mysql-community-embedded-compat-5.7.28-1.el7.x86_64.rpm
mysql-community-libs-5.7.28-1.el7.x86_64.rpm
mysql-community-test-5.7.28-1.el7.x86_64.rpm
mysql-community-common-5.7.28-1.el7.x86_64.rpm
mysql-community-embedded-devel-5.7.28-1.el7.x86_64.rpm
mysql-community-client-5.7.28-1.el7.x86_64.rpm
mysql-community-server-5.7.28-1.el7.x86_64.rpm
//安装包的时侯按这个顺序执行
[root@localhost mysql]# rpm -ivh mysql-community-common-5.7.28-1.el7.x86_64.rpm 
[root@localhost mysql]# rpm -ivh mysql-community-libs-5.7.28-1.el7.x86_64.rpm
[root@localhost mysql]# rpm -ivh mysql-community-libs-compat-5.7.28-1.el7.x86_64.rpm
[root@localhost mysql]# rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm
[root@localhost mysql]# rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm
root@localhost mysql]# rpm -ivh mysql-community-devel-5.7.28-1.el7.x86_64.rpm
//初始化数据库
[root@localhost mysql]# mysqld --initialize --user=mysql
//查看数据的密码
[root@localhost ~]# cat /var/log/mysqld.log
如下部分数据,密码是:.8)0x>uL_sUr

2021-07-08T13:07:08.302187Z 1 [Note] A temporary password is generated for root@localhost: .8)0x>uL_sUr
//将mysql做成自动启动
[root@localhost ~]# systemctl start mysqld.service
//连接数据库
[root@localhost log]# mysql -uroot -p
//重新设置密码
mysql> set password=password('root');
//关闭防火墙
[root@localhost log]# systemctl stop firewalld
//禁用防火墙
[root@localhost log]# systemctl disable firewalld.service
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

如果遇到如下错误:

3.1,

错误:依赖检测失败:
libcrypto.so.10()(64bit) 被 mysql-community-libs-compat-5.7.28-1.el7.x86_64 需要
libcrypto.so.10(libcrypto.so.10)(64bit) 被 mysql-community-libs-compat-5.7.28-1.el7.x86_64需要
libssl.so.10()(64bit) 被 mysql-community-libs-compat-5.7.28-1.el7.x86_64 需要
libssl.so.10(libssl.so.10)(64bit) 被 mysql-community-libs-compat-5.7.28-1.el7.x86_64 需要
安装的时候最好在root权限下安装

在命令后面加如下命令即可

--nodeps --force

rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm --nodeps --force

3.2,

[root@localhost lib64]# mysql -uroot -p
如下:
错误:error while loading shared libraries: libncurses.so.5: cannot open shared object file
解决,找到/usr/lib64 或者是 /usr/lib 找到libncurses.so的高版本用如下命令:

sudo ln -s /usr/lib64/libncurses.so.6.1 /usr/lib64/libncurses.so.5
如下:
错误:error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory
同样的解决方法
sudo ln -s /usr/lib64/libtinfo.so.6.1 /usr/lib64/libtinfo.so.5

接下来我们就进入正题开始搭建

4 配置master主库

4.1修改/etc/my.cnf文件

###在my.cnf文件里添加
#开启binlog日志
log_bin=mysql-bin
#设置主库的id
server-id=1
#立即同步到binglog里面
sync-binlog=1
#不同步那些数据
binlog-ignore-db=performance_schema
binlog-ignore-db=information_schema
binlog-ignore-db=sys

修改完后记得重新启动数据库

[root@localhost etc]# systemctl restart mysqld

4.2,给slave授权,因为主库不是随便的人,需要得到授权的从库,才能复制

//给slave从库授权,才能对主库进行复制
//授权给root用户
mysql> grant replication slave on *.* to 'root'@'%' identified by 'root';
mysql> grant all privileges on *.* to 'root'@'%' identified by 'root';
//查看状态,显示binlog日志的名称,以及复制的起始位置,如下则说明启动成功
mysql> show master status;
+------------------+----------+--------------+-------------------------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB                          | Executed_Gtid_Set |
+------------------+----------+--------------+-------------------------------------------+-------------------+
| mysql-bin.000001 |      717 |              | performance_schema,information_schema,sys |                   |
+------------------+----------+--------------+-------------------------------------------+-------------------+
1 row in set (0.00 sec)

上面我们就把master主库搭健好了

5,配置slave库

5.1修改slave库的/etc/my.cnf配置文件

# 在my.cnf里面添加如下修改
#添加从库的服务id
server-id=2
#给从库的relaylog起一个名字
relay_log=mysql-relay-bin
#设置只读
read_only=1

5.2,改完后记得重新启动数据库

[root@localhost etc]# systemctl restart mysqld

5.3,查看有没有做过slave复制

//表明没有做过
mysql> show slave status;
Empty set (0.00 sec)

5.4,表明从那个主库复制数据,进入mysql终端,执行如下命令

master_host=‘主库的ip’

master_port=主库的端口

master_user='主库的用户root'

master_password='主库的密码'

master_log_file='主库的binglog日志,上面我们在主库上面查看到的'

master_log_pos=从主库复制的起始位置

mysql> change master to master_host='192.168.112.128',master_port=3306,master_user='root',master_password='root',master_log_file='mysql-bin.000001',master_log_pos=717;

5.6,启动slave

mysql> start slave;

5.7,用如下命令看是否开启成功:

mysql> show slave status \G;

显示如下说明开启成功:

Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.112.128
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 717
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

测试是否成功;

//master创建数据库,创建表,插入数据看slave是否也有数据
mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> use test;
Database changed
mysql> create table user(dno int primary key,name varchar(10))engine=innodb charset=utf8;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into user values(1,'java');
Query OK, 1 row affected (0.05 sec)

//slave查看
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> use test
Database changed
mysql> select * from user;
+-----+------+
| dno | name |
+-----+------+
|   1 | java |
+-----+------+
1 row in set (0.00 sec)

mysql>

好了,我们的主从复制架构就搭建成功了,后续我会更新其他的架构,如果对你有帮助可以收藏一下。

注意:

如果都配置好了,没有实现复制,首先用mysql> show slave status \G;查看状态,如果没有启动,启动 start slave;这个是很容易出现的问题

二,半同步复制

目的:添加半同步复制机制来降低数据丢失的概率。

半同步复制需要一个插件,semi,mysql5.7,支持这个插件,但没有带这个插件,需要安装

1,首先我们得查看是否可以支持动态插件得安装

mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)

2,可以用如下命令查看都有哪些插件,如果有那我们就不需要安装了

show plugins

3,在master主库安装如下插件

//安装插件,并且命名为'semisync_master.so'
mysql>install plugin rpl_semi_sync_master soname 'semisync_master.so'

4,用如下命令查看semi,的状态

mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | OFF        |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)

rpl_semi_sync_master_enabled 状态是OFF表示没有开启

 rpl_semi_sync_master_timeout  便是超时时间

5,那么我们要开启semi,并且设置超时时间,可以用如下命令,建议在文件/etc/my.cnf里添加如下参数进行设置

//设置为1是将semi开启
mysql> set global rpl_semi_sync_master_enabled=1;
//设置为1秒
mysql> set global rpl_semi_sync_master_timeout=1000;

6,接下就是去slave从库,安装semi插件

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

7,查看从库的状态,

mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

8,同上,我们要开启从库的semi,建议在文件/etc/my.cnf里添加如下参数进行设置,

//开启从库semi的插件
mysql> set global rpl_semi_sync_slave_enabled=1;
//停止slave;
mysql> stop slave;
//重启slave
mysql> start slave;

这样我们半同步复制就完成了

同样,我们可以对主库进行操作数据时,可以去查看/var/log/mysqld.log查看有没有使用半同步复制,到日志的最后面看到如下 数据,则说明成功了

2021-07-10T02:18:23.472872Z 3 [Note] Semi-sync replication initialized for transactions.
2021-07-10T02:18:23.472905Z 3 [Note] Semi-sync replication enabled on the master.
2021-07-10T02:18:23.473421Z 0 [Note] Starting ack receiver thread
2021-07-10T02:31:14.501075Z 3 [Warning] Timeout waiting for reply of binlog (file: mysql-bin.000002, pos: 416), semi-sync up to file , position 0.
2021-07-10T02:31:14.501108Z 3 [Note] Semi-sync replication switched OFF.

三,并行复制

原理:

在从库中有两个线程IO Thread和SQL Thread,都是单线程模式工作,因此有了延迟问题,我们可以采用多线程机制来加强,减少从库复制延迟。(IO Thread多线程意义不大,主要指的是SQL Thread多线程),那么SQL Thread用多个线程,同时操作就会引起事务冲突,那么怎么才能使事务不冲突呢,那么我们就将不冲突的事务放在一个组里面,同一组里实现多线程。在一个组里提交的事务,一定不会修改同一行。这是一种新的并行复制思路

1,并行复制就是以组为单位,进行事务复制,首先查看master主库设置组的一些参数

mysql> show variables like '%binlog_group%';
+-----------------------------------------+-------+
| Variable_name                           | Value |
+-----------------------------------------+-------+
| binlog_group_commit_sync_delay          | 0     |
| binlog_group_commit_sync_no_delay_count | 0     |
+-----------------------------------------+-------+
2 rows in set (0.00 sec)

2,设置组的参数,建议在文件/etc/my.cnf里添加如下参数进行设置

//设置有多少组
mysql> set global binlog_group_commit_sync_delay=1000;

//设置每个组有多少事务
mysql> set global binlog_group_commit_sync_no_delay_count=100;

3,接下来就是对slave从库进行配置,首先查看,slave的一些参数信息

mysql> show variables like '%slave%';
+---------------------------------+-----------------------+
| Variable_name                   | Value                 |
+---------------------------------+-----------------------+
| init_slave                      |                       |
| log_slave_updates               | OFF                   |
| log_slow_slave_statements       | OFF                   |
| pseudo_slave_mode               | OFF                   |
| rpl_semi_sync_slave_enabled     | ON                    |
| rpl_semi_sync_slave_trace_level | 32                    |
| rpl_stop_slave_timeout          | 31536000              |
| slave_allow_batching            | OFF                   |
| slave_checkpoint_group          | 512                   |
| slave_checkpoint_period         | 300                   |
| slave_compressed_protocol       | OFF                   |
| slave_exec_mode                 | STRICT                |
| slave_load_tmpdir               | /tmp                  |
| slave_max_allowed_packet        | 1073741824            |
| slave_net_timeout               | 60                    |
| slave_parallel_type             | DATABASE              |
| slave_parallel_workers          | 0                     |
| slave_pending_jobs_size_max     | 16777216              |
| slave_preserve_commit_order     | OFF                   |
| slave_rows_search_algorithms    | TABLE_SCAN,INDEX_SCAN |
| slave_skip_errors               | OFF                   |
| slave_sql_verify_checksum       | ON                    |
| slave_transaction_retries       | 10                    |
| slave_type_conversions          |                       |
| sql_slave_skip_counter          | 0                     |
+---------------------------------+-----------------------+

4,接下就就是去设置上一些参数,建议在文件/etc/my.cnf里添加如下参数进行设置

//设置前先把slave停止,不然不让设置
mysql> stop slave;
//将复制数据的类型从数据库复制,改为组复制
mysql> set global slave_parallel_type='LOGICAL_CLOCK';
//每组容许的最大线程数,建议4-8
mysql> set global slave_parallel_workers=8;

5,接下设置relaylog的一下参数,首先查看一下relaylog的一些参数信息

mysql> show variables like '%relay_log%';
+---------------------------+--------------------------------------+
| Variable_name             | Value                                |
+---------------------------+--------------------------------------+
| max_relay_log_size        | 0                                    |
| relay_log                 | mysql-relay-bin                      |
| relay_log_basename        | /var/lib/mysql/mysql-relay-bin       |
| relay_log_index           | /var/lib/mysql/mysql-relay-bin.index |
| relay_log_info_file       | relay-log.info                       |
| relay_log_info_repository | FILE                                 |
| relay_log_purge           | ON                                   |
| relay_log_recovery        | OFF                                  |
| relay_log_space_limit     | 0                                    |
| sync_relay_log            | 10000                                |
| sync_relay_log_info       | 10000                                |
+---------------------------+--------------------------------------+
11 rows in set (0.00 sec)

6,接下来就是设置

relay_log_info_file是日志信息源  设置为 table,,这样性能可以有50%~80%的提升

 relay_log_recovery将其打开,不然就没法往里面写了

7,设置参数,修改文件/etc/my.cnf的形式进行设置,有可能我们用set方式修改参数有可能不生效

所以我们尽量都用这种方式,写进文件

# log_bin
server-id=2
relay_log=mysql-relay-bin
read_only=1
relay_log_recovery=1
relay_log_info_file=table
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=8

8,文件设置完参数,需要重启服务

[root@localhost ~]# systemctl restart mysqld

这样我们就升级了并行复制。

四,读写分离

读写分离,我们可以采用两种方式去实现:

*.基于编程和配置实现(应用端),可以用ShardingSphere进行实现:ShardingSphere是一套开源的分布式数据库中间件解决方案

* 基于服务器端代理实现(服务器端),可以用MySQL Proxy进行实现:是官方提供的MySQL中间件产品可以实现负载平衡、读写分离等。

下面介绍的是基于服务器端代理实现

1,将下载mysql-proxy导入proxy服务器,并且将其解压

//解压mysql-proxy
drwxr-xr-x 8 7161 wheel       87 Aug 19  2014 mysql-proxy-0.8.5-linux-el6-x86-64bit
-rw-r--r-- 1 root root  12067298 Jul 11 08:59 mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz

2,创建/etc/mysql-proxy.cnf文件,在里面添加如下信息

#用户
user=root
#主库,从库的用户名
admin-username=root
#主库,从库的密码
admin-password=root
#代理服务器的地址
proxy-address=:117.50.3.46:4040
#主库的服务器地址(负责写)
proxy-backend-addersses=192.168.112.128:3306
#主库的服务器地址(负责读)
proxy-read-only-backend-addresses=192.168.112.129:3306
#控制读写分离的脚本
proxy-lua-script=/root/mysql/mysql-proxy-0.8.5-linux-el6-x86-64bit/share/doc/mysql-proxy/rw-splitting.lua
#表明mysql-proxy代理服务器的日志文件
log-file=/var/log/mysql-proxy.log
//日志级别
log-level=debug
#mysqlproxy运行的方式,守护进程的方式运行,启动起来,就在后台执行了
daemon=true
#遇到问题,尝试重启
keppalive=true

3,将刚刚新建的文件改为可读可写

[root@10-9-85-165 etc]# chmod 660 /etc/mysql-proxy.cnf

4,修改控制分离的脚本,修改最小连接数(当达到最小连接数才触发读写分离,可以为了测试,将最小连接数修改为1)

[root@10-9-85-165 mysql]# vi mysql-proxy-0.8.5-linux-el6-x86-64bit/share/doc/mysql-proxy/rw-splitting.lua
//部分数据
if not proxy.global.config.rwsplit then
        proxy.global.config.rwsplit = {
                //最小连接数
                min_idle_connections = 4,
                //最大连接数
                max_idle_connections = 8,

                is_debug = false
        }
end

5,启动如下脚本

mysql-proxy-0.8.5-linux-el6-x86-64bit/bin/mysql-proxy

如下:

[root@10-9-85-165 mysql]# cd mysql-proxy-0.8.5-linux-el6-x86-64bit/bin/
[root@10-9-85-165 bin]# ll
-rwxr-xr-x 1 7161 wheel 1707 Aug 19  2014 mysql-binlog-dump
-rwxr-xr-x 1 7161 wheel 1707 Aug 19  2014 mysql-myisam-dump
-rwxr-xr-x 1 7161 wheel 1707 Aug 19  2014 mysql-proxy
//启动mysql-proxy, 指定上面新建的配置文件/etc/mysql-proxy.cnf
[root@10-9-85-165 bin]# ./mysql-proxy --defaults-file=/etc/mysql-proxy.cnf

我们读写分离就完成。

 二,双主模式,MMM架构,MHA(实现故障自动切换)

为什么用双主模?是用另一个主库做备份,实现高可用

1,首先得新增一个主库,跟上面配置主库一样,需要配置一下,我这里就不重复这个过程了

2,在两台主库,都增加如下配置,在/etc/my.cnf文件下,添加如下配置,添加完后记得重启,mysql

#开启relaylog
relay_log=mysql-relay-bin
log_slave_updates=1
#在双主双写下,指定主键自动增长的方式1,3,5,双主单写下不需要
auto_increment_offset=1
auto_increment_increment=2

3,双主模式,两台主机需要互相同步,互为主从,所以,都需要执行如下命令,互相指定同步的机器,和binglog日志,以及位置,这个只是示例。要根据你的服务器把两台主库都配置了了。

强调:看复制的binlog日志名称,和位置,进入mysql终端用show master status查看,上面都有介绍 

mysql> change master to master_host='192.168.112.130',master_port=3306,master_user='root',master_password='root',master_log_file='mysql-bin.000001',master_log_pos=8848;

双主模式搭建好了,实现故障自动切换我们可以采用MMM架构或者MHA架构,下面是对这两种架构的介绍,我就不搭建,有兴趣的小伙伴可以去查阅资料,自己搭建

3,MMM架构

MMM(Master-Master Replication Manager for MySQL)是一套用来管理和监控双主复制,支持双主故障切换 的第三方软件。MMM 使用Perl语言开发,虽然是双主架构,但是业务上同一时间只允许一个节点进行写入操作。下图是基于MMM实现的双主高可用架构。

MMM架构的机制:

MMM故障处理机制MMM 包含writer和reader两类角色,分别对应写节点和读节点。当 writer节点出现故障,程序会自动移除该节点上的VIP写操作切换到 Master2,并将Master2设置为writer将所有Slave节点会指向Master2除了管理双主节点,MMM 也会管理 Slave 节点,在出现宕机、复制延迟或复制错误,MMM 会移除该节点的 VIP,直到节点恢复正常。

MMM监控机制MMM 包含monitor和agent两类程序,功能如下:

monitor:监控集群内数据库的状态,在出现异常时发布切换命令,一般和数据库分开部署。agent:运行在每个 MySQL 服务器上的代理进程,monitor 命令的执行者,完成监控的探针工作和具体服务设置,例如设置 VIP(虚拟IP)、指向新同步节点。

4,MHA架构

MHA(Master High Availability)是一套比较成熟的 MySQL 高可用方案,也是一款优秀的故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。MHA还支持在线快速将Master切换到其他主机,通常只需0.5-2秒。

 MHA故障处理机制:

MHA故障处理机制:

把宕机master的binlog保存下来

根据binlog位置点找到最新的slave

用最新slave的relay log修复其它slave

将保存下来的binlog在最新的slave上恢复

将最新的slave提升为master

将其它slave重新指向新提升的master,并开启主从复制 

MHA优点:

自动故障转移快

主库崩溃不存在数据一致性问题

性能优秀,支持半同步复制和异步复制

一个Manager监控节点可以监控多个集群