系列文章目录



Mysql集群及高可用-多主复制与Mysql路由(读写分离)8



mysql集群及高可用

  • 系列文章目录
  • 一、Mysql集群-主复制
  • 二、容错机制(组模式)
  • 三、配置多主复制
  • 四、测试
  • 五、Mysql路由(通过连接不同端口实现路由)(读写分离)
  • 六、测试
  • 6.1 7001端口(轮询)测试
  • 6.2 7002端口(第一个服务器不可用才调度到第二个服务器)测试
  • 七、总结



一、Mysql集群-主复制

Mysql集群的组复制有2种模式
单组模式以及多组模式

组复制必须要inodb引擎,数据库表结构需要有主键(有主键约束)

可以下载mysql的官方译文来进行学习

官方文档

官方主复制的系统变量含义


单主模式你只能在一个节点上去写,其余节点读(其实就是一组多从的架构)
但是当主挂了可以从slave端自动切换,内部高可用(这是个集群)

这种模式下,前面还需一层prox(实现读写分离),把所有数据库写的调度到master(也可读,但是一般都是调度到写),因为写不能在slave上面写,把所有读的调度到slave上面

主从有延迟,所以对实时性要求高的场景是不适合的
主从架构适用于读的请求远远高于写的请求

最多节点是9个,官网给出的

mysql 8 mgr多主搭建 mysql多主集群_sql


mysql 8 mgr多主搭建 mysql多主集群_sql_02


多主模式

所有节点都可以读写,完全去中心化,不需要找master

mysql 8 mgr多主搭建 mysql多主集群_数据库_03


二、容错机制(组模式)

在有3个节点的集群,down一个集群还可以用,down两个集群就废了

mysql 8 mgr多主搭建 mysql多主集群_java_04


三、配置多主复制

组复制对数据一致性的要求很高,这种多主复制,在任何一台节点上写的时候,会把这台节点上执行的sql语句发往集群中所有的节点进行校验,校验通过在所有节点上运行,集群内部任意一个节点校验失败,直接回滚不会执行该sql,所有节点都这样

**主复制必须使用Inodb引擎,要禁用其它的存储引擎,**当初编译数据库的时候,只编译了inodb引擎,然后书写my.cnf和官网少个禁用Inodb引擎的参数(认为可以不加),导致后续的报错,必须要加这个参数!!!


server1:

mysql 8 mgr多主搭建 mysql多主集群_mysql_05

mysql 8 mgr多主搭建 mysql多主集群_数据库_06

不再执行安全脚本,它会做其它的事情,我们要保证3个数据库一开始就一模一样,数据库的纯净,避免数据不一致的问题

mysql 8 mgr多主搭建 mysql多主集群_java_07

由于是临时密码登录的,所以做不了任何事情,所以需要修改下密码

mysql 8 mgr多主搭建 mysql多主集群_mysql_08

需要禁用sql语句不记录到二进制日志

mysql 8 mgr多主搭建 mysql多主集群_sql_09


mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_10

这些参数需要加入到/etc/my.cnf

group_name是uuid形势的,你自己创建就行

mysql 8 mgr多主搭建 mysql多主集群_sql_11

mysql 8 mgr多主搭建 mysql多主集群_java_12

默认情况下是不允许其他主机除了Localhost加入到mgr里面
所以需要把这个网段加入进去,表示这个网段其它主机加入也是允许的
默认是单组模式,你要OFF禁用
打开更新检测,这两个是配套的

mysql 8 mgr多主搭建 mysql多主集群_sql_13

需要创建用于主复制的用户
也是基于主从,二进制日志的复制

刚才写的my.cnf

都是要打开二进制日志的

mysql 8 mgr多主搭建 mysql多主集群_sql_14


先关闭二进制日志,因为我们需要先创建用户,避免冲突

mysql 8 mgr多主搭建 mysql多主集群_java_15


创建用于复制的用户,授权,刷新使之生效(刷新用户授权表)

激活二进制日志

配置复制的信道

确认下加载的plugins

mysql 8 mgr多主搭建 mysql多主集群_java_16


已经有了

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_17


集群是没有初始节点的,没有任何成员,所以需要一个引导节点

mysql 8 mgr多主搭建 mysql多主集群_数据库_18

所以,将server1作为集群的初始节点
只有server1做这3步,其它节点负责join就行了

mysql 8 mgr多主搭建 mysql多主集群_java_19

都是用uuid来标识成员Id,集群有成员了

mysql 8 mgr多主搭建 mysql多主集群_mysql_20


server2:

mysql 8 mgr多主搭建 mysql多主集群_mysql_21


初始化,不要加很多选项,避免影响初始化

mysql 8 mgr多主搭建 mysql多主集群_mysql_22

修改主配置文件,只改id和Local_adress其余不变

id更改

mysql 8 mgr多主搭建 mysql多主集群_java_23


local_address更改这个my.cnf不全,后续会报错

mysql 8 mgr多主搭建 mysql多主集群_数据库_24

正确的:
需要再加入一个参数

mysql 8 mgr多主搭建 mysql多主集群_java_25

操作和当初操作server1一样

mysql 8 mgr多主搭建 mysql多主集群_mysql_26


mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_27

mysql 8 mgr多主搭建 mysql多主集群_数据库_28


不需要向server1一样修改参数,有个引导的节点,直接加入集群就行了

报错,查看错误日志

mysql 8 mgr多主搭建 mysql多主集群_sql_29

报错内容,数据冲突了,需要加入第二个红框的参数选项
加入join in的时候要放弃本地的数据,以master的数据为准,需要一个为准

mysql 8 mgr多主搭建 mysql多主集群_mysql_30

在所有的slave端的/etc/my.cnf上多加上这个参数

mysql 8 mgr多主搭建 mysql多主集群_java_31


加入后不用重启,直接进入数据库,直接用热生效就行

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_32

mysql 8 mgr多主搭建 mysql多主集群_sql_33


server1:

在数据库中,可以看到server2不是ONLINE,还是没有加入,处于恢复状态中

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_34


server2:

mysql 8 mgr多主搭建 mysql多主集群_java_35


在数据目录下/usr/local/mysql/data

cat server2.err

mysql 8 mgr多主搭建 mysql多主集群_java_36

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_37


出现问题,重新做下server3


server3:

mysql 8 mgr多主搭建 mysql多主集群_mysql_38

mysql 8 mgr多主搭建 mysql多主集群_数据库_39


修改/etc/my.cnf

mysql 8 mgr多主搭建 mysql多主集群_java_40


做初始化

mysql 8 mgr多主搭建 mysql多主集群_mysql_41


把server2的参数复制给3,更改下id localhost_address

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_42

mysql 8 mgr多主搭建 mysql多主集群_数据库_43


mysql 8 mgr多主搭建 mysql多主集群_mysql_44


mysql 8 mgr多主搭建 mysql多主集群_sql_45

mysql 8 mgr多主搭建 mysql多主集群_mysql_46


mysql 8 mgr多主搭建 mysql多主集群_java_47


在server1的数据库中:

server3也是恢复状态,2和3问题点一样

mysql 8 mgr多主搭建 mysql多主集群_sql_48


server3:

查看错误日志

在数据目录下cat server3.err 发现是master的问题,server1不能做master

mysql 8 mgr多主搭建 mysql多主集群_mysql_49


server2:

mysql 8 mgr多主搭建 mysql多主集群_java_50


可以发现server2还是OFFLINE

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_51


server3:

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_52


查看错误日志说是server1的问题

换一个做引导节点换成server2


server2:

mysql 8 mgr多主搭建 mysql多主集群_sql_53

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_54


集群中一定要有解析

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_55


server3:

mysql 8 mgr多主搭建 mysql多主集群_mysql_56


server2

mysql 8 mgr多主搭建 mysql多主集群_mysql_57

成功了


server1:

mysql 8 mgr多主搭建 mysql多主集群_java_58


在server1上面添加相应的禁用数据库引擎

mysql 8 mgr多主搭建 mysql多主集群_java_59


再添入这个参数,因为server1成为slave

mysql 8 mgr多主搭建 mysql多主集群_java_60

mysql 8 mgr多主搭建 mysql多主集群_mysql_61


还是没有加入进去

mysql 8 mgr多主搭建 mysql多主集群_数据库_62

mysql 8 mgr多主搭建 mysql多主集群_sql_63


重新做一遍server1,估计是粗心导致最后server2和server3是好的

mysql 8 mgr多主搭建 mysql多主集群_java_64


主配置文件就可以不用重新配了,之前配好的

mysql 8 mgr多主搭建 mysql多主集群_java_65


mysql 8 mgr多主搭建 mysql多主集群_sql_66

mysql 8 mgr多主搭建 mysql多主集群_java_67

mysql 8 mgr多主搭建 mysql多主集群_sql_68


mysql 8 mgr多主搭建 mysql多主集群_数据库_69


多主模式搭建成功


四、测试

给多组模式创建数据库,一个创建后,所有节点都有,测试成功

组模式的数据库表结构需要有主键(有主键约束)

server1:

进入数据库

mysql 8 mgr多主搭建 mysql多主集群_mysql_70


server2:

进入数据库

mysql 8 mgr多主搭建 mysql多主集群_java_71


server3:

进入数据库

mysql 8 mgr多主搭建 mysql多主集群_sql_72


五、Mysql路由(通过连接不同端口实现路由)(读写分离)

后端是集群(无论单组多组),前面加个接入层,通过中间件,对于业务会更加透明
通过中间件代理将应用流量分摊到集群后端的结点上

Mysql路由是官方提供的代理插件,使用场景,应用和数据库的接口(负载均衡)

MGR (组复制) 内部自带高可用,由Mysql路由根据不同端口,连接到不同集群实现负载均衡


另一个软件Mysql prox(连接端口一致)是根据用户的sql语句(如查询和插入)不同sql来转发到不同的服务器集群,是一种反向代理机制(nginx一样),就是客户端始终知道连接的是server4,后台连接是谁不知道

也可以使用MyCAT(ali做的Mysql中间件)


mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_73


再开启一个虚拟机server4,下载软件mysql-router-community

我提前下载好了,在我/pub/docs/mysql,rpm安装

mysql 8 mgr多主搭建 mysql多主集群_mysql_74


mysql 8 mgr多主搭建 mysql多主集群_sql_75

进入主配置目录/etc/mysqlrouter/mysqlrouter.conf

不用原本的修改配置文件,因为都是全局变量

添加上这段,根据端口来定义不同的负载均衡的组,通过不一样的算法

bind_adress监听地址本机所有接口

由于配置的3个节点是多主模式,不管是读写都可以调度

round-robin算法是轮询的,第一个读1,第二个读2,第三个读3

first-available第一个可用加载第一个,第一个不可用加载第二个
因为数据库的写入是持续的,第一个可用就一直用第一个就行了

mysql 8 mgr多主搭建 mysql多主集群_mysql_76

然后启动服务

开启服务后,开启两个端口7001和7002

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_77


六、测试

7001端口和7002端口算法不一样
7001端口 :
round-robin算法是轮询的,第一个读1,第二个读2,第三个读3
7002端口 :
first-available第一个可用加载第一个,第一个不可用加载第二个
因为数据库的写入是持续的,第一个可用就一直用第一个就行了


6.1 7001端口(轮询)测试

宿主机:

在宿主机上面查看有无mysql命令

mysql 8 mgr多主搭建 mysql多主集群_mysql_78

没有需要安装mariadb,都是客户端,所以使用mariadb也可以

yum install mariadb

-P 端口 -u 用户 -p 密码

没有授权,连接不了(只有本地,远程连接不了)

mysql 8 mgr多主搭建 mysql多主集群_数据库_79


server1:

在server1、server2、server3上面都可以授权不只是sever1,因为每个节点都可以读写

给user1(可以远程登录)授予查询所有权限

mysql 8 mgr多主搭建 mysql多主集群_java_80

给user2(可以远程连接)授予插入和更新的所有权限在test库

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_81

刷新用户授权表

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_82

继续测试


宿主机:

7001是只读的,调度到1上(轮询机制)

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_83


mysql 8 mgr多主搭建 mysql多主集群_sql_84


mysql 8 mgr多主搭建 mysql多主集群_java_85


server1:

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_86


mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_87

同理给sevre2、3都安装lsof


server2:

mysql 8 mgr多主搭建 mysql多主集群_java_88


server3:

mysql 8 mgr多主搭建 mysql多主集群_mysql_89

第一次连接失败了,所以根据轮询连接到server2


宿主机退出数据库,再次进入

mysql 8 mgr多主搭建 mysql多主集群_sql_90

server3:

mysql 8 mgr多主搭建 mysql多主集群_数据库_91


server2:

mysql 8 mgr多主搭建 mysql多主集群_java_92

server1:

mysql 8 mgr多主搭建 mysql多主集群_数据库_93


再次测试一次

退出数据库,重新进入数据库

mysql 8 mgr多主搭建 mysql多主集群_sql_94

这个时候应该是server1有其它没有

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_95


6.2 7002端口(第一个服务器不可用才调度到第二个服务器)测试

换用户测试

宿主机:

mysql 8 mgr多主搭建 mysql多主集群_数据库_96

server1:

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_97


server2:

mysql 8 mgr多主搭建 mysql多主集群_sql_98

server3:

mysql 8 mgr多主搭建 mysql多主集群_数据库_99


宿主机:

mysql 8 mgr多主搭建 mysql多主集群_sql_100


server1:

连接的还是server1

mysql 8 mgr多主搭建 mysql多主集群_sql_101


宿主机:

退出数据库再进入数据库

mysql 8 mgr多主搭建 mysql多主集群_mysql_102


连接还是1server1:

mysql 8 mgr多主搭建 mysql多主集群_sql_103


停止掉server1:

模拟发生故障,测试7002的算法,并且测试MGR集群的高可用

mysql 8 mgr多主搭建 mysql多主集群_sql_104

server2:

mysql 8 mgr多主搭建 mysql多主集群_sql_105


mysql 8 mgr多主搭建 mysql多主集群_java_106


宿主机(客户端)断开数据库连接,再查看一次,它自动连接上(客户端重新连接了)

mysql 8 mgr多主搭建 mysql多主集群_sql_107

连接到server2上了

mysql 8 mgr多主搭建 mysql多主集群_mysql_108


宿主机(客户端)

插入没有问题

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_109


后端集群还是可以用server3:

mysql 8 mgr多主搭建 mysql多主集群_java_110

mysql 8 mgr多主搭建 mysql多主集群_sql_111


恢复server1:

server1:

mysql 8 mgr多主搭建 mysql多主集群_java_112


mysql 8 mgr多主搭建 mysql多主集群_mysql_113

加入集群,否则不在集群中

mysql 8 mgr多主搭建 mysql多主集群_数据库_114


mysql 8 mgr多主搭建 mysql多主集群_java_115

这个模式是GTID的形势(多主)

看看数据恢复没

数据恢复正常

mysql 8 mgr多主搭建 mysql多主集群_java_116

停掉mysql路由为下面实验清理环境

mysql 8 mgr多主搭建 mysql多主集群_mysql 8 mgr多主搭建_117


七、总结

分表是垂直分(一个节点上深入优化)
分库是水平分(分到多个结点,水平扩容)
数据库读写分离,做更多优化需要分库分表
Mysql单表存储数据达到百万级,性能下降快
这个时候需要分库分表
一张大表拆成多个表,这样就不会达到百万
分库分到多个服务器(结点),水平扩容

可以通过MyCAT应用软件去做也可用通过后端数据库做好,在应用层(代码),在写代码直接高速读在那块读,写在那块写,应用直接接入数据库更快,效率最高,因为中间不需要代理,没有损耗
但是没有损耗意味着这种方式麻烦,开发应用的时候要完全知道数据库的变化,类似是写死了,代码写好了,一旦后续数据库变动,代码就需要更改很多

实际情况,后端数据库实例特别多,不好用直接代码写死,最好都是用代理层,提供一个统一的接入,接入后再由代理做相应的控制,这样好,而且还可以在代理层,做相应的缓冲(nosql),进一步减少数据库后端的压力,数据库是一个热点,应用都是从数据库里调数据,数据库一旦坏了,整个应用就报废了


END