系列文章目录
Mysql集群及高可用-多主复制与Mysql路由(读写分离)8
mysql集群及高可用
- 系列文章目录
- 一、Mysql集群-主复制
- 二、容错机制(组模式)
- 三、配置多主复制
- 四、测试
- 五、Mysql路由(通过连接不同端口实现路由)(读写分离)
- 六、测试
- 6.1 7001端口(轮询)测试
- 6.2 7002端口(第一个服务器不可用才调度到第二个服务器)测试
- 七、总结
一、Mysql集群-主复制
Mysql集群的组复制有2种模式
单组模式以及多组模式
组复制必须要inodb引擎,数据库表结构需要有主键(有主键约束)
可以下载mysql的官方译文来进行学习
单主模式你只能在一个节点上去写,其余节点读(其实就是一组多从的架构)
但是当主挂了可以从slave端自动切换,内部高可用(这是个集群)
这种模式下,前面还需一层prox(实现读写分离),把所有数据库写的调度到master(也可读,但是一般都是调度到写),因为写不能在slave上面写,把所有读的调度到slave上面
主从有延迟,所以对实时性要求高的场景是不适合的
主从架构适用于读的请求远远高于写的请求
最多节点是9个,官网给出的
多主模式
所有节点都可以读写,完全去中心化,不需要找master
二、容错机制(组模式)
在有3个节点的集群,down一个集群还可以用,down两个集群就废了
三、配置多主复制
组复制对数据一致性的要求很高,这种多主复制,在任何一台节点上写的时候,会把这台节点上执行的sql语句发往集群中所有的节点进行校验,校验通过在所有节点上运行,集群内部任意一个节点校验失败,直接回滚不会执行该sql,所有节点都这样
**主复制必须使用Inodb引擎,要禁用其它的存储引擎,**当初编译数据库的时候,只编译了inodb引擎,然后书写my.cnf和官网少个禁用Inodb引擎的参数(认为可以不加),导致后续的报错,必须要加这个参数!!!
server1:
不再执行安全脚本,它会做其它的事情,我们要保证3个数据库一开始就一模一样,数据库的纯净,避免数据不一致的问题
由于是临时密码登录的,所以做不了任何事情,所以需要修改下密码
需要禁用sql语句不记录到二进制日志
这些参数需要加入到/etc/my.cnf
group_name是uuid形势的,你自己创建就行
默认情况下是不允许其他主机除了Localhost加入到mgr里面
所以需要把这个网段加入进去,表示这个网段其它主机加入也是允许的
默认是单组模式,你要OFF禁用
打开更新检测,这两个是配套的
需要创建用于主复制的用户
也是基于主从,二进制日志的复制
刚才写的my.cnf
都是要打开二进制日志的
先关闭二进制日志,因为我们需要先创建用户,避免冲突
创建用于复制的用户,授权,刷新使之生效(刷新用户授权表)
激活二进制日志
配置复制的信道
确认下加载的plugins
已经有了
集群是没有初始节点的,没有任何成员,所以需要一个引导节点
所以,将server1作为集群的初始节点
只有server1做这3步,其它节点负责join就行了
都是用uuid来标识成员Id,集群有成员了
server2:
初始化,不要加很多选项,避免影响初始化
修改主配置文件,只改id和Local_adress其余不变
id更改
local_address更改这个my.cnf不全,后续会报错
正确的:
需要再加入一个参数
操作和当初操作server1一样
不需要向server1一样修改参数,有个引导的节点,直接加入集群就行了
报错,查看错误日志
报错内容,数据冲突了,需要加入第二个红框的参数选项
加入join in的时候要放弃本地的数据,以master的数据为准,需要一个为准
在所有的slave端的/etc/my.cnf上多加上这个参数
加入后不用重启,直接进入数据库,直接用热生效就行
server1:
在数据库中,可以看到server2不是ONLINE,还是没有加入,处于恢复状态中
server2:
在数据目录下/usr/local/mysql/data
cat server2.err
出现问题,重新做下server3
server3:
修改/etc/my.cnf
做初始化
把server2的参数复制给3,更改下id localhost_address
在server1的数据库中:
server3也是恢复状态,2和3问题点一样
server3:
查看错误日志
在数据目录下cat server3.err
发现是master的问题,server1不能做master
server2:
可以发现server2还是OFFLINE
server3:
查看错误日志说是server1的问题
换一个做引导节点换成server2
server2:
集群中一定要有解析
server3:
server2
成功了
server1:
在server1上面添加相应的禁用数据库引擎
再添入这个参数,因为server1成为slave
还是没有加入进去
重新做一遍server1,估计是粗心导致最后server2和server3是好的
主配置文件就可以不用重新配了,之前配好的
多主模式搭建成功
四、测试
给多组模式创建数据库,一个创建后,所有节点都有,测试成功
组模式的数据库表结构需要有主键(有主键约束)
server1:
进入数据库
server2:
进入数据库
server3:
进入数据库
五、Mysql路由(通过连接不同端口实现路由)(读写分离)
后端是集群(无论单组多组),前面加个接入层,通过中间件,对于业务会更加透明
通过中间件代理将应用流量分摊到集群后端的结点上
Mysql路由是官方提供的代理插件,使用场景,应用和数据库的接口(负载均衡)
MGR (组复制) 内部自带高可用,由Mysql路由根据不同端口,连接到不同集群实现负载均衡
另一个软件Mysql prox(连接端口一致)是根据用户的sql语句(如查询和插入)不同sql来转发到不同的服务器集群,是一种反向代理机制(nginx一样),就是客户端始终知道连接的是server4,后台连接是谁不知道
也可以使用MyCAT(ali做的Mysql中间件)
再开启一个虚拟机server4,下载软件mysql-router-community
我提前下载好了,在我/pub/docs/mysql
,rpm安装
进入主配置目录/etc/mysqlrouter/mysqlrouter.conf
不用原本的修改配置文件,因为都是全局变量
添加上这段,根据端口来定义不同的负载均衡的组,通过不一样的算法
bind_adress监听地址本机所有接口
由于配置的3个节点是多主模式,不管是读写都可以调度
round-robin算法是轮询的,第一个读1,第二个读2,第三个读3
first-available第一个可用加载第一个,第一个不可用加载第二个
因为数据库的写入是持续的,第一个可用就一直用第一个就行了
然后启动服务
开启服务后,开启两个端口7001和7002
六、测试
7001端口和7002端口算法不一样
7001端口 :
round-robin算法是轮询的,第一个读1,第二个读2,第三个读3
7002端口 :
first-available第一个可用加载第一个,第一个不可用加载第二个
因为数据库的写入是持续的,第一个可用就一直用第一个就行了
6.1 7001端口(轮询)测试
宿主机:
在宿主机上面查看有无mysql命令
没有需要安装mariadb,都是客户端,所以使用mariadb也可以
yum install mariadb
-P 端口 -u 用户 -p 密码
没有授权,连接不了(只有本地,远程连接不了)
server1:
在server1、server2、server3上面都可以授权不只是sever1,因为每个节点都可以读写
给user1(可以远程登录)授予查询所有权限
给user2(可以远程连接)授予插入和更新的所有权限在test库
刷新用户授权表
继续测试
宿主机:
7001是只读的,调度到1上(轮询机制)
server1:
同理给sevre2、3都安装lsof
server2:
server3:
第一次连接失败了,所以根据轮询连接到server2
宿主机退出数据库,再次进入
server3:
server2:
server1:
再次测试一次
退出数据库,重新进入数据库
这个时候应该是server1有其它没有
6.2 7002端口(第一个服务器不可用才调度到第二个服务器)测试
换用户测试
宿主机:
server1:
server2:
server3:
宿主机:
server1:
连接的还是server1
宿主机:
退出数据库再进入数据库
连接还是1server1:
停止掉server1:
模拟发生故障,测试7002的算法,并且测试MGR集群的高可用
server2:
宿主机(客户端)断开数据库连接,再查看一次,它自动连接上(客户端重新连接了)
连接到server2上了
宿主机(客户端)
插入没有问题
后端集群还是可以用server3:
恢复server1:
server1:
加入集群,否则不在集群中
这个模式是GTID的形势(多主)
看看数据恢复没
数据恢复正常
停掉mysql路由为下面实验清理环境
七、总结
分表是垂直分(一个节点上深入优化)
分库是水平分(分到多个结点,水平扩容)
数据库读写分离,做更多优化需要分库分表
Mysql单表存储数据达到百万级,性能下降快
这个时候需要分库分表
一张大表拆成多个表,这样就不会达到百万
分库分到多个服务器(结点),水平扩容
可以通过MyCAT应用软件去做也可用通过后端数据库做好,在应用层(代码),在写代码直接高速读在那块读,写在那块写,应用直接接入数据库更快,效率最高,因为中间不需要代理,没有损耗
但是没有损耗意味着这种方式麻烦,开发应用的时候要完全知道数据库的变化,类似是写死了,代码写好了,一旦后续数据库变动,代码就需要更改很多
实际情况,后端数据库实例特别多,不好用直接代码写死,最好都是用代理层,提供一个统一的接入,接入后再由代理做相应的控制,这样好,而且还可以在代理层,做相应的缓冲(nosql),进一步减少数据库后端的压力,数据库是一个热点,应用都是从数据库里调数据,数据库一旦坏了,整个应用就报废了
END