目录
Mycat介绍
Mycat是一个开源的分库分表中间件。Mycat的前身是阿里的Cobar。用于在多个数据库上的表通过mycat代理连接,实现一张或者多张分库或分表的大表数据根据定义的分片规则聚合展示。
学习Mycat主要是学习Mycat的配置文件的配置方法,配置文件中核心的配置文件有server.xml,schema.xml,rule.xml 。
server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<!-- 配置该属性的时候一定要保证mycat的字符集和mysql 的字符集是一致的 -->
<property name="charset">utf8</property>
<!-- 指定每次分配socker direct buffer 的值,默认是4096字节 -->
<property name="processorBufferChunk">4096</property>
<!-- 配置系统可用的线程数量,默认值为CPU核心 X 每个核心运行线程的数量 -->
<property name="processors">4</property>
<!-- 指定BufferPool 的计算比例 默认值为bufferChunkSize(4096)X processors X 1000 -->
<property name="processorBufferPool">100000000</property>
<!-- 用来控制ThreadLocalPool 分配Pool的比例大小,默认值为100 -->
<property name="processorBufferLocalPercent">100</property>
<!-- 用来指定Mycat全局序列类型,0为本地文件,1为数据库方式,2为时间戳列方式,默认使用本地文件方式,文件方式主要用于测试-->
<property name="sequnceHandlerType">0</property>
<!-- TCP 参数配置,mycat在每次建立前后端连接时候,都会使用这些参数初始化TCP属性,
详细可以查看Java API 文档:http://docs.oracle.com/javase/7/docs/api/net/StandardSocketOptions.html -->
<property name="frontSocketSoRcvbuf">1024*1024</property>
<property name="frontSocketSoSndbuf">4*1024*1024</property>
<property name="frontSocketNoDelay">1</property>
<property name="backSocketSoRcvbuf">4*1024*1024</property>
<property name="backSocketSoSndbuf">1024*1024</property>
<property name="backSocketNoDelay">1</property>
<!-- mysql 连接相关配置 -->
<!--指定mysql协议中的报文头长度,默认4个字节-->
<property name="packetHeaderSize">4</property>
<!-- 配置可以携带的数据量最大值,默认16M-->
<property name="maxPacketSize">1024*1024*16</property>
<!-- <property name="idleTimeout">1024*1024*16</property> 指定连接的空闲时间超时长度,如果某个连接空闲时间超过该值,则将连接关闭并回收,单位为毫秒,默认值为30分钟-->
<!-- <property name="txIsolation">3</property> 初始化前端连接事务的隔离级别有:
READ_UNCOMMITTED=1
READ_COMMITTED=2
REPEATED_READ=3
SERIALIZABLE=4
默认为3-->
<!-- <property name="sqlExecuteTimeout">3</property>执行sql超时时间,默认为300秒-->
<!-- 心跳属性配置 -->
<!-- <property name="processorCheckPeriod">1000</property>清理前后端空闲、超时、关闭连接的时间间隔,单位为毫秒,默认为1秒-->
<!-- <property name="dataNodeIdleCheckPeriod">300*1000</property>对后端连接进行空闲,超时检查的时间间隔,单位为毫秒,默认为300秒-->
<!-- <property name="dataNodeHeartbeatPeriod">10*1000</property>对后端所有读写库发起心跳的间隔时间,单位为毫秒,默认为10秒-->
<!-- 服务相关属性 -->
<!-- <property name="bindIp">0.0.0.0</property>mycat服务监听的ip地址,默认为0.0.0.0-->
<!-- <property name="serverPort">8066</property>定义mycat使用的端口,默认值为8066-->
<!-- <property name="managerPort">9066</property>定义mycat管理的端口,默认值为9066-->
<!-- 分布式事务开关属性 -->
<!-- <property name="handleDistributedTransactions">0</property>0为不过滤分布式事务,1过滤分布式事务,2不过滤分布式事务,但是记录分布式事务日志。主要用户是否允许跨库事务。mycat 1.6版本开始,支持此属性-->
<!-- <property name="useOffHeapForMerge">1</property>配置是否启用非堆内存跨分片结果集,1为开启,0为关闭,mycat1.6开始支持该属性-->
<!-- 全局表一致性检测 -->
<property name="useGlobleTableCheck">0</property> <!--通过添加_MYCAT_OP_TIME字段来进行一致性检测,为BIGINT类型 1为开启全加班一致性检测、0为关闭 -->
<property name="useSqlStat">0</property> <!-- 1为开启实时统计、0为关闭 -->
<!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
<!-- <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
<!--
<property name="processors">1</property>
<property name="processorExecutor">32</property>
-->
<!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
<property name="processorBufferPoolType">0</property>
<!--默认是65535 64K 用于sql解析时最大文本长度 -->
<!--<property name="maxStringLiteralLength">65535</property>-->
<!--<property name="processorExecutor">16</property>-->
<!--
<property name="serverPort">8066</property> <property name="managerPort">9066</property>
<property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
<!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
<property name="handleDistributedTransactions">0</property>
<!--单位为m-->
<property name="memoryPageSize">1m</property>
<!--单位为k-->
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!--单位为m-->
<property name="systemReserveMemorySize">384m</property>
<!--是否采用zookeeper协调切换 -->
<property name="useZKSwitch">true</property>
</system>
<!-- 全局SQL防火墙设置 -->
<!--
<firewall>
<whitehost>
<host host="127.0.0.1" user="mycat"/>
<host host="127.0.0.2" user="mycat"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>
-->
<!-- 定义登录mycat对的用户权限 -->
<user name="root">
<property name="password">123456</property>
<!-- 若要访问TESTDB 必须先在server.xml 中定义,否则无法访问TESTDB-->
<property name="schemas">TESTDB</property>
<!-- 配置是否允许只读 -->
<property name="readOnly">true</property>
<!-- 定义限制前端整体的连接数,如果其值为0,或者不设置,则表示不限制连接数量 -->
<property name="benchmark">11111</property>
<!-- 设置是否开启密码加密功能,默认为0不开启加密,为1则表示开启加密 -->
<property name="usingDecrypt">1</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
</mycat:server>
schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 数据库配置,与server.xml中的数据库对应 -->
<!--
name: 逻辑数据库名,与server.xml中的schema对应
checkSQLschema: 数据库前缀相关设置
sqlMaxLimit: select 时默认的limit,避免查询全表,如果没有加上limit语句,MyCat也会自动的加上所对应的值。
-->
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- Table标签: 定义了MyCat中的逻辑表,所有需要拆分的表都需要在这个标签中定义。-->
<!-- name属性:定义逻辑表的表名,这个名字就如同我在数据库中执行create table命令指定的名字一样,同个schema标签中定义的名字必须唯一 -->
<!-- dataNode属性:定义这个逻辑表所属的dataNode, 该属性的值需要和dataNode标签中name属性的值相互对应-->
<!-- rule属性:用于指定逻辑表要使用的规则名字,规则名字在rule.xml中定义,必须与tableRule标签中name属性属性值对应。 -->
<!-- primaryKey属性:该逻辑表对应真实表的主键 -->
<!-- type属性:该属性定义了逻辑表的类型,目前逻辑表只有“全局表”和”普通表”两种类型。对应的配置:全局表:global。普通表:不指定该值为globla的所有表 -->
<!-- autoIncrement属性: MySQL对非自增长主键,使用last_insert_id()是不会返回结果的,只会返回0。所以,
只有定义了自增长主键的表才可以用last_insert_id()返回主键值。mycat目前提供了自增长主键功能,但是
如果对应的mysql节点上数据表,没有定义auto_increment,那么在mycat层调用last_insert_id()也是不会返回
结果的。由于insert操作的时候没有带入分片键,mycat会先取下这个表对应的全局序列,然后赋值给分片键。
这样才能正常的插入到数据库中,最后使用last_insert_id()才会返回插入的分片键值。如果要使用这个功能最
好配合使用数据库模式的全局序列。使用autoIncrement=“true” 指定这个表有使用自增长主键,这样mycat才会
不抛出分片键找不到的异常。使用autoIncrement=“false” 来禁用这个功能,当然你也可以直接删除掉这个属性。
默认就是禁用的。 -->
<!-- needAddLimit属性:指定表是否需要自动的在每个语句后面加上limit限制。这个属性默认为true,你也可以设置成false`禁用掉默认行为。 -->
<table name="user" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="mod-long"/>
<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>
</schema>
<!-- 分片配置 -->
<!-- dataNode 标签定义了MyCat中的数据节点,即数据分片 -->
<!-- name属性:定义数据节点的名字,这个名字需要是唯一的,我们需要在table标签上应用这个名字,来建立表与分片对应的关系。 -->
<!-- dataHost属性:是引用dataHost标签上定义的name属性。 -->
<!-- database属性:database是指数据库 -->
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />
<dataNode name="dn3" dataHost="localhost1" database="db3" />
<!-- 物理数据库配置 -->
<!-- name属性:唯一标识dataHost标签,供上层的标签使用 -->
<!-- maxCon属性:指定每个读写实例连接池的最大连接。-->
<!-- minCon属性:指定每个读写实例连接池的最小连接。-->
<!--
balance属性:负载均衡类型4种:
1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2. balance="1",所有读操作都随机的发送到readHost。全部的readHost与stand by writeHost参与select语句的负载均衡,
简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
3. balance="2",所有读操作都随机的在writeHost、readhost上分发。
4. balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
-->
<!-- dbType属性:指定后端连接的数据库类型,目前支持二进制的mysql协议,还有其他使用JDBC连接的数据库。例如:MongoDB、Oracle、Spark等。 -->
<!--
writeType属性:负载均衡类型。
0:所有的写操作发送到配置的第一个writeHost,第一个挂了切换到第二个。切换记录在文件dnindex.properties
1:所有的写操作都随机的发送到配置的writeHost,1.5以后版本废弃不推荐。
-->
<!--
switchType属性
-1 不自动切换
1 默认值,自动切换
2 基于MySql主从同步的状态决定是否切换 : 心跳语句为show slave status
3 基于mysql galary cluster 的切换机制(适合集群)1.4.1心跳语句为 show status like 'wsrep%'
-->
<!--
dbDriver属性: 指定连接后段数据库使用的driver,目前可选的值有native和JDBC。使用native的话,因为这个值执行的
是二进制的mysql协议,所以可以使用mysql和maridb,其他类型的则需要使用JDBC驱动来支持。如果使用JDBC的话需
要符合JDBC4标准的驱动jar 放到mycat\lib目录下,并检查驱动jar包中包括如下目录结构文件 META-INF\services\java.sql.Driver。
在这个文件写上具体的driver类名,例如com.mysql.jdbc.Driver -->
<dataHost name="localhost1" maxCon="1000" minCon="10" slaveThreshold="100" balance="0" writeType="0" switchType="1" dbType="mysql" dbDriver="native">
<!--
heartbeat标签:这个标签内指明用于和后端数据库进行心跳检查的语句。
例如,MYSQL可以使用select user(),oracle可以使用select 1 from dual等。
这个标签还有一个connectionInitSql属性,主要是当使用Oracla数据库时,需要执行的初始化SQL语句就这个放到这里面来。
例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'
-->
<heartbeat>select user()</heartbeat>
<!--
writeHost标签、readHost标签:writeHost指定写实例、readHost指定读实例,组着这些读写实例来满足系统的要求。
在一个dataHost内可以定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,
那么这个writeHost绑定的所有readHost都将不可用。
-->
<!-- host属性:用于标识不同实例,一般writeHost我们使用*M1, readHost我们用*S1 -->
<writeHost host="hostM1" url="localhost:3306" user="root" password="root">
<readHost host="hostS1" url="localhost:3306" user="root" password="root"/>
</writeHost>
</dataHost>
</mycat:schema>
rule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<!--
规则:根据<columns>字段来进行分库分表,采用了基于范围的规则。
name 属性指定唯一的名字,用于标识不同的表规则内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。
columns 内指定要拆分的列名字。
algorithm 使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。
table 标签内使用。让逻辑表使用这个规则进行分片。
-->
<tableRule name="auto-sharding-long">
<rule>
<columns>org_id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
<tableRule name="mod-long">
<rule>
<columns>org_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<tableRule name="rule2">
<rule>
<columns>user_id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<!-- 枚举法:通过在配置文件中配置可能的枚举ID来配置分片规则 -->
<tableRule name="sharding-by-intfile">
<rule>
<columns>sharding_id</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<tableRule name="sharding-by-murmur">
<rule>
<columns>id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
<tableRule name="crc32slot">
<rule>
<columns>id</columns>
<algorithm>crc32slot</algorithm>
</rule>
</tableRule>
<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns>
<algorithm>partbymonth</algorithm>
</rule>
</tableRule>
<tableRule name="latest-month-calldate">
<rule>
<columns>calldate</columns>
<algorithm>latestMonth</algorithm>
</rule>
</tableRule>
<tableRule name="auto-sharding-rang-mod">
<rule>
<columns>id</columns>
<algorithm>rang-mod</algorithm>
</rule>
</tableRule>
<tableRule name="jch">
<rule>
<columns>id</columns>
<algorithm>jump-consistent-hash</algorithm>
</rule>
</tableRule>
<!--
一致性hash
name 指定算法的名字。
class 制定路由算法具体的类名字。
property 为具体算法需要用到的一些属性。
-->
<function name="murmur" class="io.mycat.route.function.PartitionByMurmurHash">
<!-- 默认是0 -->
<property name="seed">0</property>
<!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
<property name="count">2</property>
<!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 -->
<property name="virtualBucketTimes">160</property>
<!--节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,
以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->
<property name="weightMapFile">weightMapFile</property>
<!--用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,
会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 -->
<property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
</function>
<!-- 位循环冗余校验多项式算法 -->
<function name="crc32slot" class="io.mycat.route.function.PartitionByCRC32PreSlot">
<!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
<property name="count">2</property>
</function>
<!-- 枚举法 -->
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<!-- 所有节点配置都是从0开始的,0表示点1 -->
<property name="defaultNode">0</property>
</function>
<!-- 范围约定 -->
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
<!-- 在<property>标签中,autopartition-long.txt是主键范围的具体配置 -->
<property name="mapFile">autopartition-long.txt</property>
</function>
<!-- 求模法 -->
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- 与count(你的结点数)进行求模预算,此种在批量插入时需要切换数据源,数据不连续 -->
<property name="count">3</property>
</function>
<!-- 固定分片hash算法 -->
<function name="func1" class="io.mycat.route.function.PartitionByLong">
<!--
上面columns 标识将要分片的表字段,algorithm 分片函数,partitionCount 分片个数列表,partitionLength 分片范围列表
分区长度:默认为最大2^n=1024 ,即最大支持1024分区约束:
count,length两个数组的长度必须是一致的。
1024 = sum((count[i]*length[i])). count和length两个向量的点积恒等于1024
如果需要平均分配设置:平均分为8分片,partitionCount*partitionLength=1024
<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
<property name="partitionCount">8</property>
<property name="partitionLength">128</property>
</function>
-->
<property name="partitionCount">2,1</property>
<property name="partitionLength">256,512</property>
</function>
<!-- 按单月小时拆分 -->
<function name="latestMonth" class="io.mycat.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property>
</function>
<!-- 自然月分片 -->
<function name="partbymonth" class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2015-01-01</property>
</function>
<!-- 日期列分区法 配置中配置了开始日期,分区天数,即默认从开始日期算起,分隔10天一个分区 -->
<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2014-01-01</property>
<property name="sPartionDay">10</property>
</function>
<!-- 范围取模分片 -->
<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
<property name="mapFile">partition-range-mod.txt</property>
</function>
<!-- Google的一致性哈希算法 -->
<function name="jump-consistent-hash" class="io.mycat.route.function.PartitionByJumpConsistentHash">
<property name="totalBuckets">3</property>
</function>
</mycat:rule>