数据库中间件 mycat 介绍 实现mysql读写分离 mysql主从同步

1 引入

数据库作为一个项目最重要的部分,不允许出现任何差错,所以Mysql也要实现主从结构,读写分离,要实现这种结构,通常借助一个开源的数据库中间件Mycat

2 是什么

Mycat是阿里巴巴开源的数据库中间件,实现了 MySQL 协议的Server,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数据库里。

  • 对于软件工程师来说

    Mycat 就是一个近似等于 MySQL 的数据库服务器,你可以用连接 MySQL 的方式去连接 Mycat(除了端口不同,默认的 Mycat 端口是 8066 而非 MySQL 的 3306,因此需要在连接字符串上增加端口信息),大多数情况下,可以用你熟悉的对象映射框架使用 Mycat,但建议对于分片表,尽量使用基础的 SQL 语句,因为这样能达到最佳性能,特别是几千万甚至几百亿条记录的情况下。

  • 对于架构师来说

    Mycat 是一个强大的数据库中间件,不仅仅可以用作读写分离、以及分表分库、容灾备份,而且可以用于多租户应用开发、云平台基础设施、让你的架构具备很强的适应性和灵活性,借助于即将发布的 Mycat 智能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码一行也不用改变。

简单来说,mycat就是一个代理,我们把它当数据库使用,但它实际不是数据库,而是一个java应用,它帮我们关联数据库以及执行sql语句并返回结果

查看GitHub的官方readme,可以看到Mycat的功能介绍,其中的部分内容给出了解决数据库集群环境下遇到的问题的工具

说明:

    1. 一般不会用Mycat的“基于心跳的自动故障切换”,因为数据库是一个很严谨的东西,假如在数据写入数据库时master数据库挂了,Mycat又自动切换数据库,就会导致数据丢失——master真挂了,要靠别的方式去解决(类似redis的aof机制),避免数据丢失,这是一个中间件无法解决的

    2. 一般不会用Mycat的“分布式事务”

    3. 一般也不会用Mycat的“全局序列号”,都用自己的独立的额外的解决方案

3 应用场景

  1. 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;

  2. 分表分库,对于超过 1000 万的表进行分片,最大支持 1000 亿的单表分片;

  3. 多租户应用,每个应用一个库,但应用程序只连接 Mycat,从而不改造程序本身,实现多租户化;

  4. 报表系统,借助于 Mycat 的分表能力,处理大规模报表的统计;

  5. 替代 Hbase,分析大数据;

  6. 作为海量数据实时查询的一种简单有效方案

4 安装

从GitHub下载安装包,放到Linux系统下的opt文件夹下,解压Mycat安装包,可以得到一个文件夹

tar zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

将文件夹移动到usr/local下,由于mycat是一个java程序,所以直接启动就行,相关配置在各种配置文件中

mv mycat /usr/local/

5 server.xml中的配置

在启动mycat前,需要修改server配置文件中的设定

cd /usr/local/mycat
vim server.xml

在server.xml里可以配置多个user标签,对应多个连接mysql的账号,每个账号通过标签设置密码

接着配置该账户对应的逻辑库“TESTDB”,每个逻辑库都可以基于privileges标签对库和表的权限进行设置,这种权限管理功能默认关闭,dml分为4个值,顺序为“增改查删”,0代表没有权限,1代表有权限,所以这里的0110表示只有改和查的权限

通过设置readOnly,可以令账号只具备查看权限

6 schema.xml中的配置

6.1 最终配置如图

在schema.xml中可以配置逻辑库,包括创建逻辑库(用于在server.xml中使用)、将逻辑库映射到mysql数据库,简洁版配置最终代码如图

整个配置从上往下写,但理解上要从下往上看

6.2 dataHost标签

声明dataHost标签,这个标签里配置连接参数和心跳检测

6.2.1 配置连接参数

6.2.1.1 balance属性(实现读写分离)

dataHost标签中有一个balance属性,用于设置负载均衡模式,通常设为3,也就是开启读写分离

balance=0:不开启读写分离,所有读操作都发生在当前的writeHost上
balance=1:所有读操作都随机发送到当前的writeHost对应的readHost和备用的writeHost
balance=2:所有的读操作都随机发送到所有的writeHost,readHost上
balance=3:所有的读操作都只发送到writeHost的readHost上

6.2.1.2 writeType属性

这个属性默认值为0,通常使用时不需要配置

负载均衡类型,目前的取值有3种:
writeType="0", 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
writeType="1",所有写操作都随机的发送到配置的writeHost。 
writeType="2",没实现。

6.2.1.3 switchType属性

这个属性默认值为1,通常也不需要修改

switchtype属性如下(控制自动切换的 )
-1不自动切换
1默认值自动切换
2基于mysql主从状态决定是否切换

6.2.1.4 dbType属性

就是设置逻辑库关联的数据库类型,通常就是mysql

6.2.1.5 dbDriver属性

默认为native,即本地的,通常也不需要修改

6.2.2 配置心跳检测(heartbeat标签)

  • 拓展:mycat心跳检测的原理

    在mysql中输入下面的sql语句,就能获得一条数据

    所以mycat要做的就是对各个关联的数据库随便发送一个查询,只要能收到回复,就证明数据库存活

这个标签用于设置mycat执行心跳检测时发送的查询语句

6.2.3 writeHost标签

用于配置mycat连接的用于写入操作的mysql

6.2.4 readHost标签

用于配置mycat连接的用于读取操作的mysql,为了简化,只配置了一个readHost标签

6.3 dataNode标签

接着声明dataNode标签,这个标签关联mysql数据库以及dataHost

6.4 schema标签

最后声明schema标签,一个schema标签对应一个逻辑库,通过配置多个schema标签,实现创建和配置逻辑库

6.4.1 逻辑库关联server.xml的账户

创建的逻辑库的名字要与server.xml中配置账户时给的逻辑库名字相同,这才能将逻辑库关联到server.xml的账户

6.4.2 设置逻辑库查询mysql数据库时数据数量限制

  • 拓展:mysql查询数据时多用limit

    如果要直接查看mysql,建议直接双击打开表,因为这等于执行

select * from 表名 limit 1000

    或者执行下面的代码(但也不建议用,只是+limit相对count+limit)

select * from 表名 limit 100

    千万不要使用下面的命令

select * from 表名   //如果数据由1亿,就真的会去查1亿
select count from 表名 limit 100   //不要用count 这会扫描整个表 直接用*就行了

mycat查询mysql的数据时,可以设置每次返回的数量,等效于sql语句中设置limit,避免一次查太多数据导致mysql数据库崩溃

6.4.3 设置逻辑库关联的dataNode

每个schema标签关联一个dataNode标签,实现逻辑库的配置

7 启动mycat

  • 拓展:报错 can`t get connection for sql

    如果报错,如图表示心跳检测功能希望发送select user()到mysql,但没能成功,可能原因是给mycat配置的账户权限不足,如果mysql确实修改了账户权限,那么尝试刷新一下mysql的缓存或者重启mysql,令账户权限的修改生效

  • 拓展:mysql的缓存

    mysql也有自己的内存级的缓存,在启动时就把配置存到了内存中,所以如果手动修改了user表中账号的权限,要么手动重启mysql,要么执行下面的刷新语句,否则更新后的权限无法载入缓存

GitHub上的官方文档给出了运行指令,可以看出mycat是一个独立的进程

根据官方文档,使用命令启动mycat

8 mycat连接测试

启动mycat后,先进行连接测试

官方推荐采用命令行测试,类似mysql的连接方式

//mysql连接方式如下
mysql -u root -p

//mycat连接方式如下
mysql -uroot -proot -P8066 -h127.0.0.1

9 演示mycat的读写分离

上面配置并开启了mycat后,在win下,可以通过navicat查看mysql的主库和从库,主库配置在虚拟机中,从库配置在本地

通过navicat连接mycat,可以看到mycat连接的表,这些表就是mycat通过mysql负责读取操作的库获得的表

点击这些表,修改表中的数据,数据不会显示出来,反倒显示在了主库,这说明通过修改这张表,实现了数据写入mysql负责写入操作的库,而修改结果不显示在这张表上,说明修改结果并没有同步到mysql负责读取操作的库中,也是就是说没有实现主从同步

但至少已经看得出,mycat实现了mysql的读写分离

10 设置主从同步

  • 拓展:mysql配置文件之long query time

    在mysql的配置文件中(my.ini),有一个配置叫“long query time” 默认为10,表示超过10秒的查询为慢查询,会被记录到log中,方便开发人员查阅以便优化sql或者表

  • 拓展:mysql配置文件之max_connection

    在win或mac系统的my.ini中,可以修改mysql的一些设置

    其中max_connection=151代表最大并发数,可以把mysql看成插排,可同时接收151个插头,所以这151并不少,实际开发每个请求能用个1秒就了不得了,用完就走了,所以基本用不上修改

虽然已经配置了读写分离,但是还没有配置主从同步,所以数据写到主库后,并没有自动同步到从库

10.1 设置mysql主库的配置文件

mysql的主库配置在虚拟机上,因此需要在虚拟机中打开主库的配置文件,Linux系统中,环境配置文件放置在etc目录下

在Linux下的mysql配置文件默认属性很少,但只是默认没配置进去,并不代表没有这个属性,可以根据win下的mysql配置文件往上加

vim /etc/my.cnf

首先添加服务id配置,要保证唯一

server-id=1

然后开启二进制日志文件

log-bin=/var/lib/mysql/mysql-bin

最终配置如图

重启mysql

service mysqld restart

在navicat连接的主库下,执行sql语句,这能生成一个叫mysql-bin.000001的文件和position值,这两个数据用于配置从库

show master status;

10.2 设置mysql从库的配置文件

由于mysql的从库配置在本机,所以在win系统下搜索my.ini即可找到配置文件

首先添加服务id配置,要保证唯一

server-id=2

然后重启数据库,通过win+R启动“运行”弹窗,输入下面的命令,进入计算机管理窗口,执行重启操作

services.msc

接着在navicat中,在从库下新建一个查询,输入停止从库的命令

接着执行下面的查询代码,将从库的master变更为执行master

change master to master_host='主库IP',
master_port=3306, master_user='主库用户名', 
master_password='主库密码', 
master_log_file='主库刚刚查到的File值',
master_log_pos= Position值;

最后执行下面的查询代码,重启从库

START SLAVE

现在可以查看从库的状态,可以看到从库显示正在等待主库发送指令,现在我们再给主库修改数据,从库就能实时同步数据

10.3 演示主从同步

  • 拓展:mysql从库同步主库的原理

    从库同步主库的原理是主库发生变化时,主库发送指令告知从库,从库通过读取主库保存增量指令的日志文件实现数据同步,而主库保存增量指令的日志文件就是之前获得的file

现在依然通过mycat打开mysql的表,直接修改表中的数据,按下提交的“√”后,表上的数据并没有修改,但是刷新一下表,发现数据修改了

这一系列变化,首先说明mycat实现了mysql读写分离,然后说明了mysql实现了主从同步——之所以要刷新一下,是因为主从同步存在一定的延迟

mycat实现读写分离以及mysql实现主从同步的流程如图,其中提到了弱一致性,指的是可以允许等待一段时间后,才达成一致性;相对的,强一致性则是要求一旦发生数据修改,立马同步

另一个概念是最终一致性,就需要等待很久才达成一致性,常见场景是前端发来许多订单请求,为了避免请求过多导致服务器阻塞,我们会把这些请求放在redsi中,为了避免redis崩溃导致数据丢失,所以每隔半小时把数据从redis保存到mysql中,放到mysql的过程就是达到最终一致性,在系统庞大的情况下, 我们都会追求最终一致性。

而强一致性的场景比如取款,一旦取出就要立刻达成一致,避免超额,实现手段是使用锁

现在,整个数据库集群的结构如下

posted @ 2021-10-10 22:56  夏·舍  阅读(186)  评论(0编辑  收藏  举报