当前位置: 当前位置:首页 >IT科技类资讯 >MySQL读写分离神器:MyCat浅析 正文

MySQL读写分离神器:MyCat浅析

2025-11-04 23:34:47 来源:多维IT资讯作者:人工智能 点击:120次

前言:

在如今的写分互联⽹时代,⼤数据已成为⾏业发展的离神⼀个重要⻛向标,⽽对于海量数据的器M浅析处理⼜成为⽆论是技术还是业务发展中都不可回避的重要问题。数据量越来越⼤,写分对性能要求越来越⾼;对于⼤量数据的离神存储的现在主要分为两种数据库:关系型数据库和 NoSQL 数据库。

传统数据库天然存在着单机单库瓶颈、器M浅析难于扩展;⽽ NoSQL 产品的写分出现虽然弥补了传统数据库的性能问题 ,但是不能完全替代传统数据库。

随着业务量的离神扩张和数据量的激增,系统负载很⼤的器M浅析情况下,就必须对数据进⾏分割。写分数据被分到多个分⽚数据库后,离神应⽤如果需要读取数据,器M浅析就要需要处理多个数据源的写分数据。

如果没有数据库中间件(eg:MyCat) ,离神那么应⽤将直接⾯对分⽚集群,数据源切换、器M浅析事务处理、数据聚合都需要应⽤直接处理,原本该是专注于业务的WordPress模板应⽤,将会花⼤量的⼯作来处理分⽚后的问题。

MyCat 是什么?对于 DBA 来说:

MyCat 就是 MySql Server 增强版的存储引擎。

对于软件工程师来说:

MyCat 就是数据库服务器,可以像操作数据库那样操作MyCat。

对于架构师来说:

MyCat 是⼀个强⼤的数据库中间件,不仅可以⽤作读写分离以及分库分表,甚⾄可⽤于多租户应⽤开发、云平台基础设施,让架构具备很强的灵活性和适应性。

MyCat的应用场景:

1、⽀持读写分离、主从切换;

2、垂直分库、⽔平分表;

3、多租户应⽤,如果每个应⽤⼀个库,所有的应该只需连接 Mycat,实现多租户;

4、报表系统,处理⼤规模报表的统计。数据被切分到不同的服务器租用分⽚数据库上,当应⽤需要读取数据时,中间件 mycat 就可以帮助开发⼈员进⾏数据聚合、事务、数据源切换等处理,让开发⼈员更加专注于业务开发。

MyCat 基本概念介绍:

逻辑库(schema):

对实际应⽤⽽⾔,业务开发⼈员并不需要知道中间件的存在,所以 mycat 中间件⼀个或多个数据库集群构成的逻辑库。

逻辑表(table):

对应⽤来说,读写数据的表就是逻辑表。逻辑表是对应逻辑库存在的。

分片表:

指原有很⼤的数据表需要切分到不同数据库上的表。

非分片表 :

针对分⽚表来说,原则上是不需要切分的表。

E-R 表:

基于关系型数据库中实体关系模型,⼦表和⽗表记录存放在同⼀个分⽚上,通过表分组保证数据 join 不会出现跨库操作。

全局表:

类似字典的表;变动不频繁、数据量总体变化不是很⼤、规模不超过10w 的服务器托管表。

分片节点(dataNode):

⼀个⼤表被分到不同的分⽚数据库上⾯,每个表分⽚所在的数据库就是分⽚节点

节点主机(dataHost):

⼀个或多个分⽚节点(dataNode)所在的机器就是节点主机

分片规则(rule):

⼀个⼤表被分成若⼲个分⽚表,就需要⼀定的规则,这样按照某种业务规则把数据分到某个分⽚的规则就是分⽚规则。

MyCat连接池解读:

MyCat通过共享⼀个MySQL上的所有物理连接,并结合连接状态同步的特性,MyCat的连接池做到了最佳的吞吐量,也在⼀定程度上提升了整个系统的并发⽀撑能⼒。

其中ConMap 是存放连接池对象重要的数据结构,ConMap部分源码如下:

private final ConcurrentHashMap

public ConQueue getSchemaConQueue(String schema)

{

// 根据schema 获取当前切⽚的连接

ConQueue queue = items.get(schema);

if (queue == null) { // 如果没有可⽤连接,则新建

ConQueue newQueue = new ConQueue();

queue = items.putIfAbsent(schema,newQueue);

return (queue == null) ? newQueue: queue;

}

return queue;

}

public BackendConnection tryTakeCon(final String schema,

boolean autoCommit)

{

final ConQueue queue = items.get(schema);

// 尝试获取⼀个可⽤连接

BackendConnection con = tryTakeCon(queue,autoCommit);

if (con != null) {

return con;

}

如果没有可⽤连接或者不是⾃动模式,为了⾼效且充分利⽤数据库连接,当某个⽤户会话需要⼀个⾃动提交到分⽚ dn1(对应db1)的 SQL 连接的时候,连接池⾸先找是否有 db1 上的可⽤连接。

如果有,看是否有⾃动提交模式的连接,找到就返回,否则返回 db1 上的⼿动提交模式的连接,若没有db1 的可⽤连接,则随机返回⼀个其他 db 对应的可⽤连接,若没有可⽤连接,并且连接池还没达到上限,则创建⼀个新连接并返回。

MyCat网络模型NIO/AIO:

SocketConnector 发起连接请求类,如 MyCAT 与 MySQL 数据库的连接,都是由 MyCAT 主动发起连接请求。SocketAcceptor 接收连接请求类,如 MyCAT 启动 9066 和 8066 分别侦听管理员和应⽤程序的连接请求。SocketWR 读写操作类,SocketConnector 和 SocketAcceptor 只负责 socket 建⽴,当 socket 连接建⽴后进⾏字节的读写操作则由SocketWR 来完成。在 MyCAT 中,NIO 采⽤多 Reactor 模式,内部维护⼀个 Selector 选择器分别处理不同是事件。例如 NIOConnector 类- selector 事件选择器。connectQueue 需要建⽴连接的对象,临时放在这个队列⾥

reactorPool 当连接建⽴后,从 reactorPool 中分配⼀个 NIOReactor,处理 Read和 Write 事件

connect 源码解读:

private void connect(Selector selector) {

AbstractConnection c = null;

while ((c = connectQueue.poll()) != null) {

try {

SocketChannel channel = (SocketChannel) c.getChannel();

channel.register(selector, SelectionKey.OP_CONNECT, c);

channel.connect(new InetSocketAddress(c.host, c.port));

} catch (Exception e) {

LOGGER.error("error:",e);

c.close(e.toString());

}

}

// 处理connect事件,交给reactor处理

private void finishConnect(SelectionKey key, Object att) {

BackendAIOConnection c = (BackendAIOConnection) att;

try {

if (finishConnect(c, (SocketChannel) c.channel)) {

clearSelectionKey(key);

c.setId(ID_GENERATOR.getId());

NIOProcessor processor =

MycatServer.getInstance().nextProcessor();

c.setProcessor(processor);

NIOReactor reactor = reactorPool.getNextReactor();

reactor.postRegister(c);

c.onConnectfinish();

}

} catch (Exception e) {

clearSelectionKey(key);

LOGGER.error("error:",e);

c.close(e.toString());

c.onConnectFailed(e);

}

}判断 connectQueue 中是否新的连接请求。建⽴⼀个 SocketChannel。在 selector 中进行注册 OP_CONNECT。发起 SocketChannel.connect()操作。

MyCat读写分离实战:

在⼀些⼤型⽹站业务场景中,单台数据库提供的并发量已经⽆法满⾜业务需求;为了提供数据库的并发能⼒和负载能⼒,⼀般通过读写分离来实现。

当我们的数据库实现读写分离的时候,在应⽤中需要对数据源进⾏切换, MyCat能够帮我们更好的实现数据源的动态切换,也就是应⽤程序只需要连接MyCat中间件,⾃动帮我们读取读写的数据库。

未采用MyCat中间件项目架构:

采用MyCat中间件架构:

两者对比差异:

图⼀需要在应⽤程序中配置多个数据源,通过不同的业务需求动态切换多个数据源。⽽通过MyCat以后,应⽤程序只需要连接MyCat作为数据源,⽅便拓展,对现有的程序不影响。

搭建主从:

jdk 准备:jdk1.7 往上版本mysql 准备,两台mysql服务,⼀台作为主库负责写⼊数据,⼀台是从库负责读数据MyCat 安装:MyCAT 有提供编译好的安装包,Mycat-server-xxxxx.linux.tar.gz 解压MyCat 相关⽬录说明:

bin 程序目录,进入到 bin目录:

Linux 下运⾏:./mycat console,⾸先要 chmod +x *conf ⽬录下存放配置⽂件,server.xml 是 Mycat 服务器参数调整和⽤户授权的配置⽂件,schema.xml 是逻辑库定义和表以及分⽚定义的配置⽂件,rule.xml是分⽚规则的配置⽂件,分⽚规则的具体⼀些参数信息单独存放为⽂件,version.txtlib ⽬录下主要存放 mycat 依赖的⼀些 jar ⽂件.⽇志存放在 logs/mycat.log 中,每天⼀个⽂件,⽇志的配置是在conf/log4j.xml 中,根据⾃⼰的需要,可以调整输出级别为 debug,debug 级别下,会输出更多的信息,⽅便排查问题。

配置schemal.xml逻辑库、逻辑表、分片:

"localhost1" maxCon="1000" minCon="10" balance="0"

writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">

writeHost>

readHost>

dataHost>

配置server.xml,主要配置连接MyCat的逻辑库、逻辑表访问权限的配置:

123456

TESTDB_YONG

TESTDB_YONG

-->

</user>

读写分离测试:

准备两台mysql服务器,⼀台配置为主数据库,负责数据的写⼊,⼀台配置为从数据库,负责数据的读取。数据库中间件MyCat通过shcemal.xml和server.xml配置两台数据库的读写。启动MyaCat服务,连接mycat实现读写分离数据源的切换:mysql -h127.0.0.1 -P8066 -uroot -p连接成功后,然后业务开发⼈员就可以像操作数据库那样使⽤ mycat,mycat 会根据配置的相关路由规则对数据进⾏分⽚存储和汇总。

通过MyCat插⼊数据:

insert into test(id, name) value (1,wyw);

Query OK, 1 row affected (0.05 sec)

查看主从数据库是否有数据,

访问数据:

select * from test where id = 1;

±-----+

| id |

±-----+

| 1 |

±-----+

1 rows in set (0.00 sec)

根据MyCat的运⾏⽇志查看读写分离的的实质:mycat/logs/mycat.log

查询指令在从服务器上:

作者:人工智能
------分隔线----------------------------
头条新闻
图片新闻
新闻排行榜