Mycat 是数据库中间件, 就是介于数据库与应用之间, 进行数据处理与交互的中间服 务由于前面讲的对数据进行分片处理之后, 从原有的一个库, 被切分为多个分片数据库, 所有的分片数据库集 群构成了整个完整的数据库存储
如下图:
如上图所表示, 数据被分到多个分片数据库后, 应用如果需要读取数据, 就要需要处理多个数据源的数据
如果没有数据库中间件, 那么应用将直接面对分片集群, 数据源切换事务处理数据聚合都需要应用直接处 理, 原本该是专注于业务的应用, 将会花大量的工作来处理分片后的问题, 最重要的是每个应用处理将是完全的 重复造轮子
所以有了数据库中间件, 应用只需要集中与业务处理, 大量的通用的数据聚合, 事务, 数据源切换都由中间 件来处理, 中间件的性能与处理能力将直接决定应用的读写性能, 所以一款好的数据库中间件至关重要
第一部 MyCat 的环境搭建
首先去官网下载 MyCat, 官网地址为: dl.mycat.io
注意必须下载发行版, 也就是说带有 RELEASE 字眼的就是发行版, BETA 是测试版选择 windows 版本来学习即可
我们主要关注的是 MyCat 的 conf 目录如下图:
我们打开 schema.xml 文件中看一下里面的配置都是些什么意思: 配置文件如下:
- <?xml version="1.0" ?>
- <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
- <mycat:schema xmlns:mycat="http://io.mycat/">
- <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
- <!-- auto sharding by id (long) -->
- <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"
- />
- <!-- global table is auto cloned to all defined data nodes ,so can join
- with any table whose sharding node is in the same data node -->
- <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3"
- />
- <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />
- <!-- random sharding using mod sharind rule -->
- <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
- rule="mod-long" />
- <!-- <table name="dual" primaryKey="ID" dataNode="dnx,dnoracle2" type="global"
- needAddLimit="false"/>
- <table name="worker" primaryKey="ID" dataNode="jdbc_dn1,jdbc_dn2,jdbc_dn3"
- rule="mod-long" />
- -->
- <table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"
- />
- <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile">
- <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id">
- <childTable name="order_items" joinKey="order_id" parentKey="id" />
- </childTable>
- <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
- parentKey="id" />
- </table>
- <!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
- />
- -->
- </schema>
- <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
- />
- -->
- <dataNode name="dn1" dataHost="localhost1" database="db1" />
- <dataNode name="dn2" dataHost="localhost1" database="db2" />
- <dataNode name="dn3" dataHost="localhost1" database="db3" />
- <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
- <dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" />
- <dataNode name="jdbc_dn2" dataHost="jdbchost" database="db2" />
- <dataNode name="jdbc_dn3" dataHost="jdbchost" database="db3" />
- -->
- <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0"
- dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
- <heartbeat>
- select user()
- </heartbeat>
- <!-- can have multi write hosts -->
- <writeHost host="hostM1" url="localhost:3306" user="root" password="123456">
- <!-- can have multi read hosts -->
- <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx"
- />
- </writeHost>
- <writeHost host="hostS1" url="localhost:3316" user="root" password="123456"
- />
- <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/>
- -->
- </dataHost>
- <!-- <dataHost name="sequoiadb1" maxCon="1000" minCon="1" balance="0"
- dbType="sequoiadb" dbDriver="jdbc">
- <heartbeat> </heartbeat>
- <writeHost host="hostM1" url="sequoiadb://1426587161.dbaas.sequoialab.net:11920/SAMPLE" user="jifeng" password="jifeng"></writeHost>
- </dataHost>
- <dataHost name="oracle1" maxCon="1000" minCon="1" balance="0" writeType="0" dbType="oracle" dbDriver="jdbc"> <heartbeat>select 1 from dual</heartbeat>
- <connectionInitSql>alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'</connectionInitSql>
- <writeHost host="hostM1" url="jdbc:oracle:thin:@127.0.0.1:1521:nange" user="base" password="123456"> </writeHost> </dataHost>
- <dataHost name="jdbchost" maxCon="1000" minCon="1" balance="0" writeType="0" dbType="mongodb" dbDriver="jdbc">
- <heartbeat>select user()</heartbeat>
- <writeHost host="hostM" url="mongodb://192.168.0.99/test" user="admin" password="123456"></writeHost> </dataHost>
- <dataHost name="sparksql" maxCon="1000" minCon="1" balance="0" dbType="spark" dbDriver="jdbc">
- <heartbeat> </heartbeat>
- <writeHost host="hostM1" url="jdbc:hive2://feng01:10000" user="jifeng" password="jifeng"></writeHost> </dataHost> -->
- <!-- <dataHost name="jdbchost" maxCon="1000" minCon="10" balance="0" dbType="mysql"
- dbDriver="jdbc"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1"
- url="jdbc:mysql://localhost:3306" user="root" password="123456"> </writeHost>
- </dataHost> -->
- </mycat:schema>
schema 标签用于定义 MyCat 实例中的逻辑库, MyCat 可以有多个逻辑库, 每个逻辑库都有自己的相关配 置可以使用 schema 标签来划分这些不同的逻辑库 如果不配置 schema 标签, 所有的表配置, 会属于同一个默认的逻辑库
对于我们开发人员来说, 我们知道连接到 mycat 的逻辑库, 后面拖着多少个 MySQL 我们不管的, 我们只需要连接到 MyCat 这个逻辑库, 对于后面的分库分表, MyCat 给我们屏蔽了分库分表的复杂性
table 标签定义了 MyCat 中的逻辑表, 所有需要拆分的表都需要在这个标签中定义
table 标签里面的子标签 childTabel 表示这个表跟父 table 分在一起, 不会被拆散, 也就是前面所说的分库分表之前, 要考虑好表的关联, 不然否则就面临跨库 Join 连接问题
如下代码:
- <table name="customer" primaryKey="ID" dataNode="dn1,dn2"
- rule="sharding-by-intfile">
- <childTable name="orders" primaryKey="ID" joinKey="customer_id"
- parentKey="id">
- <childTable name="order_items" joinKey="order_id"
- parentKey="id" />
- </childTable>
- <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
- parentKey="id" />
- </table>
table 中的 type 属性的 global 表示该表为全局表即前面所提到每一个节点可以读到这个表, 这对是否在分库分表中的 join 查询很关键而且这属性表示不会进行分片, 即全局表使用, 每个节点都有代码如下:
<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />
table 中的 dataNode 属性表示你要分片, 要分到那几个节点上去, rule 代表着分库分表的规则他的分片分表规则在 rule.xml 文件中, 你可以在 Table 标签的 rule 属性设置复合
自己的分片分表规则, 都在 rule.xml 中对应着如下图:
<dataNode > 标签, 标签中的 name 属性表示节点的名字 dataHost 属性表示对应 MySQL 的数据库连接, database 属性表示 Mysql 数据库名, 代码如下:
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataHost > 标签节点表示对应 MySQL 的数据库连接对应配置, 什么最大连接数, 最小连接数之类的属性
<dataHost > 标签中的子标签 < hearbeat > 表示存活检测,
<dataHost > 标签中的子标签 < writeHost > 和 < readHost > 表示 MySQL 中的读写分离, 而 < writeHost > 子标签中还有 < readHost > 子标签, 表示写操作的数据库还要承担一部分读库的压力
代码如下:
- <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
- writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
- <heartbeat>select user()</heartbeat>
- <!-- can have multi write hosts -->
- <writeHost host="hostM1" url="localhost:3306" user="root"
- password="123456">
- <!-- can have multi read hosts -->
- <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
- </writeHost>
- <writeHost host="hostS1" url="localhost:3316" user="root"
- password="123456" />
- <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
- </dataHost>
下面进行读写分离的演示:
第一步先注释 schma 里面的配置如下图:
接着在修改 < dataNode>,<dataHost > 节点信息, 详细信息在图中说明如下图:
接着再还要修改 mycat 中 server.xml 文件, 我这里没有使用 zookeeper 所以要把 zookeeper 协调切换关闭因为我们只是在本地玩, 如下图:
接着在继续修改 server.xml 文件如下图:
接着就是启动了, 启动之前要进行环境变量设置如下:
接着就是设置一起启动参数了, 在 startup_newrap.bat 文件中修改如下图:
接着就是启动了, 如下:
接着就是用图形化工具连接 MyCat 了如下图:
接着自己在图形化界面中修改数据库, 这里就不演示了如下:
接着 mycat 进行分库分表演示:
注意一定要在每一个 mysql 中建立好 tabel 标签对应的 travelrecord 表, 而表中必须要有 id 这属性,
如下图:
注意一定要在每一个 mysql 中建立好 tabel 标签对应的 travelrecord 表, 而表中必须要有 id 这属性, 因为上面的分库分表策略是根据 id 分的, 在 rule.xml 中找到分表策略如下:
在根据 rang-long 在 rule.xml 找到对应的 function, 如下图:
在找到 autoparitition-long.txt 文件, 看到如下分库分表了, 如下图:
然后在分别对应修改 dataNode 和 dataHost 标签, 如下图:
最后进行分库分表测试
比如 490M=4900000 分到第 0 个节点, 在 mycat 总设置, 如下图:
接着去查看第 0 个节点会有一条数据分到这里, 其他节点没有
如果使用上面的分库分表策略不能超过范 autoparitition-long.txt 里面配置的范围的
其他的分配策略, 还可以用 CRC32slot 策略类似于 redis 集群中的 Slot, 如下:
还可以用 rang-mod 求模来分, 如下:
然后找 partition-range-mod.txt, 可以具体, 如下:
其他就不演示了
来源: https://www.cnblogs.com/huangjuncong/p/8596017.html