在如今的互联时代,数据已成为业发展的个重要向标,对于海量数据的处理成为论是技术还是业务发展中都不可回避的重要问题。数据量越来越,对性能要求越来越;对于量数据的存储的现在主要分为两种数据库:关系型数据库和NoSQL数据库。
传统数据库天然存在着单机单库瓶颈、难于扩展;NoSQL产品的出现虽然弥补了传统数据库的性能问题,但是不能完全替代传统数据库。
随着业务量的扩张和数据量的激增,系统负载很的情况下,就必须对数据进分割。数据被分到多个分数据库后,应如果需要读取数据,就要需要处理多个数据源的数据。
如果没有数据库中间件(eg:MyCat),那么应将直接对分集群,数据源切换、事务处理、数据聚合都需要应直接处理,原本该是专注于业务的应,将会花量的作来处理分后的问题。
MyCat是什么?对于DBA来说:
MyCat就是MySqlServer增强版的存储引擎。
对于软件工程师来说:
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部分源码如下:
privatefinalConcurrentHashMapstring,span=""ConQueueitems=newConcurrentHashMap();
publicConQueuegetSchemaConQueue(Stringschema)
{
//根据schema获取当前切的连接
ConQueuequeue=items.get(schema);
if(queue==null){//如果没有可连接,则新建
ConQueuenewQueue=newConQueue();
queue=items.putIfAbsent(schema,newQueue);
return(queue==null)?newQueue:queue;
}
returnqueue;
}
publicBackendConnectiontryTakeCon(finalStringschema,
booleanautoCommit)
{
finalConQueuequeue=items.get(schema);
//尝试获取个可连接
BackendConnectioncon=tryTakeCon(queue,autoCommit);
if(con!=null){
returncon;
}
如果没有可连接或者不是动模式,为了效且充分利数据库连接,当某个户会话需要个动提交到分dn1(对应db1)的SQL连接的时候,连接池先找是否有db1上的可连接。
如果有,看是否有动提交模式的连接,找到就返回,否则返回db1上的动提交模式的连接,若没有db1的可连接,则随机返回个其他db对应的可连接,若没有可连接,并且连接池还没达到上限,则创建个新连接并返回。
MyCat网络模型NIO/AIO:·SocketConnector发起连接请求类,如MyCAT与MySQL数据库的连接,都是由MyCAT主动发起连接请求。
·SocketAcceptor接收连接请求类,如MyCAT启动和分别侦听管理员和应程序的连接请求。
·SocketWR读写操作类,SocketConnector和SocketAcceptor只负责socket建,当socket连接建后进字节的读写操作则由SocketWR来完成。在MyCAT中,NIO采多Reactor模式,内部维护个Selector选择器分别处理不同是事件。例如NIOConnector类-selector事件选择器。
·connectQueue需要建连接的对象,临时放在这个队列
·reactorPool当连接建后,从reactorPool中分配个NIOReactor,处理Read和Write事件
connect源码解读:
privatevoidconnect(Selectorselector){
AbstractConnectionc=null;
while((c=connectQueue.poll())!=null){
try{
SocketChannelchannel=(SocketChannel)c.getChannel();
channel.register(selector,SelectionKey.OP_CONNECT,c);
channel.connect(newInetSocketAddress(c.host,c.port));
}catch(Exceptione){
LOGGER.error("error:",e);
c.close(e.toString());
}
}
//处理connect事件,交给reactor处理
privatevoidfinishConnect(SelectionKeykey,Objectatt){
BackendAIOConnectionc=(BackendAIOConnection)att;
try{
if(finishConnect(c,(SocketChannel)c.channel)){
clearSelectionKey(key);
c.setId(ID_GENERATOR.getId());
NIOProcessorprocessor=
MycatServer.getInstance().nextProcessor();
c.setProcessor(processor);
NIOReactorreactor=reactorPool.getNextReactor();
reactor.postRegister(c);
c.onConnectfinish();
}
}catch(Exceptione){
clearSelectionKey(key);
LOGGER.error("error:",e);
c.close(e.toString());
c.onConnectFailed(e);
}
}
1、判断connectQueue中是否新的连接请求。
2、建个SocketChannel。
3、在selector中进行注册OP_CONNECT。
4、发起SocketChannel.connect()操作。
MyCat读写分离实战:在些型站业务场景中,单台数据库提供的并发量已经法满业务需求;为了提供数据库的并发能和负载能,般通过读写分离来实现。
当我们的数据库实现读写分离的时候,在应中需要对数据源进切换,MyCat能够帮我们更好的实现数据源的动态切换,也就是应程序只需要连接MyCat中间件,动帮我们读取读写的数据库。
未采用MyCat中间件项目架构: