当前位置:首页 > 创新应用 > 正文

MySQL读写分离原来如此简单

前言这篇我们来说说基于Mycat实现读写分离,实现的相关技术还有sharding-sphere、TDDL等,技术解决的问题都是一致的,技术之间思想基本相同,所以我们只需要发现系统中可能存在的问题,理解理论上的解决方案和找到一个应用上的落地实现的技术就可以了。话不多说我们以以下几方面介绍:现存数据库存...

前言这篇我们来说说基于Mycat实现读写分离,实现的相关技术还有sharding-sphere、TDDL等,技术解决的问题都是一致的,技术之间思想基本相同,所以我们只需要发现系统中可能存在的问题,理解......

前言

这篇我们来说说基于Mycat实现读写分离,实现的相关技术还有sharding-sphere、TDDL等,技术解决的问题都是一致的,技术之间思想基本相同,所以我们只需要发现系统中可能存在的问题,理解理论上的解决方案和找到一个应用上的落地实现的技术就可以了。话不多说我们以以下几方面介绍:

现存数据库存在问题

解决方案

MyCat使用和基本原理

单库应用

最简单的软件系统和数据库架构就是这样的只有一个单独的数据库,想想我们的系统刚开发,或者你是大学生在做毕业设计的时候,架构是不就是下图这样的:


问题

如上图我们的应用程序和MySQL数据库直连,数据库的配置信息是写在我们的应用配置文件中(脑子里要闪现出项目中的数据库配置),数据库只有一个实例来提供服务,之后我们的项目要发布到网络上提供服务,如果网站推广做的好就会有越来越多的用户使用,访问量就会很大,App可以通过nginx负载均衡等,我们的数据库还是单机在卖命?压力就会很大,一旦数据库宕机就GG了逆风翻盘已不存在,客户心里就骂骂咧咧的:垃圾软件卸载,所有的数据都存储在一个数据库中或者一个表中,数据越来越多怎么办?单表数据超过几百万条,几千万条上亿条怎么维护?等等总结几点如下:

应用程序直连数据库,耦合性高

用户并发高,数据库压力大,无论读还是写没有明确划分

数据库单实例运行是肯定不行的

表中数据越来越多怎么维护等等

解决方案

通过上边问题相信大家可以看出本质,我们可以部署多台MySQL搭建集群,配置读和写操作不同的数据库,数据进行拆分,存储在多张表中,应用程序与数据库降低耦合,添加中间件,总结几点如下

添加数据库中间件降低耦合

读写分离,提高数据库响应速度

数据库分表分库,更好维护数据

上边我们说到数据库会出现什么问题以及解决的思想,就是使用数据库中间件(MyCat)来做读写分离,分表分库等,下边我们就说说如何具体使用!

数据库中间件什么时候使用中间件

随着业务的发展,数据库里的表越来越大,一两年以后,2千万、甚至上亿记录的表就会出现了(一般可以简单认为表比较复杂的时候,MySQL几百万上千万的时候,Oracle几千万的时候,就会出现复杂查询或变更有性能问题),这时候可能会导致复杂的查询慢,插入和修改数据慢,修改表的DDL执行太慢导致无法修改列类型或者加索引或者加字段等等。怎么办呢?这时候我们就可以读写分离,分表分库
如果我们的业务发展到了需要降低单库单表的压力、或者读写分离,而研发团队又不大,自己对这一块的技术积累不足以自己开发一些中间层代码去搞定问题,就需要考虑引入数据中间件了。

常用中间件


Cobar:
阿里巴巴B2B开发的关系型分布式系统,管理将近3000个MySQL实例。在阿里经受住了考验,后面由于作者的走开的原因cobar没有人维护了,阿里也开发了tddl替代cobar。

Mycat:
社区爱好者在阿里cobar基础上进行二次开发,解决了cobar当时存在的一些问题,并且加入了许多新的功能在其中。目前MyCAT社区活跃度很高,目前已经有一些公司在使用MyCAT。总体来说支持度比较高,也会一直维护下去,

OneProxy:
数据库界大牛,前支付宝数据库团队领导楼总开发,基于mysql官方的proxy思想利用c进行开发的,OneProxy是一款商业收费的中间件,楼总舍去了一些功能点,专注在性能和稳定性上。有朋友测试过说在高并发下很稳定。

Vitess:
这个中间件是Youtube生产在使用的,但是架构很复杂。与以往中间件不同,使用Vitess应用改动比较大要使用他提供语言的API接口,我们可以借鉴他其中的一些设计思想。

Kingshard:
Kingshard是前360Atlas中间件开发团队的陈菲利用业务时间用go语言开发的,目前参与开发的人员有3个左右,目前来看还不是成熟可以使用的产品,需要在不断完善。

Atlas:
360团队基于mysqlproxy把lua用C改写。原有版本是支持分表,目前已经放出了分库分表版本。在网上看到一些朋友经常说在高并发下会经常挂掉,如果大家要使用需要提前做好测试。

MaxScale
是mariadb(MySQL原作者维护的一个版本)研发的中间件

MySQLRoute
MySQL官方Oracle公司发布的中间件

国内使用较多的是Mycat,免费,简单,功能强大,社区完善,后两者虽是官方提供的但是拿到国内就有点水土不服,毕竟国内网站的吞吐量是非常大的。现在也有选择使用sharding-sphere的

Mycat安装

下载上传Linux解压安装在/usr/local目录下即可,版本为1.6,下图就是mycat目录结构,几乎所有软件都是这些目录就不一个一个说了!


mycat主要配置文件

:定义逻辑库,表、分片节点等内容

:定义分片规则

:定义用户以及系统相关变量,如端口等

一主一从读写分离


我们先来个一主一从配置,主库负责写入数据,从库负责读取数据,从库和主库需要数据同步,可以使用MySQL(5.5版本之后)自带的主从复制实现,先搭建MySQL主从复制,再配置一主一从实现读写分离,一个主机负责处理所有的写请求,一台从机负责所有的读请求,架构图如下


Mysql主从复制原理

主数据库会将所有的写操作写入到二进制文件(binlog)中,从数据库读取binlog日志再将读取到的binlog写入到中继日志(Relaylog)中,再通过SQL线程执行语句,实现主从复制数据同步,与Redis一样主数据库只能有一台,从数据库可以有多台,不同之处在于Redis是全量复制,而MySQL是从确认主从关系后开始复制,之前的数据是不同步的,读取二进制文件和写入中继日志都会发生IO所以会存在延时


主数据库配置(编辑/etc/文件)
启动二进制日志log-bin=mysql-bin设置需要复制的数据库,这里设置了上边不复制项就可以不设置binlog-do-db=mycatdbServerIDserver-id=2重启systemctlrestartmysqld关闭防火墙systemctlstopfirewalld查看防火墙状态systemctlstatusfirewalld


创建可以进行复制的从节点用户slave
刷新flushprivileges;例如changemastertomaster_host='192.168.11.201',master_user='slave',master_password='123456',master_log_file='',master_log_pos=582;

如果之前环境搭建过主从复制会报错,运行stopslave;和restartmaster;

启动从服务器复制功能
查看从服务器状态showslavestatus\G;
哎呦?出错了?


不慌

程序员基本素养看日志,问题提示主从使用了相同的serverUUID,这个UUID是在文件中,也就是你安装mysql时在文件中配置的datadir路径下,输出之后发现确实是一样的

[root@stt201data][auto]server-uuid=dbbcb5a4-7331-11ea-b078-000c29382f46
盘它

停止从库的mysqld服务,删除文件,再启动数据库服务即可:

systemctlstopmysqld删除文件systemctlstartmysqld查看状态
一套创建库创建表插入数据连招安排
--创建、添加数据都是写,你说在哪弄?--创建库CREATEDATABASEmycatdb;--创建表_mycat(idINTNOTNULL,nameVARCHAR(20)NOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;--插入数据_mycat(id,name)values(1,"添添"),(2,"小添"),(3,"晓添");--主库和从库查询数据若都可以正常显示,说明木得问题SELECTid,_mycat;
Mycat配置读写分离

分为以下两个步骤:

修改文件

修改文件

修改文件


修改文件

删除schema标签间表信息,datanode标签只留一个,dataHost标签只留一个,writeHost,readHost只留一对


启动Mycat吧前提

安装JDK,并且配置环境变量,Mycat基于Java编写,需要JVM

在mysql中创建mycat用户密码为123456(和我们文件中一致)

mysql启动远程访问

--表示任意ip后可通过root用户密码123456访问GRANTALLPRIVILEGESON*.*TO'root'@'%'IDENTIFIEDBY'123456'WITHGRANTOPTION;--刷新flushprivileges;

sql都准备好,就是懂你~~~

启动方式

控制台启动:到mycat/bin目录下运行./mycatconsole;推荐使用,可以第一时间看到日志方便定位问题

后台启动:到mycat/bin目录下运行./mycatstart;


如果看到图上红框内容说明mycat启动成功

Mycat登陆登录后台管理窗口

用于管理维护Mycat

登陆数据窗口

用于通过Mycat查询数据,我们开发是使用8066端口搞事情

查看数据
--登陆查看数据库,看下图,查出来的是我们的逻辑库,区分大小写哦showdatabases;--使用逻辑库useMYCATDB;--查看库下所有表showtables;--查看数据SELECT*FROMtb_mycat;


验证读写分离
--进入主mysql,添加一条数据,@@hostname为当前主机的名字--主数据库和从数据库的主机名不同,所以数据也不一样_mycat(id,name)values(4,@@hostname);--我们登陆mycat查看数据,如果是从数据库的数据那么就证明成功SELECT*_mycat;

呀呀呀!咱们到这里就实现MySQL的主从复制,使用Mycat实现Mysql单主单从的读写分离,心里还真有点小激动呢!到这里大家跟着做出来,喝杯茶,下方留个言啥的岂不美哉!

双主双从读写分离介绍

上边我们介绍了一主一从实现读写分离,但是如果主库或者从库宕机就无法正常提供写和读的服务。我们使用双主双从,master1和master2为主服务器,都有对应的slave,当Master1宕机时Master2负责写请求,M1和M2互为备机,提高MySQL可用性,架构图如下

集群规划

编号

角色

IP地址

主机名

1

Master1

192.168.11.201

stt201

2

Slave1

192.168.11.202

stt202

3

Master2

192.168.11.203

stt203

4

Slave2

192.168.11.204

stt204

双主双从配置Master1配置文件
启动二进制日志log-bin=mysql-bin设置需要复制的数据库,这里设置了上边不复制项就可以不设置binlog-do-db=mycatdb步进值auto_imcrement。一般有n台主MySQL就填nauto_increment_increment=2在作为从数据库时,有写入操作也要更新二进制文件log-slave-updates=1
Master2配置
启动二进制日志log-bin=mysql-bin设置需要复制的数据库,这里设置了上边不复制项就可以不设置binlog-do-db=mycatdb步进值auto_imcrement。一般有n台主MySQL就填nauto_increment_increment=2ServerIDserver-id=2ServerIDserver-id=4#启用中继日志relay-log=mysql-relay
启动前提

先删除mycatdb库(为什么呢?)

dropdatabasemycatdb;

主从都重启mysql服务

systemctlrestartmysqldsystemctlstatusmysqld

在两台主服务器上创建并授权slave用户,我们上边创建过的

--查看是否有用户存在mysqlusemysql;mysqlselectuserfromuser;

取消主从关系,在slave上运行

mysqlstopslave;mysqlrestartmaster;
配置主从和主主互备并且验证同步
--主从和主主互备与我们一主一从那个命令一样,不同的是我们需要在主节点运行一遍下方命令实现主主互备所以我们先查看Master的信息changemastertomaster_host='主IP',master_user='上方我们创建的用户',master_password='上方密码',master_log_file='File',master_log_pos=Position;--启动从服务startslave;--查看状态,IO和SQL是否都为YESshowslavestatus\G;--在主服务器做写入操作,参考一主一从
贴出过程大家可供参考

Mycat配置读写分离修改文件
?xmlversion="1.0"?!DOCTYPEmycat:schemaSYSTEM""mycat:schemaxmlns:mycat=""!--dataNode配置数据库地址,对应下方dataNode标签name属性值--schemaname="MYCATDB"checkSQLschema="false"sqlMaxLimit="100"dataNode="dn1"/schema!--数据节点name:自定义唯一dataHost:数据主机database:物理数据库名,我这里有数据库名为mycatdb--dataNodename="dn1"dataHost="host1"database="mycatdb"/!--数据主机name:和datanode的dataHost一致balance:配置读写分离类型,单主单从配置3,双主双从配置1--dataHostname="host1"maxCon="1000"minCon="10"balance="1"writeType="0"dbType="mysql"dbDriver="native"switchType="1"slaveThreshold="100"!--心跳机制,检测数据库是否可用--heartbeatselectuser()/heartbeat!--写主机目前只配置一个url:配置数据库的ip:端口--writeHosthost="hostM1"url="192.168.11.201:3306"user="root"password="123456"!--配置读主机--readHosthost="hostS1"url="192.168.11.202:3306"user="root"password="123456"//writeHostwriteHosthost="hostM2"url="192.168.11.203:3306"user="root"password="123456"!--配置读主机--readHosthost="hostS2"url="192.168.11.204:3306"user="root"password="123456"//writeHost/dataHost/mycat:schema
验证读写分离

配置完mycat之后启动和登录mycat,下图前四个窗口是mysql窗口,在第一个窗口添加数据,以hostname为区分,数据成功添加并同步成功,在mycat窗口查询大家看到输出的数据时stt202和stt204这两个主机正是从服务器!

验证抗风险性

我们模拟一下mysql宕机,停止stt201服务器上mysql服务,通过mycat插入数据,通过select语句查询数据发现只有stt203和stt204上有数据,stt202是stt201的从服务器所以没有同步数据,但是stt203和stt204两台主机仍然可以为我们提供正常的数据服务

故障恢复

这是运维大佬正在召唤师峡谷大展异彩,突然接到报警书数据库崩了,没有什么问题是重启解决不了了,我们现在重启一下stt201上的mysql服务,在使用mycat插入数据,发现四台服务器上数据一致,包括之前stt201宕机时插入的id为6的数据也在,是因为我们有主主互备,并且stt202是stt201的从服务。

总结

mysql单机会出现单点故障问题,数据库宕机将造成数据无法读写,而且如果网站并发高,一个数据库实例无法支撑庞大的业务流量,我们项目中一般是读比写多,所以我们可以使用mysql的读写分离

mysql读写分离这里演示了两种一主一从和双主双从,如果大家后边的n主n从可以参考配置修改即可,读写分离需要保证主库和从库数据一致这个可以依赖之后自带的主从复制实现

一主一从模式存在的问题是如果主库或者从库宕机也无法实现正常的服务,所以我们在生产中会使用多主多从方式都提供备用机提高mysql的可用性

mysql的主从复制可以单独实现,但是如果要实现读写分离则需要使用数据库中间件,我们这里使用的是Mycat

Mycat我们需要安装和配置,以及一些重要配置参数大家要心里有数

这篇文章我们先说一下基于Mycat实现Mysql读写分离,下一篇安排MySQL分表分库

最新文章